Merge last green PGO from inbound to central
authorMarco Bonardo <mbonardo@mozilla.com>
Sat, 25 Feb 2012 11:11:15 +0100
changeset 87705 ce20e9b47e9cd067254fff7d1f6099539dac80ae
parent 87643 7cb1e4c50145ebc5f14d4749fa241e9c2dcbb0f6 (current diff)
parent 87704 73a29259b8d8e8c47f094e349db67890768659ab (diff)
child 87706 6fbaf8cf139c21106a9d5c9a97ec931b8e0d606a
child 87724 b86f8295746190d92286ea0909bec768f5d307f2
push id22140
push usermak77@bonardo.net
push dateSat, 25 Feb 2012 10:12:06 +0000
treeherdermozilla-central@ce20e9b47e9c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone13.0a1
first release with
nightly linux32
ce20e9b47e9c / 13.0a1 / 20120225031723 / files
nightly linux64
ce20e9b47e9c / 13.0a1 / 20120225031723 / files
nightly mac
ce20e9b47e9c / 13.0a1 / 20120225031723 / files
nightly win32
ce20e9b47e9c / 13.0a1 / 20120225031723 / files
nightly win64
ce20e9b47e9c / 13.0a1 / 20120225031723 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last green PGO from inbound to central
browser/themes/pinstripe/livemark-item.png
browser/themes/winstripe/livemark-item-aero.png
browser/themes/winstripe/livemark-item.png
mobile/android/base/resources/layout/gecko_menu.xml
toolkit/components/places/tests/autocomplete/test_livemarks.js
toolkit/components/places/tests/chrome/test_329534.xul
toolkit/components/places/tests/unit/test_exclude_livemarks.js
toolkit/components/places/tests/unit/test_livemarkService_getLivemarkIdForFeedURI.js
--- a/accessible/src/base/Statistics.h
+++ b/accessible/src/base/Statistics.h
@@ -55,31 +55,31 @@ namespace statistics {
 
   /**
    * Report that ISimpleDOM* has been used.
    */
   inline void ISimpleDOMUsed()
   {
     static bool firstTime = true;
     if (firstTime) {
-      Telemetry::Accumulate(Telemetry::ISIMPLE_DOM_USAGE, 1);
+      Telemetry::Accumulate(Telemetry::A11Y_ISIMPLEDOM_USAGE, 1);
       firstTime = false;
     }
   }
 
   /**
    * Report that IAccessibleTable has been used.
    */
   inline void IAccessibleTableUsed()
-    { Telemetry::Accumulate(Telemetry::IACCESSIBLE_TABLE_USAGE, 1); }
+    { Telemetry::Accumulate(Telemetry::A11Y_IATABLE_USAGE, 1); }
 
   /**
    * Report that XForms accessibility has been instantiated.
    */
   inline void XFormsAccessibleUsed()
-    { Telemetry::Accumulate(Telemetry::XFORMS_ACCESSIBLE_USED, 1); }
+    { Telemetry::Accumulate(Telemetry::A11Y_XFORMS_USAGE, 1); }
 
 } // namespace statistics
 } // namespace a11y
 } // namespace mozilla
 
 #endif
 
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -131,17 +131,17 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
     kNoReqStates,
     eARIASelectable,
     eARIAReadonly
   },
   {
     "combobox",
     roles::COMBOBOX,
     kUseMapRole,
-    eHasValueMinMax,
+    eNoValue,
     eOpenCloseAction,
     eNoLiveAttr,
     states::COLLAPSED | states::HASPOPUP,
     eARIAAutoComplete,
     eARIAReadonly
   },
   {
     "dialog",
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -849,19 +849,20 @@ nsAccessible::ChildAtPoint(PRInt32 aX, P
   if (!foundFrame || !(content = foundFrame->GetContent()))
     return fallbackAnswer;
 
   // Get accessible for the node with the point or the first accessible in
   // the DOM parent chain.
   nsDocAccessible* contentDocAcc = GetAccService()->
     GetDocAccessible(content->OwnerDoc());
 
-  // contentDocAcc in some circumstances can be NULL
-  // See https://bugzilla.mozilla.org/show_bug.cgi?id=729861
-  NS_ENSURE_TRUE(contentDocAcc, fallbackAnswer);
+  // contentDocAcc in some circumstances can be NULL. See bug 729861
+  NS_ASSERTION(contentDocAcc, "could not get the document accessible");
+  if (!contentDocAcc)
+    return fallbackAnswer;
 
   nsAccessible* accessible = contentDocAcc->GetAccessibleOrContainer(content);
   if (!accessible)
     return fallbackAnswer;
 
   if (accessible == this) {
     // Manually walk through accessible children and see if the are within this
     // point. Skip offscreen or invisible accessibles. This takes care of cases
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1648,22 +1648,16 @@ function delayedStartup(isLoadingBlank, 
   }
 
   PlacesToolbarHelper.init();
 
   ctrlTab.readPref();
   gPrefService.addObserver(ctrlTab.prefName, ctrlTab, false);
   gPrefService.addObserver(allTabs.prefName, allTabs, false);
 
-  // Delayed initialization of the livemarks update timer.
-  // Livemark updates don't need to start until after bookmark UI
-  // such as the toolbar has initialized. Starting 5 seconds after
-  // delayedStartup in order to stagger this before the download manager starts.
-  setTimeout(function() PlacesUtils.livemarks.start(), 5000);
-
   // Initialize the download manager some time after the app starts so that
   // auto-resume downloads begin (such as after crashing or quitting with
   // active downloads) and speeds up the first-load of the download manager UI.
   // If the user manually opens the download manager before the timeout, the
   // downloads will start right away, and getting the service again won't hurt.
   setTimeout(function() {
     gDownloadMgr = Cc["@mozilla.org/download-manager;1"].
                    getService(Ci.nsIDownloadManager);
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -220,16 +220,17 @@ endif
                  browser_tab_dragdrop.js \
                  browser_tab_dragdrop2.js \
                  browser_tab_dragdrop2_frame1.xul \
                  browser_tabfocus.js \
                  browser_tabs_isActive.js \
                  browser_tabs_owner.js \
                  browser_urlbarCopying.js \
                  browser_urlbarEnter.js \
+                 browser_urlbarRevert.js \
                  browser_urlbarTrimURLs.js \
                  browser_urlHighlight.js \
                  browser_visibleFindSelection.js \
                  browser_visibleTabs.js \
                  browser_visibleTabs_contextMenu.js \
                  browser_visibleTabs_bookmarkAllPages.js \
                  browser_visibleTabs_bookmarkAllTabs.js \
                  browser_visibleTabs_tabPreview.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_urlbarRevert.js
@@ -0,0 +1,29 @@
+function test() {
+  waitForExplicitFinish();
+
+  let tab = gBrowser.addTab("http://example.com");
+  gBrowser.selectedTab = tab;
+
+  onLoad(function () {
+    let originalValue = gURLBar.value;
+
+    gBrowser.userTypedValue = "foobar";
+    gBrowser.selectedTab = gBrowser.tabs[0];
+    gBrowser.selectedTab = tab;
+    is(gURLBar.value, "foobar", "location bar displays typed value");
+
+    gURLBar.focus();
+    EventUtils.synthesizeKey("VK_ESCAPE", {});
+    is(gURLBar.value, originalValue, "ESC reverted the location bar value");
+
+    gBrowser.removeTab(tab);
+    finish();
+  });
+}
+
+function onLoad(callback) {
+  gBrowser.selectedBrowser.addEventListener("pageshow", function loadListener() {
+    gBrowser.selectedBrowser.removeEventListener("pageshow", loadListener, false);
+    executeSoon(callback);
+  });
+}
--- a/browser/components/distribution.js
+++ b/browser/components/distribution.js
@@ -40,16 +40,20 @@ EXPORTED_SYMBOLS = [ "DistributionCustom
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
   "distribution-customization-complete";
 
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+                                  "resource://gre/modules/PlacesUtils.jsm");
+
 function DistributionCustomizer() {
   let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
                getService(Ci.nsIProperties);
   let iniFile = dirSvc.get("XCurProcD", Ci.nsIFile);
   iniFile.append("distribution");
   iniFile.append("distribution.ini");
   if (iniFile.exists())
     this._iniFile = iniFile;
@@ -73,37 +77,16 @@ DistributionCustomizer.prototype = {
     }
     catch (e) {
       locale = "en-US";
     }
     this.__defineGetter__("_locale", function() locale);
     return this._locale;
   },
 
-  get _bmSvc() {
-    let svc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-              getService(Ci.nsINavBookmarksService);
-    this.__defineGetter__("_bmSvc", function() svc);
-    return this._bmSvc;
-  },
-
-  get _annoSvc() {
-    let svc = Cc["@mozilla.org/browser/annotation-service;1"].
-              getService(Ci.nsIAnnotationService);
-    this.__defineGetter__("_annoSvc", function() svc);
-    return this._annoSvc;
-  },
-
-  get _livemarkSvc() {
-    let svc = Cc["@mozilla.org/browser/livemark-service;2"].
-              getService(Ci.nsILivemarkService);
-    this.__defineGetter__("_livemarkSvc", function() svc);
-    return this._livemarkSvc;
-  },
-
   get _prefSvc() {
     let svc = Cc["@mozilla.org/preferences-service;1"].
               getService(Ci.nsIPrefService);
     this.__defineGetter__("_prefSvc", function() svc);
     return this._prefSvc;
   },
 
   get _prefs() {
@@ -162,73 +145,75 @@ DistributionCustomizer.prototype = {
       }
     }
 
     let prependIndex = 0;
     for (let iid = 0; iid <= maxItemId; iid++) {
       if (!items[iid])
         continue;
 
-      let index = this._bmSvc.DEFAULT_INDEX;
+      let index = PlacesUtils.bookmarks.DEFAULT_INDEX;
       let newId;
 
       switch (items[iid]["type"]) {
       case "default":
         break;
 
       case "folder":
         if (iid < defaultItemId)
           index = prependIndex++;
 
-        newId = this._bmSvc.createFolder(parentId, items[iid]["title"], index);
+        newId = PlacesUtils.bookmarks.createFolder(parentId,
+                                                   items[iid]["title"],
+                                                   index);
 
         this._parseBookmarksSection(newId, "BookmarksFolder-" +
                                     items[iid]["folderId"]);
 
         if (items[iid]["description"])
-          this._annoSvc.setItemAnnotation(newId,
-                                          "bookmarkProperties/description",
-                                          items[iid]["description"], 0,
-                                          this._annoSvc.EXPIRE_NEVER);
+          PlacesUtils.annotations.setItemAnnotation(newId,
+                                                    "bookmarkProperties/description",
+                                                    items[iid]["description"], 0,
+                                                    PlacesUtils.annotations.EXPIRE_NEVER);
 
         break;
 
       case "separator":
         if (iid < defaultItemId)
           index = prependIndex++;
-        this._bmSvc.insertSeparator(parentId, index);
+        PlacesUtils.bookmarks.insertSeparator(parentId, index);
         break;
 
       case "livemark":
         if (iid < defaultItemId)
           index = prependIndex++;
 
         // Don't bother updating the livemark contents on creation.
-        newId = this._livemarkSvc.
-          createLivemarkFolderOnly(parentId,
-                                   items[iid]["title"],
-                                   this._makeURI(items[iid]["siteLink"]),
-                                   this._makeURI(items[iid]["feedLink"]),
-                                   index);
+        PlacesUtils.livemarks.addLivemark({ title: items[iid]["title"]
+                                          , parentId: parentId
+                                          , index: index
+                                          , feedURI: this._makeURI(items[iid]["feedLink"])
+                                          , siteURI: this._makeURI(items[iid]["siteLink"])
+                                          });
         break;
 
       case "bookmark":
       default:
         if (iid < defaultItemId)
           index = prependIndex++;
 
-        newId = this._bmSvc.insertBookmark(parentId,
-                                           this._makeURI(items[iid]["link"]),
-                                           index, items[iid]["title"]);
+        newId = PlacesUtils.bookmarks.insertBookmark(parentId,
+                                                     this._makeURI(items[iid]["link"]),
+                                                     index, items[iid]["title"]);
 
         if (items[iid]["description"])
-          this._annoSvc.setItemAnnotation(newId,
-                                          "bookmarkProperties/description",
-                                          items[iid]["description"], 0,
-                                          this._annoSvc.EXPIRE_NEVER);
+          PlacesUtils.annotations.setItemAnnotation(newId,
+                                                    "bookmarkProperties/description",
+                                                    items[iid]["description"], 0,
+                                                    PlacesUtils.annotations.EXPIRE_NEVER);
 
         break;
       }
     }
   },
 
   _customizationsApplied: false,
   applyCustomizations: function DIST_applyCustomizations() {
@@ -272,20 +257,20 @@ DistributionCustomizer.prototype = {
     let bmProcessed = false;
     try {
       bmProcessed = this._prefs.getBoolPref(bmProcessedPref);
     }
     catch (e) {}
 
     if (!bmProcessed) {
       if (sections["BookmarksMenu"])
-        this._parseBookmarksSection(this._bmSvc.bookmarksMenuFolder,
+        this._parseBookmarksSection(PlacesUtils.bookmarksMenuFolderId,
                                     "BookmarksMenu");
       if (sections["BookmarksToolbar"])
-        this._parseBookmarksSection(this._bmSvc.toolbarFolder,
+        this._parseBookmarksSection(PlacesUtils.toolbarFolderId,
                                     "BookmarksToolbar");
       this._prefs.setBoolPref(bmProcessedPref, true);
     }
     return this._checkCustomizationComplete();
   },
 
   _prefDefaultsApplied: false,
   applyPrefDefaults: function DIST_applyPrefDefaults() {
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -772,16 +772,25 @@ BrowserGlue.prototype = {
     const PREF_TELEMETRY_PROMPTED = "toolkit.telemetry.prompted";
     const PREF_TELEMETRY_ENABLED  = "toolkit.telemetry.enabled";
     const PREF_TELEMETRY_REJECTED  = "toolkit.telemetry.rejected";
     const PREF_TELEMETRY_INFOURL  = "toolkit.telemetry.infoURL";
     const PREF_TELEMETRY_SERVER_OWNER = "toolkit.telemetry.server_owner";
     // This is used to reprompt users when privacy message changes
     const TELEMETRY_PROMPT_REV = 2;
 
+    function appendTelemetryNotification(notifyBox, message, buttons, hideclose) {
+      let notification = notifyBox.appendNotification(message, "telemetry", null,
+						      notifyBox.PRIORITY_INFO_LOW,
+						      buttons);
+      notification.setAttribute("hideclose", hideclose);
+      notification.persistence = -1;  // Until user closes it
+      return notification;
+    }
+
     var telemetryPrompted = null;
     try {
       telemetryPrompted = Services.prefs.getIntPref(PREF_TELEMETRY_PROMPTED);
     } catch(e) {}
     // If the user has seen the latest telemetry prompt, do not prompt again
     // else clear old prefs and reprompt
     if (telemetryPrompted === TELEMETRY_PROMPT_REV)
       return;
@@ -818,33 +827,30 @@ BrowserGlue.prototype = {
                         Services.prefs.setBoolPref(PREF_TELEMETRY_REJECTED, true);
                       }
                     }
                   ];
 
     // Set pref to indicate we've shown the notification.
     Services.prefs.setIntPref(PREF_TELEMETRY_PROMPTED, TELEMETRY_PROMPT_REV);
 
-    var notification = notifyBox.appendNotification(telemetryPrompt, "telemetry", null, notifyBox.PRIORITY_INFO_LOW, buttons);
-    notification.setAttribute("hideclose", true);
-    notification.persistence = -1;  // Until user closes it
-
+    let notification = appendTelemetryNotification(notifyBox, telemetryPrompt,
+						   buttons, true);
     let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
     let link = notification.ownerDocument.createElementNS(XULNS, "label");
     link.className = "text-link telemetry-text-link";
     link.setAttribute("value", browserBundle.GetStringFromName("telemetryLinkLabel"));
     link.addEventListener('click', function() {
       // Open the learn more url in a new tab
       browser.selectedTab = browser.addTab(Services.prefs.getCharPref(PREF_TELEMETRY_INFOURL));
       // Remove the notification on which the user clicked
       notification.parentNode.removeNotification(notification, true);
       // Add a new notification to that tab, with no "Learn more" link
       notifyBox = browser.getNotificationBox();
-      notification = notifyBox.appendNotification(telemetryPrompt, "telemetry", null, notifyBox.PRIORITY_INFO_LOW, buttons);
-      notification.persistence = -1; // Until user closes it
+      appendTelemetryNotification(notifyBox, telemetryPrompt, buttons, true);
     }, false);
     let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
     description.appendChild(link);
   },
 #endif
 
   _showPluginUpdatePage: function BG__showPluginUpdatePage() {
     Services.prefs.setBoolPref(PREF_PLUGINS_NOTIFYUSER, false);
@@ -1295,17 +1301,17 @@ BrowserGlue.prototype = {
   ensurePlacesDefaultQueriesInitialized:
   function BG_ensurePlacesDefaultQueriesInitialized() {
     // This is actual version of the smart bookmarks, must be increased every
     // time smart bookmarks change.
     // When adding a new smart bookmark below, its newInVersion property must
     // be set to the version it has been added in, we will compare its value
     // to users' smartBookmarksVersion and add new smart bookmarks without
     // recreating old deleted ones.
-    const SMART_BOOKMARKS_VERSION = 2;
+    const SMART_BOOKMARKS_VERSION = 3;
     const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
     const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
 
     // TODO bug 399268: should this be a pref?
     const MAX_RESULTS = 10;
 
     // Get current smart bookmarks version.  If not set, create them.
     let smartBookmarksCurrentVersion = 0;
@@ -1341,17 +1347,16 @@ BrowserGlue.prototype = {
             title: bundle.GetStringFromName("recentlyBookmarkedTitle"),
             uri: NetUtil.newURI("place:folder=BOOKMARKS_MENU" +
                                 "&folder=UNFILED_BOOKMARKS" +
                                 "&folder=TOOLBAR" +
                                 "&queryType=" +
                                 Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS +
                                 "&sort=" +
                                 Ci.nsINavHistoryQueryOptions.SORT_BY_DATEADDED_DESCENDING +
-                                "&excludeItemIfParentHasAnnotation=livemark%2FfeedURI" +
                                 "&maxResults=" + MAX_RESULTS +
                                 "&excludeQueries=1"),
             parent: PlacesUtils.bookmarksMenuFolderId,
             position: menuIndex++,
             newInVersion: 1
           },
           RecentTags: {
             title: bundle.GetStringFromName("recentTagsTitle"),
--- a/browser/components/places/content/bookmarkProperties.js
+++ b/browser/components/places/content/bookmarkProperties.js
@@ -276,23 +276,36 @@ var BookmarkPropertiesPanel = {
                                      .getKeywordForBookmark(this._itemId);
           // Load In Sidebar
           this._loadInSidebar = PlacesUtils.annotations
                                            .itemHasAnnotation(this._itemId,
                                                               PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
           break;
 
         case "folder":
-          if (PlacesUtils.itemIsLivemark(this._itemId)) {
-            this._itemType = LIVEMARK_CONTAINER;
-            this._feedURI = PlacesUtils.livemarks.getFeedURI(this._itemId);
-            this._siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
-          }
-          else
-            this._itemType = BOOKMARK_FOLDER;
+          this._itemType = BOOKMARK_FOLDER;
+          PlacesUtils.livemarks.getLivemark(
+            { id: this._itemId },
+            (function (aStatus, aLivemark) {
+              if (Components.isSuccessCode(aStatus)) {
+                this._itemType = LIVEMARK_CONTAINER;
+                this._feedURI = aLivemark.feedURI;
+                this._siteURI = aLivemark.siteURI;
+                this._fillEditProperties();
+
+                let acceptButton = document.documentElement.getButton("accept");
+                acceptButton.disabled = !this._inputIsValid();
+
+                let newHeight = window.outerHeight +
+                                this._element("descriptionField").boxObject.height;
+                window.resizeTo(window.outerWidth, newHeight);
+              }
+            }).bind(this)
+          );
+
           break;
       }
 
       // Description
       if (PlacesUtils.annotations
                      .itemHasAnnotation(this._itemId, PlacesUIUtils.DESCRIPTION_ANNO)) {
         this._description = PlacesUtils.annotations
                                        .getItemAnnotation(this._itemId,
@@ -336,18 +349,17 @@ var BookmarkPropertiesPanel = {
       case ACTION_EDIT:
         this._fillEditProperties();
         acceptButton.disabled = this._readOnly;
         break;
       case ACTION_ADD:
         this._fillAddProperties();
         // if this is an uri related dialog disable accept button until
         // the user fills an uri value.
-        if (this._itemType == BOOKMARK_ITEM ||
-            this._itemType == LIVEMARK_CONTAINER)
+        if (this._itemType == BOOKMARK_ITEM)
           acceptButton.disabled = !this._inputIsValid();
         break;
     }
 
     // When collapsible elements change their collapsed attribute we must
     // resize the dialog.
     // sizeToContent is not usable due to bug 90276, so we'll use resizeTo
     // instead and cache the element size. See WSucks in the legacy
@@ -513,26 +525,16 @@ var BookmarkPropertiesPanel = {
    */
   _inputIsValid: function BPP__inputIsValid() {
     if (this._itemType == BOOKMARK_ITEM &&
         !this._containsValidURI("locationField"))
       return false;
     if (this._isAddKeywordDialog && !this._element("keywordField").value.length)
       return false;
 
-    // Feed Location has to be a valid URI;
-    // Site Location has to be a valid URI or empty
-    if (this._itemType == LIVEMARK_CONTAINER) {
-      if (!this._containsValidURI("feedLocationField"))
-        return false;
-      if (!this._containsValidURI("siteLocationField") &&
-          (this._element("siteLocationField").value.length > 0))
-        return false;
-    }
-
     return true;
   },
 
   /**
    * Determines whether the XUL textbox with the given ID contains a
    * string that can be converted into an nsIURI.
    *
    * @param aTextboxID
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -1,49 +1,11 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Places Frontend Code.
- *
- * The Initial Developer of the Original Code is
- * Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Annie Sullivan <annie.sullivan@gmail.com>
- *   Ben Goodger <beng@google.com>
- *   Myk Melez <myk@mozilla.org>
- *   Marco Bonardo <mak77@bonardo.net>
- *   Asaf Romano <mano@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
- * 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 ***** */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 /**
  * The base view implements everything that's common to the toolbar and
  * menu views.
  */
@@ -165,17 +127,18 @@ PlacesViewBase.prototype = {
     let index = PlacesUtils.bookmarks.DEFAULT_INDEX;
     let container = this._resultNode;
     let orientation = Ci.nsITreeView.DROP_BEFORE;
     let isTag = false;
 
     let selectedNode = this.selectedNode;
     if (selectedNode) {
       let popup = document.popupNode;
-      if (!popup._placesNode || popup._placesNode == this._resultNode) {
+      if (!popup._placesNode || popup._placesNode == this._resultNode ||
+          popup._placesNode.itemId == -1) {
         // If a static menuitem is selected, or if the root node is selected,
         // the insertion point is inside the folder, at the end.
         container = selectedNode;
         orientation = Ci.nsITreeView.DROP_ON;
       }
       else {
         // In all other cases the insertion point is before that node.
         container = selectedNode.parent;
@@ -205,63 +168,72 @@ PlacesViewBase.prototype = {
 
   _cleanPopup: function PVB_cleanPopup(aPopup) {
     // Remove places popup children and update markers to keep track of
     // their indices.
     let start = aPopup._startMarker != -1 ? aPopup._startMarker + 1 : 0;
     let end = aPopup._endMarker != -1 ? aPopup._endMarker :
                                         aPopup.childNodes.length;
     let items = [];
-    let placesNodeFound = false;
+
+    // Automatically adjust the start and the end markers.
+    let firstNonStaticNodeFound = false;
     for (let i = start; i < end; ++i) {
       let item = aPopup.childNodes[i];
       if (item.getAttribute("builder") == "end") {
         // we need to do this for menus that have static content at the end but
         // are initially empty, eg. the history menu, we need to know where to
         // start inserting new items.
         aPopup._endMarker = i;
         break;
       }
+
       if (item._placesNode) {
         items.push(item);
-        placesNodeFound = true;
+        firstNonStaticNodeFound = true;
       }
       else {
-        // This is static content...
-        if (!placesNodeFound)
-          // ...at the start of the popup
-          // Initialized in menu.xml, in the base binding
+        // This is static content.
+        if (!firstNonStaticNodeFound) {
+          // We are at the beginning of the popup, in static content.
+          // The markers are initialized in menu.xml, in the base binding.
           aPopup._startMarker++;
+        }
         else {
-          // ...after places nodes
+          // We are at the end of the popup, after places nodes
           aPopup._endMarker = i;
           break;
         }
       }
     }
 
     for (let i = 0; i < items.length; ++i) {
       aPopup.removeChild(items[i]);
       if (aPopup._endMarker != -1)
         aPopup._endMarker--;
     }
   },
 
   _rebuildPopup: function PVB__rebuildPopup(aPopup) {
     this._cleanPopup(aPopup);
 
-    // If this is a livemark container check if the status menuitem has
-    // to be added or removed.
-    if (PlacesUtils.nodeIsLivemarkContainer(aPopup._placesNode))
-      this._ensureLivemarkStatusMenuItem(aPopup);
-
     let resultNode = aPopup._placesNode;
     if (!resultNode.containerOpen)
       return;
 
+    if (resultNode._feedURI) {
+      aPopup.removeAttribute("emptyplacesresult");
+      if (aPopup._emptyMenuItem) {
+        aPopup._emptyMenuItem.hidden = true;
+      }
+      aPopup._built = true;
+      this._populateLivemarkPopup(aPopup);
+      return;
+    }
+
     let cc = resultNode.childCount;
     if (cc > 0) {
       aPopup.removeAttribute("emptyplacesresult");
       if (aPopup._emptyMenuItem)
         aPopup._emptyMenuItem.hidden = true;
 
       for (let i = 0; i < cc; ++i) {
         let child = resultNode.getChild(i);
@@ -298,21 +270,24 @@ PlacesViewBase.prototype = {
     aPopup._emptyMenuItem = document.createElement("menuitem");
     aPopup._emptyMenuItem.setAttribute("label", label);
     aPopup._emptyMenuItem.setAttribute("disabled", true);
     aPopup.appendChild(aPopup._emptyMenuItem);
   },
 
   _createMenuItemForPlacesNode:
   function PVB__createMenuItemForPlacesNode(aPlacesNode) {
+    delete aPlacesNode._DOMElement;
     let element;
     let type = aPlacesNode.type;
-    if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
+    if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
       element = document.createElement("menuseparator");
+    }
     else {
+      let itemId = aPlacesNode.itemId;
       if (PlacesUtils.uriTypes.indexOf(type) != -1) {
         element = document.createElement("menuitem");
         element.className = "menuitem-iconic bookmark-item menuitem-with-favicon";
         element.setAttribute("scheme",
                              PlacesUIUtils.guessUrlSchemeForUI(aPlacesNode.uri));
       }
       else if (PlacesUtils.containerTypes.indexOf(type) != -1) {
         element = document.createElement("menu");
@@ -322,19 +297,29 @@ PlacesViewBase.prototype = {
           element.setAttribute("query", "true");
           if (PlacesUtils.nodeIsTagQuery(aPlacesNode))
             element.setAttribute("tagContainer", "true");
           else if (PlacesUtils.nodeIsDay(aPlacesNode))
             element.setAttribute("dayContainer", "true");
           else if (PlacesUtils.nodeIsHost(aPlacesNode))
             element.setAttribute("hostContainer", "true");
         }
-        else if (aPlacesNode.itemId != -1) {
-          if (PlacesUtils.nodeIsLivemarkContainer(aPlacesNode))
-            element.setAttribute("livemark", "true");
+        else if (itemId != -1) {
+          PlacesUtils.livemarks.getLivemark(
+            { id: itemId },
+            function (aStatus, aLivemark) {
+              if (Components.isSuccessCode(aStatus)) {
+                element.setAttribute("livemark", "true");
+                // Set an expando on the node, controller will use it to build
+                // its metadata.
+                aPlacesNode._feedURI = aLivemark.feedURI;
+                aPlacesNode._siteURI = aLivemark.siteURI;
+              }
+            }
+          );
         }
 
         let popup = document.createElement("menupopup");
         popup._placesNode = PlacesUtils.asContainer(aPlacesNode);
         if (this._nativeView) {
           popup._startMarker = -1;
           popup._endMarker = -1;
         }
@@ -387,52 +372,94 @@ PlacesViewBase.prototype = {
     }
 
     if (aPopup._endMarker != -1)
       aPopup._endMarker++;
 
     return element;
   },
 
+  _setLivemarkSiteURIMenuItem:
+  function PVB__setLivemarkSiteURIMenuItem(aPopup) {
+    let siteUrl = aPopup._placesNode._siteURI ? aPopup._placesNode._siteURI.spec
+                                              : null;
+    if (!siteUrl && aPopup._siteURIMenuitem) {
+      aPopup.removeChild(aPopup._siteURIMenuitem);
+      aPopup._siteURIMenuitem = null;
+      aPopup._startMarker--;
+      aPopup.removeChild(aPopup._siteURIMenuseparator);
+      aPopup._siteURIMenuseparator = null;
+      aPopup._startMarker--;
+    }
+    else if (siteUrl && !aPopup._siteURIMenuitem) {
+      // Add "Open (Feed Name)" menuitem.
+      aPopup._siteURIMenuitem = document.createElement("menuitem");
+      aPopup._siteURIMenuitem.className = "openlivemarksite-menuitem";
+      aPopup._siteURIMenuitem.setAttribute("targetURI", siteUrl);
+      aPopup._siteURIMenuitem.setAttribute("oncommand",
+        "openUILink(this.getAttribute('targetURI'), event);");
+
+      // If a user middle-clicks this item we serve the oncommand event.
+      // We are using checkForMiddleClick because of Bug 246720.
+      // Note: stopPropagation is needed to avoid serving middle-click
+      // with BT_onClick that would open all items in tabs.
+      aPopup._siteURIMenuitem.setAttribute("onclick",
+        "checkForMiddleClick(this, event); event.stopPropagation();");
+      let label =
+        PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
+                                         [aPopup.parentNode.getAttribute("label")])
+      aPopup._siteURIMenuitem.setAttribute("label", label);
+      aPopup.insertBefore(aPopup._siteURIMenuitem,
+                          aPopup.childNodes.item(aPopup._startMarker + 1));
+      aPopup._startMarker++;
+
+      aPopup._siteURIMenuseparator = document.createElement("menuseparator");
+      aPopup.insertBefore(aPopup._siteURIMenuseparator,
+                         aPopup.childNodes.item(aPopup._startMarker + 1));
+      aPopup._startMarker++;
+    }
+  },
+
   /**
    * Add, update or remove the livemark status menuitem.
    * @param aPopup
    *        The livemark container popup
+   * @param aStatus
+   *        The livemark status
    */
-  _ensureLivemarkStatusMenuItem:
-  function PVB_ensureLivemarkStatusMenuItem(aPopup) {
+  _setLivemarkStatusMenuItem:
+  function PVB_setLivemarkStatusMenuItem(aPopup, aStatus) {
     let itemId = aPopup._placesNode.itemId;
-    let as = PlacesUtils.annotations;
+    let statusMenuitem = aPopup._statusMenuitem;
+    let stringId = "";
+    if (aStatus == Ci.mozILivemark.STATUS_LOADING)
+      stringId = "bookmarksLivemarkLoading";
+    else if (aStatus == Ci.mozILivemark.STATUS_FAILED)
+      stringId = "bookmarksLivemarkFailed";
 
-    let lmStatus = null;
-    if (as.itemHasAnnotation(itemId, PlacesUtils.LMANNO_LOADFAILED))
-      lmStatus = "bookmarksLivemarkFailed";
-    else if (as.itemHasAnnotation(itemId, PlacesUtils.LMANNO_LOADING))
-      lmStatus = "bookmarksLivemarkLoading";
-
-    let lmStatusElt = aPopup._lmStatusMenuItem;
-    if (lmStatus && !lmStatusElt) {
+    if (stringId && !statusMenuitem) {
       // Create the status menuitem and cache it in the popup object.
-      lmStatusElt = document.createElement("menuitem");
-      lmStatusElt.setAttribute("lmStatus", lmStatus);
-      lmStatusElt.setAttribute("label", PlacesUIUtils.getString(lmStatus));
-      lmStatusElt.setAttribute("disabled", true);
-      aPopup.insertBefore(lmStatusElt,
+      statusMenuitem = document.createElement("menuitem");
+      statusMenuitem.setAttribute("livemarkStatus", stringId);
+      statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
+      statusMenuitem.setAttribute("disabled", true);
+      aPopup.insertBefore(statusMenuitem,
                           aPopup.childNodes.item(aPopup._startMarker + 1));
-      aPopup._lmStatusMenuItem = lmStatusElt;
+      aPopup._statusMenuitem = statusMenuitem;
       aPopup._startMarker++;
     }
-    else if (lmStatus && lmStatusElt.getAttribute("lmStatus") != lmStatus) {
+    else if (stringId &&
+             statusMenuitem.getAttribute("livemarkStatus") != stringId) {
       // Status has changed, update the cached status menuitem.
-      lmStatusElt.setAttribute("label", this.getString(lmStatus));
+      statusMenuitem.setAttribute("label", PlacesUIUtils.getString(stringId));
     }
-    else if (!lmStatus && lmStatusElt) {
-      // No status, remove the cached menuitem.
-      aPopup.removeChild(aPopup._lmStatusMenuItem);
-      aPopup._lmStatusMenuItem = null;
+    else if (!stringId && statusMenuitem) {
+      // The livemark has finished loading.
+      aPopup.removeChild(aPopup._statusMenuitem);
+      aPopup._statusMenuitem = null;
       aPopup._startMarker--;
     }
   },
 
   toggleCutNode: function PVB_toggleCutNode(aNode, aValue) {
     let elt = aNode._DOMElement;
     if (elt) {
       // We may get the popup for menus, but we need the menu itself.
@@ -483,24 +510,32 @@ PlacesViewBase.prototype = {
     let elt = aPlacesNode._DOMElement;
     if (!elt)
       throw "aPlacesNode must have _DOMElement set";
 
     // All livemarks have a feedURI, so use it as our indicator of a livemark
     // being modified.
     if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
       let menu = elt.parentNode;
-      if (!menu.hasAttribute("livemark"))
+      if (!menu.hasAttribute("livemark")) {
         menu.setAttribute("livemark", "true");
-    }
+      }
 
-    if ([PlacesUtils.LMANNO_LOADING,
-         PlacesUtils.LMANNO_LOADFAILED].indexOf(aAnno) != -1) {
-      // Loading status changed, update the livemark status menuitem.
-      this._ensureLivemarkStatusMenuItem(elt);
+      PlacesUtils.livemarks.getLivemark(
+        { id: aPlacesNode.itemId },
+        (function (aStatus, aLivemark) {
+          if (Components.isSuccessCode(aStatus)) {
+            // Set an expando on the node, controller will use it to build
+            // its metadata.
+            aPlacesNode._feedURI = aLivemark.feedURI;
+            aPlacesNode._siteURI = aLivemark.siteURI;
+            this.invalidateContainer(aPlacesNode);
+          }
+        }).bind(this)
+      );
     }
   },
 
   nodeTitleChanged:
   function PVB_nodeTitleChanged(aPlacesNode, aNewTitle) {
     let elt = aPlacesNode._DOMElement;
     if (!elt)
       throw "aPlacesNode must have _DOMElement set";
@@ -575,17 +610,34 @@ PlacesViewBase.prototype = {
       // No worries: If elt is the last item (i.e. no nextSibling),
       // _insertNewItem/_insertNewItemToPopup will insert the new element as
       // the last item.
       let nextElt = elt.nextSibling;
       this._insertNewItemToPopup(aNewPlacesNode, parentElt, nextElt);
     }
   },
 
-  nodeHistoryDetailsChanged: function() { },
+  nodeHistoryDetailsChanged:
+  function PVB_nodeHistoryDetailsChanged(aPlacesNode, aTime, aCount) {
+    if (aPlacesNode.parent && aPlacesNode.parent._feedURI) {
+      // Find the node in the parent.
+      let popup = aPlacesNode.parent._DOMElement;
+      for (let i = popup._startMarker; i < popup.childNodes.length; i++) {
+        let child = popup.childNodes[i];
+        if (child._placesNode && child._placesNode.uri == aPlacesNode.uri) {
+          if (aCount)
+            child.setAttribute("visited", "true");
+          else
+            child.removeAttribute("visited");
+          break;
+        }
+      }
+    }
+  },
+
   nodeTagsChanged: function() { },
   nodeDateAddedChanged: function() { },
   nodeLastModifiedChanged: function() { },
   nodeKeywordChanged: function() { },
   sortingChanged: function() { },
   batching: function() { },
 
   nodeInserted:
@@ -637,20 +689,70 @@ PlacesViewBase.prototype = {
     }
   },
 
   containerStateChanged:
   function PVB_containerStateChanged(aPlacesNode, aOldState, aNewState) {
     if (aNewState == Ci.nsINavHistoryContainerResultNode.STATE_OPENED ||
         aNewState == Ci.nsINavHistoryContainerResultNode.STATE_CLOSED) {
       this.invalidateContainer(aPlacesNode);
+
+      if (PlacesUtils.nodeIsFolder(aPlacesNode)) {
+        let queryOptions = PlacesUtils.asQuery(this._result.root).queryOptions;
+        if (queryOptions.excludeItems) {
+          return;
+        }
+
+        PlacesUtils.livemarks.getLivemark({ id: aPlacesNode.itemId },
+          (function (aStatus, aLivemark) {
+            if (Components.isSuccessCode(aStatus)) {
+              let shouldInvalidate = !aPlacesNode._feedURI;
+              aPlacesNode._feedURI = aLivemark.feedURI;
+              aPlacesNode._siteURI = aLivemark.siteURI;
+              if (aNewState == Ci.nsINavHistoryContainerResultNode.STATE_OPENED) {
+                aLivemark.registerForUpdates(aPlacesNode, this);
+                aLivemark.reload();
+                if (shouldInvalidate)
+                  this.invalidateContainer(aPlacesNode);
+              }
+              else {
+                aLivemark.unregisterForUpdates(aPlacesNode);
+              }
+            }
+          }).bind(this)
+        );
+      }
     }
-    else {
-      throw "Unexpected state passed to containerStateChanged";
-    }
+  },
+
+  _populateLivemarkPopup: function PVB__populateLivemarkPopup(aPopup)
+  {
+    this._setLivemarkSiteURIMenuItem(aPopup);
+    this._setLivemarkStatusMenuItem(aPopup, Ci.mozILivemark.STATUS_LOADING);
+
+    PlacesUtils.livemarks.getLivemark({ id: aPopup._placesNode.itemId },
+      (function (aStatus, aLivemark) {
+        let placesNode = aPopup._placesNode;
+        if (!Components.isSuccessCode(aStatus) || !placesNode.containerOpen)
+          return;
+
+        this._setLivemarkStatusMenuItem(aPopup, aLivemark.status);
+        this._cleanPopup(aPopup);
+
+        let children = aLivemark.getNodesForContainer(placesNode);
+        for (let i = 0; i < children.length; i++) {
+          let child = children[i];
+          this.nodeInserted(placesNode, child, i);
+          if (child.accessCount)
+            child._DOMElement.setAttribute("visited", true);
+          else
+            child._DOMElement.removeAttribute("visited");
+        }
+      }).bind(this)
+    );
   },
 
   invalidateContainer: function PVB_invalidateContainer(aPlacesNode) {
     let elt = aPlacesNode._DOMElement;
     if (!elt)
       throw "aPlacesNode must have _DOMElement set";
 
     elt._built = false;
@@ -691,97 +793,65 @@ PlacesViewBase.prototype = {
    * @param aPopup
    *        a Places popup.
    */
   _mayAddCommandsItems: function PVB__mayAddCommandsItems(aPopup) {
     // The command items are never added to the root popup.
     if (aPopup == this._rootElt)
       return;
 
-    // Check if the popup contains at least 2 menuitems with places nodes
-    let numURINodes = 0;
-    let currentChild = aPopup.firstChild;
-    while (currentChild) {
-      if (currentChild.localName == "menuitem" && currentChild._placesNode) {
-        if (++numURINodes == 2)
-          break;
+    let hasMultipleURIs = false;
+
+    // Check if the popup contains at least 2 menuitems with places nodes.
+    // We don't currently support opening multiple uri nodes when they are not
+    // populated by the result.
+    if (aPopup._placesNode.childCount > 0) {
+      let currentChild = aPopup.firstChild;
+      let numURINodes = 0;
+      while (currentChild) {
+        if (currentChild.localName == "menuitem" && currentChild._placesNode) {
+          if (++numURINodes == 2)
+            break;
+        }
+        currentChild = currentChild.nextSibling;
       }
-      currentChild = currentChild.nextSibling;
-    }
-
-    let hasMultipleURIs = numURINodes > 1;
-    let itemId = aPopup._placesNode.itemId;
-    let siteURIString = "";
-    if (itemId != -1 && PlacesUtils.itemIsLivemark(itemId)) {
-      let siteURI = PlacesUtils.livemarks.getSiteURI(itemId);
-      if (siteURI)
-        siteURIString = siteURI.spec;
+      hasMultipleURIs = numURINodes > 1;
     }
 
-    if (!siteURIString && aPopup._endOptOpenSiteURI) {
-      aPopup.removeChild(aPopup._endOptOpenSiteURI);
-      aPopup._endOptOpenSiteURI = null;
-    }
+    if (!hasMultipleURIs) {
+      // We don't have to show any option.
+      if (aPopup._endOptOpenAllInTabs) {
+        aPopup.removeChild(aPopup._endOptOpenAllInTabs);
+        aPopup._endOptOpenAllInTabs = null;
+        aPopup._endMarker--;
 
-    if (!hasMultipleURIs && aPopup._endOptOpenAllInTabs) {
-      aPopup.removeChild(aPopup._endOptOpenAllInTabs);
-      aPopup._endOptOpenAllInTabs = null;
-    }
-
-    if (!(hasMultipleURIs || siteURIString)) {
-      // We don't have to show any option.
-      if (aPopup._endOptSeparator) {
         aPopup.removeChild(aPopup._endOptSeparator);
         aPopup._endOptSeparator = null;
-        aPopup._endMarker = -1;
+        aPopup._endMarker--;
       }
-      return;
     }
-
-    if (!aPopup._endOptSeparator) {
+    else if (!aPopup._endOptOpenAllInTabs) {
       // Create a separator before options.
       aPopup._endOptSeparator = document.createElement("menuseparator");
       aPopup._endOptSeparator.className = "bookmarks-actions-menuseparator";
-      aPopup._endMarker = aPopup.childNodes.length;
       aPopup.appendChild(aPopup._endOptSeparator);
-    }
-
-    if (siteURIString && !aPopup._endOptOpenSiteURI) {
-      // Add "Open (Feed Name)" menuitem if it's a livemark with a siteURI.
-      aPopup._endOptOpenSiteURI = document.createElement("menuitem");
-      aPopup._endOptOpenSiteURI.className = "openlivemarksite-menuitem";
-      aPopup._endOptOpenSiteURI.setAttribute("targetURI", siteURIString);
-      aPopup._endOptOpenSiteURI.setAttribute("oncommand",
-          "openUILink(this.getAttribute('targetURI'), event);");
+      aPopup._endMarker++;
 
-      // If a user middle-clicks this item we serve the oncommand event
-      // We are using checkForMiddleClick because of Bug 246720
-      // Note: stopPropagation is needed to avoid serving middle-click
-      // with BT_onClick that would open all items in tabs.
-      aPopup._endOptOpenSiteURI.setAttribute("onclick",
-          "checkForMiddleClick(this, event); event.stopPropagation();");
-      aPopup._endOptOpenSiteURI.setAttribute("label",
-          PlacesUIUtils.getFormattedString("menuOpenLivemarkOrigin.label",
-          [aPopup.parentNode.getAttribute("label")]));
-      aPopup.appendChild(aPopup._endOptOpenSiteURI);
-    }
-
-    if (hasMultipleURIs && !aPopup._endOptOpenAllInTabs) {
-      // Add the "Open All in Tabs" menuitem if there are
-      // at least two menuitems with places result nodes.
+      // Add the "Open All in Tabs" menuitem.
       aPopup._endOptOpenAllInTabs = document.createElement("menuitem");
       aPopup._endOptOpenAllInTabs.className = "openintabs-menuitem";
       aPopup._endOptOpenAllInTabs.setAttribute("oncommand",
         "PlacesUIUtils.openContainerNodeInTabs(this.parentNode._placesNode, event, " +
                                                "PlacesUIUtils.getViewForNode(this));");
       aPopup._endOptOpenAllInTabs.setAttribute("onclick",
         "checkForMiddleClick(this, event); event.stopPropagation();");
       aPopup._endOptOpenAllInTabs.setAttribute("label",
         gNavigatorBundle.getString("menuOpenAllInTabs.label"));
       aPopup.appendChild(aPopup._endOptOpenAllInTabs);
+      aPopup._endMarker++;
     }
   },
 
   _onPopupShowing: function PVB__onPopupShowing(aEvent) {
     // Avoid handling popupshowing of inner views.
     let popup = aEvent.originalTarget;
     if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
       if (!popup._placesNode.containerOpen)
@@ -896,16 +966,17 @@ PlacesToolbar.prototype = {
       // a rebuild of the toolbar, it has to be rebuilt.
       // Otherwise, it will be initialized when the toolbar overflows.
       this._chevronPopup.place = this.place;
     }
   },
 
   _insertNewItem:
   function PT__insertNewItem(aChild, aBefore) {
+    delete aChild._DOMElement;
     let type = aChild.type;
     let button;
     if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
       button = document.createElement("toolbarseparator");
     }
     else {
       button = document.createElement("toolbarbutton");
       button.className = "bookmark-item";
@@ -918,18 +989,29 @@ PlacesToolbar.prototype = {
         button.setAttribute("type", "menu");
         button.setAttribute("container", "true");
 
         if (PlacesUtils.nodeIsQuery(aChild)) {
           button.setAttribute("query", "true");
           if (PlacesUtils.nodeIsTagQuery(aChild))
             button.setAttribute("tagContainer", "true");
         }
-        else if (PlacesUtils.nodeIsLivemarkContainer(aChild)) {
-          button.setAttribute("livemark", "true");
+        else if (PlacesUtils.nodeIsFolder(aChild)) {
+          PlacesUtils.livemarks.getLivemark(
+            { id: aChild.itemId },
+            function (aStatus, aLivemark) {
+              if (Components.isSuccessCode(aStatus)) {
+                button.setAttribute("livemark", "true");
+                // Set an expando on the node, controller will use it to build
+                // its metadata.
+                aChild._feedURI = aLivemark.feedURI;
+                aChild._siteURI = aLivemark.siteURI;
+              }
+            }
+          );
         }
 
         let popup = document.createElement("menupopup");
         popup.setAttribute("placespopup", "true");
         button.appendChild(popup);
         popup._placesNode = PlacesUtils.asContainer(aChild);
 #ifndef XP_MACOSX
         popup.setAttribute("context", "placesContext");
@@ -1183,22 +1265,29 @@ PlacesToolbar.prototype = {
       elt = elt.parentNode;
 
     if (elt.parentNode == this._rootElt) {
       // Node is on the toolbar.
 
       // All livemarks have a feedURI, so use it as our indicator.
       if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
         elt.setAttribute("livemark", true);
-      }
 
-      if ([PlacesUtils.LMANNO_LOADING,
-           PlacesUtils.LMANNO_LOADFAILED].indexOf(aAnno) != -1) {
-        // Loading status changed, update the livemark status menuitem.
-        this._ensureLivemarkStatusMenuItem(elt.firstChild);
+        PlacesUtils.livemarks.getLivemark(
+          { id: aPlacesNode.itemId },
+          (function (aStatus, aLivemark) {
+            if (Components.isSuccessCode(aStatus)) {
+              // Set an expando on the node, controller will use it to build
+              // its metadata.
+              aPlacesNode._feedURI = aLivemark.feedURI;
+              aPlacesNode._siteURI = aLivemark.siteURI;
+              this.invalidateContainer(aPlacesNode);
+            }
+          }).bind(this)
+        );
       }
     }
     else {
       // Node is in a submenu.
       PlacesViewBase.prototype.nodeAnnotationChanged.apply(this, arguments);
     }
   },
 
@@ -1618,23 +1707,26 @@ PlacesToolbar.prototype = {
     if (parent.localName == "toolbarbutton")
       this._openedMenuButton = parent;
 
     return PlacesViewBase.prototype._onPopupShowing.apply(this, arguments);
   },
 
   _onPopupHidden: function PT__onPopupHidden(aEvent) {
     let popup = aEvent.target;
-
+    let placesNode = popup._placesNode;
     // Avoid handling popuphidden of inner views
-    if (popup._placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
+    if (placesNode && PlacesUIUtils.getViewForNode(popup) == this) {
       // UI performance: folder queries are cheap, keep the resultnode open
       // so we don't rebuild its contents whenever the popup is reopened.
-      if (!PlacesUtils.nodeIsFolder(popup._placesNode))
-        popup._placesNode.containerOpen = false;
+      // Though, we want to always close feed containers so their expiration
+      // status will be checked at next opening.
+      if (!PlacesUtils.nodeIsFolder(placesNode) || placesNode._feedURI) {
+        placesNode.containerOpen = false;
+      }
     }
 
     let parent = popup.parentNode;
     if (parent.localName == "toolbarbutton") {
       this._openedMenuButton = null;
       // Clear the dragover attribute if present, if we are dragging into a
       // folder in the hierachy of current opened popup we don't clear
       // this attribute on clearOverFolder.  See Notify for closeTimer.
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -39,17 +39,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
 
 // XXXmano: we should move most/all of these constants to PlacesUtils
 const ORGANIZER_ROOT_BOOKMARKS = "place:folder=BOOKMARKS_MENU&excludeItems=1&queryType=1";
-const ORGANIZER_SUBSCRIPTIONS_QUERY = "place:annotation=livemark%2FfeedURI";
 
 // No change to the view, preserve current selection
 const RELOAD_ACTION_NOTHING = 0;
 // Inserting items new to the view, select the inserted rows
 const RELOAD_ACTION_INSERT = 1;
 // Removing items from the view, select the first item after the last selected
 const RELOAD_ACTION_REMOVE = 2;
 // Moving items within a view, don't treat the dropped items as additional
@@ -203,25 +202,21 @@ PlacesController.prototype = {
       return this._canInsert();
     case "placesCmd_new:separator":
       return this._canInsert() &&
              !PlacesUtils.asQuery(this._view.result.root).queryOptions.excludeItems &&
              this._view.result.sortingMode ==
                  Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
     case "placesCmd_show:info":
       var selectedNode = this._view.selectedNode;
-      if (selectedNode &&
-          PlacesUtils.getConcreteItemId(selectedNode) != -1  &&
-          !PlacesUtils.nodeIsLivemarkItem(selectedNode))
-        return true;
-      return false;
+      return selectedNode && PlacesUtils.getConcreteItemId(selectedNode) != -1
     case "placesCmd_reload":
       // Livemark containers
       var selectedNode = this._view.selectedNode;
-      return selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode);
+      return selectedNode && !!selectedNode._feedURI;
     case "placesCmd_sortBy:name":
       var selectedNode = this._view.selectedNode;
       return selectedNode &&
              PlacesUtils.nodeIsFolder(selectedNode) &&
              !PlacesUtils.nodeIsReadOnly(selectedNode) &&
              this._view.result.sortingMode ==
                  Ci.nsINavHistoryQueryOptions.SORT_BY_NONE;
     case "placesCmd_createBookmark":
@@ -504,17 +499,17 @@ PlacesController.prototype = {
           if (PlacesUtils.nodeIsBookmark(node)) {
             nodeData["bookmark"] = true;
             PlacesUtils.nodeIsTagQuery(node.parent)
 
             var parentNode = node.parent;
             if (parentNode) {
               if (PlacesUtils.nodeIsTagQuery(parentNode))
                 nodeData["tagChild"] = true;
-              else if (PlacesUtils.nodeIsLivemarkContainer(parentNode))
+              else if (parentNode._feedURI)
                 nodeData["livemarkChild"] = true;
             }
           }
           break;
       }
 
       // annotations
       if (uri) {
@@ -729,18 +724,27 @@ PlacesController.prototype = {
            "This method should be passed a URI as a nsIURI object, not as a string.");
   },
 
   /**
    * Reloads the selected livemark if any.
    */
   reloadSelectedLivemark: function PC_reloadSelectedLivemark() {
     var selectedNode = this._view.selectedNode;
-    if (selectedNode && PlacesUtils.nodeIsLivemarkContainer(selectedNode))
-      PlacesUtils.livemarks.reloadLivemarkFolder(selectedNode.itemId);
+    if (selectedNode) {
+      let itemId = selectedNode.itemId;
+      PlacesUtils.livemarks.getLivemark(
+        { id: itemId },
+        (function(aStatus, aLivemark) {
+          if (Components.isSuccessCode(aStatus)) {
+            aLivemark.reload(true);
+          }
+        }).bind(this)
+      );
+    }
   },
 
   /**
    * Opens the links in the selected folder, or the selected links in new tabs.
    */
   openSelectionInTabs: function PC_openLinksInTabs(aEvent) {
     var node = this._view.selectedNode;
     if (node && PlacesUtils.nodeIsContainer(node))
@@ -1060,20 +1064,22 @@ PlacesController.prototype = {
           addData(PlacesUtils.TYPE_HTML, index, overrideURI);
         }
 
         // This order is _important_! It controls how this and other
         // applications select data to be inserted based on type.
         addData(PlacesUtils.TYPE_X_MOZ_PLACE, i);
 
         // Drop the feed uri for livemark containers
-        if (PlacesUtils.nodeIsLivemarkContainer(node))
-          addURIData(i, PlacesUtils.livemarks.getFeedURI(node.itemId).spec);
-        else if (node.uri)
+        if (node._feedURI) {
+          addURIData(i, node._feedURI.spec);
+        }
+        else if (node.uri) {
           addURIData(i);
+        }
       }
     }
     finally {
       if (!didSuppressNotifications)
         result.suppressNotifications = false;
     }
   },
 
@@ -1133,18 +1139,17 @@ PlacesController.prototype = {
     // of them automatically.
     let copiedFolders = [];
     aNodes.forEach(function (node) {
       if (this._shouldSkipNode(node, copiedFolders))
         return;
       if (PlacesUtils.nodeIsFolder(node))
         copiedFolders.push(node);
 
-      let overrideURI = PlacesUtils.nodeIsLivemarkContainer(node) ?
-        PlacesUtils.livemarks.getFeedURI(node.itemId).spec : null;
+      let overrideURI = node._feedURI ? node._feedURI.spec : null;
       let resolveShortcuts = !PlacesControllerDragHelper.canMoveNode(node);
 
       contents.forEach(function (content) {
         content.entries.push(
           PlacesUtils.wrapNode(node, content.type, overrideURI, resolveShortcuts)
         );
       });
     }, this);
--- a/browser/components/places/content/editBookmarkOverlay.js
+++ b/browser/components/places/content/editBookmarkOverlay.js
@@ -1,44 +1,11 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Places Bookmark Properties dialog.
- *
- * The Initial Developer of the Original Code is Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2006
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Asaf Romano <mano@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
- * 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 ***** */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const LAST_USED_ANNO = "bookmarkPropertiesDialog/folderLastUsed";
 const MAX_FOLDER_ITEM_IN_MENU_LIST = 5;
 
 var gEditItemOverlay = {
   _uri: null,
   _itemId: -1,
   _itemIds: [],
@@ -47,16 +14,17 @@ var gEditItemOverlay = {
   _allTags: [],
   _multiEdit: false,
   _itemType: -1,
   _readOnly: false,
   _hiddenRows: [],
   _observersAdded: false,
   _staticFoldersListBuilt: false,
   _initialized: false,
+  _titleOverride: "",
 
   // the first field which was edited after this panel was initialized for
   // a certain item
   _firstEditedField: "",
 
   get itemId() {
     return this._itemId;
   },
@@ -75,16 +43,18 @@ var gEditItemOverlay = {
   _determineInfo: function EIO__determineInfo(aInfo) {
     // hidden rows
     if (aInfo && aInfo.hiddenRows)
       this._hiddenRows = aInfo.hiddenRows;
     else
       this._hiddenRows.splice(0, this._hiddenRows.length);
     // force-read-only
     this._readOnly = aInfo && aInfo.forceReadOnly;
+    this._titleOverride = aInfo && aInfo.titleOverride ? aInfo.titleOverride
+                                                       : "";
   },
 
   _showHideRows: function EIO__showHideRows() {
     var isBookmark = this._itemId != -1 &&
                      this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK;
     var isQuery = false;
     if (this._uri)
       isQuery = this._uri.schemeIs("place");
@@ -155,42 +125,44 @@ var gEditItemOverlay = {
     this._determineInfo(aInfo);
     if (aFor instanceof Ci.nsIURI) {
       this._itemId = -1;
       this._uri = aFor;
       this._readOnly = true;
     }
     else {
       this._itemId = aFor;
+      // We can't store information on invalid itemIds.
+      this._readOnly = this._readOnly || this._itemId == -1;
+
       var containerId = PlacesUtils.bookmarks.getFolderIdForItem(this._itemId);
       this._itemType = PlacesUtils.bookmarks.getItemType(this._itemId);
       if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {
         this._uri = PlacesUtils.bookmarks.getBookmarkURI(this._itemId);
-        if (!this._readOnly) // If readOnly wasn't forced through aInfo
-          this._readOnly = PlacesUtils.itemIsLivemark(containerId);
         this._initTextField("keywordField",
                             PlacesUtils.bookmarks
                                        .getKeywordForBookmark(this._itemId));
-        // Load In Sidebar checkbox
         this._element("loadInSidebarCheckbox").checked =
           PlacesUtils.annotations.itemHasAnnotation(this._itemId,
                                                     PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
       }
       else {
-        if (!this._readOnly) // If readOnly wasn't forced through aInfo
-          this._readOnly = false;
-
         this._uri = null;
-        this._isLivemark = PlacesUtils.itemIsLivemark(this._itemId);
-        if (this._isLivemark) {
-          var feedURI = PlacesUtils.livemarks.getFeedURI(this._itemId);
-          var siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
-          this._initTextField("feedLocationField", feedURI.spec);
-          this._initTextField("siteLocationField", siteURI ? siteURI.spec : "");
-        }
+        this._isLivemark = false;
+        PlacesUtils.livemarks.getLivemark(
+          {id: this._itemId },
+          (function (aStatus, aLivemark) {
+            if (Components.isSuccessCode(aStatus)) {
+              this._isLivemark = true;
+              this._initTextField("feedLocationField", aLivemark.feedURI.spec, true);
+              this._initTextField("siteLocationField", aLivemark.siteURI ? aLivemark.siteURI.spec : "", true);
+              this._showHideRows();
+            }
+          }).bind(this)
+        );
       }
 
       // folder picker
       this._initFolderMenuList(containerId);
 
       // description field
       this._initTextField("descriptionField", 
                           PlacesUIUtils.getItemDescription(this._itemId));
@@ -374,20 +346,27 @@ var gEditItemOverlay = {
     throw Cr.NS_ERROR_NO_INTERFACE;
   },
 
   _element: function EIO__element(aID) {
     return document.getElementById("editBMPanel_" + aID);
   },
 
   _getItemStaticTitle: function EIO__getItemStaticTitle() {
-    if (this._itemId == -1)
-      return PlacesUtils.history.getPageTitle(this._uri);
+    if (this._titleOverride)
+      return this._titleOverride;
 
-    return PlacesUtils.bookmarks.getItemTitle(this._itemId);
+    let title = "";
+    if (this._itemId == -1) {
+      title = PlacesUtils.history.getPageTitle(this._uri);
+    }
+    else {
+      title = PlacesUtils.bookmarks.getItemTitle(this._itemId);
+    }
+    return title;
   },
 
   _initNamePicker: function EIO_initNamePicker() {
     var namePicker = this._element("namePicker");
     namePicker.value = this._getItemStaticTitle();
     namePicker.readOnly = this._readOnly;
 
     // clear the undo stack
@@ -420,16 +399,18 @@ var gEditItemOverlay = {
     this._uri = null;
     this._uris = [];
     this._tags = [];
     this._allTags = [];
     this._itemIds = [];
     this._multiEdit = false;
     this._firstEditedField = "";
     this._initialized = false;
+    this._titleOverride = "";
+    this._readOnly = false;
   },
 
   onTagsFieldBlur: function EIO_onTagsFieldBlur() {
     if (this._updateTags()) // if anything has changed
       this._mayUpdateFirstEditField("tagsField");
   },
 
   _updateTags: function EIO__updateTags() {
@@ -592,46 +573,16 @@ var gEditItemOverlay = {
   onKeywordFieldBlur: function EIO_onKeywordFieldBlur() {
     var keyword = this._element("keywordField").value;
     if (keyword != PlacesUtils.bookmarks.getKeywordForBookmark(this._itemId)) {
       var txn = PlacesUIUtils.ptm.editBookmarkKeyword(this._itemId, keyword);
       PlacesUIUtils.ptm.doTransaction(txn);
     }
   },
 
-  onFeedLocationFieldBlur: function EIO_onFeedLocationFieldBlur() {
-    var uri;
-    try {
-      uri = PlacesUIUtils.createFixedURI(this._element("feedLocationField").value);
-    }
-    catch(ex) { return; }
-
-    var currentFeedURI = PlacesUtils.livemarks.getFeedURI(this._itemId);
-    if (!currentFeedURI.equals(uri)) {
-      var txn = PlacesUIUtils.ptm.editLivemarkFeedURI(this._itemId, uri);
-      PlacesUIUtils.ptm.doTransaction(txn);
-    }
-  },
-
-  onSiteLocationFieldBlur: function EIO_onSiteLocationFieldBlur() {
-    var uri = null;
-    try {
-      uri = PlacesUIUtils.createFixedURI(this._element("siteLocationField").value);
-    }
-    catch(ex) {  }
-
-    var currentSiteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
-    if ((!uri && !currentSiteURI) ||
-        (uri && currentSiteURI && currentSiteURI.equals(uri))) {
-      return;
-    }
-    var txn = PlacesUIUtils.ptm.editLivemarkSiteURI(this._itemId, uri);
-    PlacesUIUtils.ptm.doTransaction(txn);
-  },
-
   onLoadInSidebarCheckboxCommand:
   function EIO_onLoadInSidebarCheckboxCommand() {
     var loadInSidebarChecked = this._element("loadInSidebarCheckbox").checked;
     var txn = PlacesUIUtils.ptm.setLoadInSidebar(this._itemId,
                                                  loadInSidebarChecked);
     PlacesUIUtils.ptm.doTransaction(txn);
   },
 
@@ -1014,25 +965,29 @@ var gEditItemOverlay = {
                           PlacesUIUtils.getItemDescription(this._itemId));
       break;
     case PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO:
       this._element("loadInSidebarCheckbox").checked =
         PlacesUtils.annotations.itemHasAnnotation(this._itemId,
                                                   PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
       break;
     case PlacesUtils.LMANNO_FEEDURI:
-      var feedURISpec = PlacesUtils.livemarks.getFeedURI(this._itemId).spec;
-      this._initTextField("feedLocationField", feedURISpec);
+      let feedURISpec =
+        PlacesUtils.annotations.getItemAnnotation(this._itemId,
+                                                  PlacesUtils.LMANNO_FEEDURI);
+      this._initTextField("feedLocationField", feedURISpec, true);
       break;
     case PlacesUtils.LMANNO_SITEURI:
-      var siteURISpec = "";
-      var siteURI = PlacesUtils.livemarks.getSiteURI(this._itemId);
-      if (siteURI)
-        siteURISpec = siteURI.spec;
-      this._initTextField("siteLocationField", siteURISpec);
+      let siteURISpec = "";
+      try {
+        siteURISpec =
+          PlacesUtils.annotations.getItemAnnotation(this._itemId,
+                                                    PlacesUtils.LMANNO_SITEURI);
+      } catch (ex) {}
+      this._initTextField("siteLocationField", siteURISpec, true);
       break;
     }
   },
 
   onItemMoved: function EIO_onItemMoved(aItemId, aOldParent, aOldIndex,
                                         aNewParent, aNewIndex, aItemType) {
     if (aItemId != this._itemId ||
         aNewParent == this._getFolderIdFromMenuList())
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -595,19 +595,17 @@ var PlacesOrganizer = {
     var infoBoxExpanderWrapper = document.getElementById("infoBoxExpanderWrapper");
     var additionalInfoBroadcaster = document.getElementById("additionalInfoBroadcaster");
 
     if (!aNode) {
       infoBoxExpanderWrapper.hidden = true;
       return;
     }
     if (aNode.itemId != -1 &&
-        ((PlacesUtils.nodeIsFolder(aNode) &&
-          !PlacesUtils.nodeIsLivemarkContainer(aNode)) ||
-         PlacesUtils.nodeIsLivemarkItem(aNode))) {
+        PlacesUtils.nodeIsFolder(aNode) && !aNode._feedURI) {
       if (infoBox.getAttribute("minimal") == "true")
         infoBox.setAttribute("wasminimal", "true");
       infoBox.removeAttribute("minimal");
       infoBoxExpanderWrapper.hidden = true;
     }
     else {
       if (infoBox.getAttribute("wasminimal") == "true")
         infoBox.setAttribute("minimal", "true");
@@ -683,18 +681,20 @@ var PlacesOrganizer = {
       var itemId = -1;
       if (concreteId != -1 && useConcreteId)
         itemId = concreteId;
       else if (aSelectedNode.itemId != -1)
         itemId = aSelectedNode.itemId;
       else
         itemId = PlacesUtils._uri(aSelectedNode.uri);
 
-      gEditItemOverlay.initPanel(itemId, { hiddenRows: ["folderPicker"],
-                                           forceReadOnly: readOnly });
+      gEditItemOverlay.initPanel(itemId, { hiddenRows: ["folderPicker"]
+                                         , forceReadOnly: readOnly
+                                         , titleOverride: aSelectedNode.title
+                                         });
 
       // Dynamically generated queries, like history date containers, have
       // itemId !=0 and do not exist in history.  For them the panel is
       // read-only, but empty, since it can't get a valid title for the object.
       // In such a case we force the title using the selectedNode one, for UI
       // polishness.
       if (aSelectedNode.itemId == -1 &&
           (PlacesUtils.nodeIsDay(aSelectedNode) ||
--- a/browser/components/places/content/treeView.js
+++ b/browser/components/places/content/treeView.js
@@ -1,46 +1,11 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla History System
- *
- * The Initial Developer of the Original Code is
- * Google Inc.
- * Portions created by the Initial Developer are Copyright (C) 2005
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Brett Wilson <brettw@gmail.com> (Original author)
- *   Asaf Romano <mano@mozilla.com> (JavaScript version)
- *
- * 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 ***** */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function PlacesTreeView(aFlatList, aOnOpenFlatContainer) {
   this._tree = null;
   this._result = null;
   this._selection = null;
   this._rootNode = null;
   this._rows = [];
   this._flatList = aFlatList;
@@ -124,16 +89,20 @@ PlacesTreeView.prototype = {
    *        A container result node.
    *
    * @return true if aContainer is a plain container, false otherwise.
    */
   _isPlainContainer: function PTV__isPlainContainer(aContainer) {
     if (aContainer._plainContainer !== undefined)
       return aContainer._plainContainer;
 
+    // Livemarks are always plain containers.
+    if (aContainer._feedURI)
+      return aContainer._plainContainer = true;
+
     // We don't know enough about non-query containers.
     if (!(aContainer instanceof Ci.nsINavHistoryQueryResultNode))
       return aContainer._plainContainer = false;
 
     switch (aContainer.queryOptions.resultType) {
       case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_QUERY:
       case Ci.nsINavHistoryQueryOptions.RESULTS_AS_SITE_QUERY:
       case Ci.nsINavHistoryQueryOptions.RESULTS_AS_DATE_SITE_QUERY:
@@ -323,17 +292,18 @@ PlacesTreeView.prototype = {
         }
       }
 
       this._rows[row] = curChild;
       rowsInserted++;
 
       // Recursively do containers.
       if (!this._flatList &&
-          curChild instanceof Ci.nsINavHistoryContainerResultNode) {
+          curChild instanceof Ci.nsINavHistoryContainerResultNode &&
+          !curChild._feedURI) {
         let resource = this._getResourceForNode(curChild);
         let isopen = resource != null &&
                      PlacesUIUtils.localStore.HasAssertion(resource,
                                                            openLiteral,
                                                            trueLiteral, true);
         if (isopen != curChild.containerOpen)
           aToOpen.push(curChild);
         else if (curChild.containerOpen && curChild.childCount > 0)
@@ -620,30 +590,30 @@ PlacesTreeView.prototype = {
 
       // Update parent when inserting the first item, since twisty has changed.
       if (aParentNode.childCount == 1)
         this._tree.invalidateRow(parentRow);
     }
 
     // Compute the new row number of the node.
     let row = -1;
-    if (aNewIndex == 0 || this._isPlainContainer(aParentNode)) {
+    let cc = aParentNode.childCount;
+    if (aNewIndex == 0 || this._isPlainContainer(aParentNode) || cc == 0) {
       // We don't need to worry about sub hierarchies of the parent node
       // if it's a plain container, or if the new node is its first child.
       if (aParentNode == this._rootNode)
         row = aNewIndex;
       else
         row = parentRow + aNewIndex + 1;
     }
     else {
       // Here, we try to find the next visible element in the child list so we
       // can set the new visible index to be right before that.  Note that we
       // have to search down instead of up, because some siblings could have
       // children themselves that would be in the way.
-      let cc = aParentNode.childCount;
       let separatorsAreHidden = PlacesUtils.nodeIsSeparator(aNode) &&
                                 this.isSorted();
       for (let i = aNewIndex + 1; i < cc; i++) {
         let node = aParentNode.getChild(i);
         if (!separatorsAreHidden || PlacesUtils.nodeIsSeparator(node)) {
           // The children have not been shifted so the next item will have what
           // should be our index.
           row = this._getRowForNode(node, false, parentRow, i);
@@ -659,18 +629,20 @@ PlacesTreeView.prototype = {
                                             aNewIndex - 1);
         row = prevIndex + this._countVisibleRowsForNodeAtRow(prevIndex);
       }
     }
 
     this._rows.splice(row, 0, aNode);
     this._tree.rowCountChanged(row, 1);
 
-    if (PlacesUtils.nodeIsContainer(aNode) && PlacesUtils.asContainer(aNode).containerOpen)
+    if (PlacesUtils.nodeIsContainer(aNode) &&
+        PlacesUtils.asContainer(aNode).containerOpen) {
       this.invalidateContainer(aNode);
+    }
   },
 
   /**
    * THIS FUNCTION DOES NOT HANDLE cases where a collapsed node is being
    * removed but the node it is collapsed with is not being removed (this then
    * just swap out the removee with its collapsing partner). The only time
    * when we really remove things is when deleting URIs, which will apply to
    * all collapsees. This function is called sometimes when resorting items.
@@ -809,64 +781,132 @@ PlacesTreeView.prototype = {
     if (aColumnType != this.COLUMN_TYPE_LASTMODIFIED) {
       let lastModifiedColumn =
         this._findColumnByType(this.COLUMN_TYPE_LASTMODIFIED);
       if (lastModifiedColumn && !lastModifiedColumn.hidden)
         this._tree.invalidateCell(row, lastModifiedColumn);
     }
   },
 
+  _populateLivemarkContainer: function PTV__populateLivemarkContainer(aNode) {
+    PlacesUtils.livemarks.getLivemark({ id: aNode.itemId },
+      (function (aStatus, aLivemark) {
+        let placesNode = aNode;
+        // Need to check containerOpen since getLivemark is async.
+        if (!Components.isSuccessCode(aStatus) || !placesNode.containerOpen)
+          return;
+
+        let children = aLivemark.getNodesForContainer(placesNode);
+        for (let i = 0; i < children.length; i++) {
+          let child = children[i];
+          this.nodeInserted(placesNode, child, i);
+        }
+      }).bind(this));
+  },
+
   nodeTitleChanged: function PTV_nodeTitleChanged(aNode, aNewTitle) {
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
   },
 
   nodeURIChanged: function PTV_nodeURIChanged(aNode, aNewURI) {
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_URI);
   },
 
   nodeIconChanged: function PTV_nodeIconChanged(aNode) {
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
   },
 
   nodeHistoryDetailsChanged:
   function PTV_nodeHistoryDetailsChanged(aNode, aUpdatedVisitDate,
                                          aUpdatedVisitCount) {
+    if (aNode.parent && aNode.parent._feedURI) {
+      // Find the node in the parent.
+      let parentRow = this._flatList ? 0 : this._getRowForNode(aNode.parent);
+      for (let i = parentRow; i < this._rows.length; i++) {
+        let child = this.nodeForTreeIndex(i);
+        if (child.uri == aNode.uri) {
+          delete child._cellProperties;
+          this._invalidateCellValue(child, this.COLUMN_TYPE_TITLE);
+          break;
+        }
+      }
+      return;
+    }
+
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_DATE);
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_VISITCOUNT);
   },
 
   nodeTagsChanged: function PTV_nodeTagsChanged(aNode) {
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_TAGS);
   },
 
   nodeKeywordChanged: function PTV_nodeKeywordChanged(aNode, aNewKeyword) {
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_KEYWORD);
   },
 
   nodeAnnotationChanged: function PTV_nodeAnnotationChanged(aNode, aAnno) {
     if (aAnno == PlacesUIUtils.DESCRIPTION_ANNO) {
       this._invalidateCellValue(aNode, this.COLUMN_TYPE_DESCRIPTION);
-    } else if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
-      // The livemark attribute is set as a cell property on the title cell.
-      this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
+    }
+    else if (aAnno == PlacesUtils.LMANNO_FEEDURI) {
+      PlacesUtils.livemarks.getLivemark(
+        { id: aNode.itemId },
+        (function (aStatus, aLivemark) {
+          if (Components.isSuccessCode(aStatus)) {
+            aNode._feedURI = aLivemark.feedURI;
+            if (aNode._cellProperties) {
+              aNode._cellProperties.push(this._getAtomFor("livemark"));
+            }
+            // The livemark attribute is set as a cell property on the title cell.
+            this._invalidateCellValue(aNode, this.COLUMN_TYPE_TITLE);
+          }
+        }).bind(this)
+      );
     }
   },
 
   nodeDateAddedChanged: function PTV_nodeDateAddedChanged(aNode, aNewValue) {
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_DATEADDED);
   },
 
   nodeLastModifiedChanged:
   function PTV_nodeLastModifiedChanged(aNode, aNewValue) {
     this._invalidateCellValue(aNode, this.COLUMN_TYPE_LASTMODIFIED);
   },
 
   containerStateChanged:
   function PTV_containerStateChanged(aNode, aOldState, aNewState) {
     this.invalidateContainer(aNode);
+
+    if (PlacesUtils.nodeIsFolder(aNode) ||
+        (this._flatList && aNode == this._rootNode)) {
+      let queryOptions = PlacesUtils.asQuery(this._rootNode).queryOptions;
+      if (queryOptions.excludeItems) {
+        return;
+      }
+
+      PlacesUtils.livemarks.getLivemark({ id: aNode.itemId },
+        (function (aStatus, aLivemark) {
+          if (Components.isSuccessCode(aStatus)) {
+            let shouldInvalidate = !aNode._feedURI;
+            aNode._feedURI = aLivemark.feedURI;
+            if (aNewState == Components.interfaces.nsINavHistoryContainerResultNode.STATE_OPENED) {
+              aLivemark.registerForUpdates(aNode, this);
+              aLivemark.reload();
+              if (shouldInvalidate)
+                this.invalidateContainer(aNode);
+            }
+            else {
+              aLivemark.unregisterForUpdates(aNode);
+            }
+          }
+        }).bind(this)
+      );
+    }
   },
 
   invalidateContainer: function PTV_invalidateContainer(aContainer) {
     NS_ASSERT(this._result, "Need to have a result to update");
     if (!this._tree)
       return;
 
     let startReplacement, replaceCount;
@@ -950,16 +990,23 @@ PlacesTreeView.prototype = {
 
         // If we don't have a parent, we made it all the way to the root
         // and didn't find a match, so we can open our item.
         if (!parent && !item.containerOpen)
           item.containerOpen = true;
       }
     }
 
+    if (aContainer._feedURI) {
+      let queryOptions = PlacesUtils.asQuery(this._result.root).queryOptions;
+      if (!queryOptions.excludeItems) {
+        this._populateLivemarkContainer(aContainer);
+      }
+    }
+
     this._tree.endUpdateBatch();
 
     // Restore selection.
     this._restoreSelection(nodesToReselect, aContainer);
     this.selection.selectEventsSuppressed = false;
   },
 
   _columns: [],
@@ -1104,33 +1151,50 @@ PlacesTreeView.prototype = {
             properties.push(this._getAtomFor("tagContainer"));
           else if (PlacesUtils.nodeIsDay(node))
             properties.push(this._getAtomFor("dayContainer"));
           else if (PlacesUtils.nodeIsHost(node))
             properties.push(this._getAtomFor("hostContainer"));
         }
         else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER ||
                  nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_FOLDER_SHORTCUT) {
-          if (PlacesUtils.nodeIsLivemarkContainer(node))
+          if (node._feedURI) {
             properties.push(this._getAtomFor("livemark"));
+          }
+          else {
+            PlacesUtils.livemarks.getLivemark(
+              { id: node.itemId },
+              (function (aStatus, aLivemark) {
+                if (Components.isSuccessCode(aStatus)) {
+                  node._feedURI = aLivemark.feedURI;
+                  node._cellProperties.push(this._getAtomFor("livemark"));
+                  // The livemark attribute is set as a cell property on the title cell.
+                  this._invalidateCellValue(node, this.COLUMN_TYPE_TITLE);
+                }
+              }).bind(this)
+            );
+          }
         }
 
         if (itemId != -1) {
           let queryName = PlacesUIUtils.getLeftPaneQueryNameFromId(itemId);
           if (queryName)
             properties.push(this._getAtomFor("OrganizerQuery_" + queryName));
         }
       }
       else if (nodeType == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
         properties.push(this._getAtomFor("separator"));
       else if (PlacesUtils.nodeIsURI(node)) {
         properties.push(this._getAtomFor(PlacesUIUtils.guessUrlSchemeForUI(node.uri)));
-        if (itemId != -1) {
-          if (PlacesUtils.nodeIsLivemarkContainer(node.parent))
-            properties.push(this._getAtomFor("livemarkItem"));
+
+        if (node.parent._feedURI) {
+          properties.push(this._getAtomFor("livemarkItem"));
+          if (node.accessCount) {
+            properties.push(this._getAtomFor("visited"));
+          }
         }
       }
 
       node._cellProperties = properties;
     }
     for (let i = 0; i < node._cellProperties.length; i++)
       aProperties.AppendElement(node._cellProperties[i]);
   },
@@ -1149,17 +1213,17 @@ PlacesTreeView.prototype = {
       if (this._flatList)
         return true;
 
       // treat non-expandable childless queries as non-containers
       if (PlacesUtils.nodeIsQuery(node)) {
         let parent = node.parent;
         if ((PlacesUtils.nodeIsQuery(parent) ||
              PlacesUtils.nodeIsFolder(parent)) &&
-            !node.hasChildren)
+            !PlacesUtils.asQuery(node).hasChildren)
           return PlacesUtils.asQuery(parent).queryOptions.expandQueries;
       }
       return true;
     }
     return false;
   },
 
   isContainerOpen: function PTV_isContainerOpen(aRow) {
@@ -1169,18 +1233,24 @@ PlacesTreeView.prototype = {
     // All containers are listed in the rows array.
     return this._rows[aRow].containerOpen;
   },
 
   isContainerEmpty: function PTV_isContainerEmpty(aRow) {
     if (this._flatList)
       return true;
 
+    let node = this._rows[aRow];
+    if (node._feedURI) {
+      let queryOptions = PlacesUtils.asQuery(this._result.root).queryOptions;
+      return queryOptions.excludeItems;
+    }
+
     // All containers are listed in the rows array.
-    return !this._rows[aRow].hasChildren;
+    return !node.hasChildren;
   },
 
   isSeparator: function PTV_isSeparator(aRow) {
     // All separators are listed in the rows array.
     let node = this._rows[aRow];
     return node && PlacesUtils.nodeIsSeparator(node);
   },
 
@@ -1413,25 +1483,28 @@ PlacesTreeView.prototype = {
       throw Cr.NS_ERROR_UNEXPECTED;
 
     let node = this._rows[aRow];
     if (this._flatList && this._openContainerCallback) {
       this._openContainerCallback(node);
       return;
     }
 
-    let resource = this._getResourceForNode(node);
-    if (resource) {
-      const openLiteral = PlacesUIUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
-      const trueLiteral = PlacesUIUtils.RDF.GetLiteral("true");
+    // Persist containers open status, but never persist livemarks.
+    if (!node._feedURI) {
+      let resource = this._getResourceForNode(node);
+      if (resource) {
+        const openLiteral = PlacesUIUtils.RDF.GetResource("http://home.netscape.com/NC-rdf#open");
+        const trueLiteral = PlacesUIUtils.RDF.GetLiteral("true");
 
-      if (node.containerOpen)
-        PlacesUIUtils.localStore.Unassert(resource, openLiteral, trueLiteral);
-      else
-        PlacesUIUtils.localStore.Assert(resource, openLiteral, trueLiteral, true);
+        if (node.containerOpen)
+          PlacesUIUtils.localStore.Unassert(resource, openLiteral, trueLiteral);
+        else
+          PlacesUIUtils.localStore.Assert(resource, openLiteral, trueLiteral, true);
+      }
     }
 
     node.containerOpen = !node.containerOpen;
   },
 
   cycleHeader: function PTV_cycleHeader(aColumn) {
     if (!this._result)
       throw Cr.NS_ERROR_UNEXPECTED;
@@ -1564,20 +1637,18 @@ PlacesTreeView.prototype = {
     // Only bookmark-nodes are editable, and those are never built lazily
     let node = this._rows[aRow];
     if (!node || node.itemId == -1)
       return false;
 
     // The following items are never editable:
     // * Read-only items.
     // * places-roots
-    // * livemark items
     // * separators
     if (PlacesUtils.nodeIsReadOnly(node) ||
-        PlacesUtils.nodeIsLivemarkItem(node) ||
         PlacesUtils.nodeIsSeparator(node))
       return false;
 
     if (PlacesUtils.nodeIsFolder(node)) {
       let itemId = PlacesUtils.getConcreteItemId(node);
       if (PlacesUtils.isRootItem(itemId))
         return false;
     }
--- a/browser/components/places/tests/browser/browser_457473_no_copy_guid.js
+++ b/browser/components/places/tests/browser/browser_457473_no_copy_guid.js
@@ -36,17 +36,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 function test() {
   // sanity check
   ok(PlacesUtils, "checking PlacesUtils, running in chrome context?");
   ok(PlacesUIUtils, "checking PlacesUIUtils, running in chrome context?");
 
   /*
-  - create, a test folder, add bookmark, separator, livemark to it
+  - create, a test folder, add bookmark, separator to it
   - fetch guids for all
   - copy the folder
   - test that guids are all different
   - undo copy
   - redo copy
   - test that guids for the copy stay the same
   */
 
@@ -61,20 +61,16 @@ function test() {
   testRootNode.containerOpen = true;
   is(testRootNode.childCount, 0, "confirm test root node is a container, and is empty");
 
   // create folder A, fill it w/ each item type
   var folderAId = PlacesUtils.bookmarks.createFolder(testRootId, "A", -1);
   PlacesUtils.bookmarks.insertBookmark(folderAId, PlacesUtils._uri("http://foo"),
                                        -1, "test bookmark");
   PlacesUtils.bookmarks.insertSeparator(folderAId, -1);
-  PlacesUtils.livemarks.createLivemarkFolderOnly(folderAId, "test livemark",
-                                                 PlacesUtils._uri("http://test"),
-                                                 PlacesUtils._uri("http://test"), -1);
-
   var folderANode = testRootNode.getChild(0);
   var folderAGUIDs = getGUIDs(folderANode);
 
   // test the test function
   ok(checkGUIDs(folderANode, folderAGUIDs, true), "confirm guid test works");
 
   // serialize the folder
   var serializedNode = PlacesUtils.wrapNode(folderANode, PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER);
@@ -120,18 +116,17 @@ function test() {
 }
 
 function getGUIDs(aNode) {
   PlacesUtils.asContainer(aNode);
   aNode.containerOpen = true;
   var GUIDs = {
     folder: PlacesUtils.bookmarks.getItemGUID(aNode.itemId),
     bookmark: PlacesUtils.bookmarks.getItemGUID(aNode.getChild(0).itemId),
-    separator: PlacesUtils.bookmarks.getItemGUID(aNode.getChild(1).itemId),
-    livemark: PlacesUtils.bookmarks.getItemGUID(aNode.getChild(2).itemId)
+    separator: PlacesUtils.bookmarks.getItemGUID(aNode.getChild(1).itemId)
   };
   aNode.containerOpen = false;
   return GUIDs;
 }
 
 function checkGUIDs(aFolderNode, aGUIDs, aShouldMatch) {
 
   function check(aNode, aGUID, aEquals) {
@@ -139,14 +134,13 @@ function checkGUIDs(aFolderNode, aGUIDs,
     return aEquals ? (nodeGUID == aGUID) : (nodeGUID != aGUID);
   }
 
   PlacesUtils.asContainer(aFolderNode);
   aFolderNode.containerOpen = true;
 
   var allMatch = check(aFolderNode, aGUIDs.folder, aShouldMatch) &&
                  check(aFolderNode.getChild(0), aGUIDs.bookmark, aShouldMatch) &&
-                 check(aFolderNode.getChild(1), aGUIDs.separator, aShouldMatch) &&
-                 check(aFolderNode.getChild(2), aGUIDs.livemark, aShouldMatch);
+                 check(aFolderNode.getChild(1), aGUIDs.separator, aShouldMatch)
 
   aFolderNode.containerOpen = false;
   return allMatch;
 }
--- a/browser/components/places/tests/browser/browser_library_views_liveupdate.js
+++ b/browser/components/places/tests/browser/browser_library_views_liveupdate.js
@@ -90,21 +90,16 @@ function startTest() {
   bs.setItemTitle(id, "bmf_edited");
   addedBookmarks.push(id);
   id = bs.insertBookmark(id,
                          PlacesUtils._uri("http://bmf1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "bmf1");
   addedBookmarks.push(id);
   bs.moveItem(id, bs.bookmarksMenuFolder, 0);
-  id = PlacesUtils.livemarks.createLivemarkFolderOnly(
-    bs.bookmarksMenuFolder, "bml",
-    PlacesUtils._uri("http://bml.siteuri.mozilla.org/"),
-    PlacesUtils._uri("http://bml.feeduri.mozilla.org/"), bs.DEFAULT_INDEX);
-  addedBookmarks.push(id);
 
   // TOOLBAR
   ok(true, "*** Acting on toolbar bookmarks");
   bs.insertBookmark(bs.toolbarFolder,
                     PlacesUtils._uri("http://tb1.mozilla.org/"),
                     bs.DEFAULT_INDEX,
                     "tb1");
   bs.setItemTitle(id, "tb1_edited");
@@ -123,20 +118,16 @@ function startTest() {
   bs.setItemTitle(id, "tbf_edited");
   addedBookmarks.push(id);
   id = bs.insertBookmark(id,
                          PlacesUtils._uri("http://tbf1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "bmf1");
   addedBookmarks.push(id);
   bs.moveItem(id, bs.toolbarFolder, 0);
-  id = PlacesUtils.livemarks.createLivemarkFolderOnly(
-    bs.toolbarFolder, "tbl", PlacesUtils._uri("http://tbl.siteuri.mozilla.org/"),
-    PlacesUtils._uri("http://tbl.feeduri.mozilla.org/"), bs.DEFAULT_INDEX);
-  addedBookmarks.push(id);
 
   // UNSORTED
   ok(true, "*** Acting on unsorted bookmarks");
   id = bs.insertBookmark(bs.unfiledBookmarksFolder,
                          PlacesUtils._uri("http://ub1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "ub1");
   bs.setItemTitle(id, "ub1_edited");
@@ -155,21 +146,16 @@ function startTest() {
   bs.setItemTitle(id, "ubf_edited");
   addedBookmarks.push(id);
   id = bs.insertBookmark(id,
                          PlacesUtils._uri("http://ubf1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "ubf1");
   addedBookmarks.push(id);
   bs.moveItem(id, bs.unfiledBookmarksFolder, 0);
-  id = PlacesUtils.livemarks.createLivemarkFolderOnly(
-    bs.unfiledBookmarksFolder, "bubl",
-    PlacesUtils._uri("http://bubl.siteuri.mozilla.org/"),
-    PlacesUtils._uri("http://bubl.feeduri.mozilla.org/"), bs.DEFAULT_INDEX);
-  addedBookmarks.push(id);
 
   // Remove all added bookmarks.
   addedBookmarks.forEach(function (aItem) {
     // If we remove an item after its containing folder has been removed,
     // this will throw, but we can ignore that.
     try {
       bs.removeItem(aItem);
     } catch (ex) {}
@@ -196,37 +182,17 @@ function finishTest() {
  */
 var bookmarksObserver = {
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsINavBookmarkObserver
   , Ci.nsIAnnotationObserver
   ]),
 
   // nsIAnnotationObserver
-  onItemAnnotationSet: function(aItemId, aAnnotationName) {
-    if (aAnnotationName == PlacesUtils.LMANNO_FEEDURI) {
-      // Check that item is recognized as a livemark.
-      let validator = function(aTreeRowIndex) {
-        let tree = gLibrary.PlacesOrganizer._places;
-        let livemarkAtom = Cc["@mozilla.org/atom-service;1"].
-                           getService(Ci.nsIAtomService).
-                           getAtom("livemark");
-        let properties = Cc["@mozilla.org/supports-array;1"].
-                         createInstance(Ci.nsISupportsArray);
-        tree.view.getCellProperties(aTreeRowIndex,
-                                    tree.columns.getColumnAt(0),
-                                    properties);
-        return properties.GetIndexOf(livemarkAtom) != -1;
-      };
-
-      var [node, index, valid] = getNodeForTreeItem(aItemId, gLibrary.PlacesOrganizer._places, validator);
-      isnot(node, null, "Found new Places node in left pane at " + index);
-      ok(valid, "Node is recognized as a livemark");
-    }
-  },
+  onItemAnnotationSet: function() {},
   onItemAnnotationRemoved: function() {},
   onPageAnnotationSet: function() {},
   onPageAnnotationRemoved: function() {},
 
   // nsINavBookmarkObserver
   onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex, aItemType,
                                         aURI) {
     var node = null;
--- a/browser/components/places/tests/browser/browser_views_liveupdate.js
+++ b/browser/components/places/tests/browser/browser_views_liveupdate.js
@@ -113,21 +113,16 @@ function startTest() {
   addedBookmarks.push(id);
   id = bs.insertBookmark(id,
                          PlacesUtils._uri("http://bmf1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "bmf1");
   bs.setItemTitle(id, "bmf1_edited");
   addedBookmarks.push(id);
   bs.moveItem(id, bs.bookmarksMenuFolder, 0);
-  id = PlacesUtils.livemarks.createLivemarkFolderOnly(
-    bs.bookmarksMenuFolder, "bml",
-    PlacesUtils._uri("http://bml.siteuri.mozilla.org/"),
-    PlacesUtils._uri("http://bml.feeduri.mozilla.org/"), bs.DEFAULT_INDEX);
-  addedBookmarks.push(id);
 
   // TOOLBAR
   info("*** Acting on toolbar bookmarks");
   id = bs.insertBookmark(bs.toolbarFolder,
                          PlacesUtils._uri("http://tb1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "tb1");
   bs.setItemTitle(id, "tb1_edited");
@@ -149,20 +144,16 @@ function startTest() {
   addedBookmarks.push(id);
   id = bs.insertBookmark(id,
                          PlacesUtils._uri("http://tbf1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "tbf1");
   bs.setItemTitle(id, "tbf1_edited");
   addedBookmarks.push(id);
   bs.moveItem(id, bs.toolbarFolder, 0);
-  id = PlacesUtils.livemarks.createLivemarkFolderOnly(
-    bs.toolbarFolder, "tbl", PlacesUtils._uri("http://tbl.siteuri.mozilla.org/"),
-    PlacesUtils._uri("http://tbl.feeduri.mozilla.org/"), bs.DEFAULT_INDEX);
-  addedBookmarks.push(id);
 
   // UNSORTED
   info("*** Acting on unsorted bookmarks");
   id = bs.insertBookmark(bs.unfiledBookmarksFolder,
                          PlacesUtils._uri("http://ub1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "ub1");
   bs.setItemTitle(id, "ub1_edited");
@@ -182,21 +173,16 @@ function startTest() {
   addedBookmarks.push(id);
   id = bs.insertBookmark(id,
                          PlacesUtils._uri("http://ubf1.mozilla.org/"),
                          bs.DEFAULT_INDEX,
                          "bubf1");
   bs.setItemTitle(id, "bubf1_edited");
   addedBookmarks.push(id);
   bs.moveItem(id, bs.unfiledBookmarksFolder, 0);
-  id = PlacesUtils.livemarks.createLivemarkFolderOnly(
-    bs.unfiledBookmarksFolder, "bubl",
-    PlacesUtils._uri("http://bubl.siteuri.mozilla.org/"),
-    PlacesUtils._uri("http://bubl.feeduri.mozilla.org/"), bs.DEFAULT_INDEX);
-  addedBookmarks.push(id);
 
   // Remove all added bookmarks.
   addedBookmarks.forEach(function (aItem) {
     // If we remove an item after its containing folder has been removed,
     // this will throw, but we can ignore that.
     try {
       bs.removeItem(aItem);
     } catch (ex) {}
@@ -228,48 +214,17 @@ function finishTest() {
  */
 var bookmarksObserver = {
   QueryInterface: XPCOMUtils.generateQI([
     Ci.nsINavBookmarkObserver
   , Ci.nsIAnnotationObserver
   ]),
 
   // nsIAnnotationObserver
-  onItemAnnotationSet: function(aItemId, aAnnotationName) {
-    if (aAnnotationName == PlacesUtils.LMANNO_FEEDURI) {
-      var views = getViewsForFolder(PlacesUtils.bookmarks.getFolderIdForItem(aItemId));
-      ok(views.length > 0, "Found affected views (" + views.length + "): " + views);
-
-      // Check that item is recognized as a livemark.
-      let validator = function(aElementOrTreeIndex) {
-        if (typeof(aElementOrTreeIndex) == "number") {
-          var sidebar = document.getElementById("sidebar");
-          var tree = sidebar.contentDocument.getElementById("bookmarks-view");
-          let livemarkAtom = Cc["@mozilla.org/atom-service;1"].
-                             getService(Ci.nsIAtomService).
-                             getAtom("livemark");
-          let properties = Cc["@mozilla.org/supports-array;1"].
-                           createInstance(Ci.nsISupportsArray);
-          tree.view.getCellProperties(aElementOrTreeIndex,
-                                      tree.columns.getColumnAt(0),
-                                      properties);
-          return properties.GetIndexOf(livemarkAtom) != -1;
-        }
-        else {
-          return aElementOrTreeIndex.hasAttribute("livemark");
-        }
-      };
-
-      for (var i = 0; i < views.length; i++) {
-        var [node, index, valid] = searchItemInView(aItemId, views[i], validator);
-        isnot(node, null, "Found new Places node in " + views[i] + " at " + index);
-        ok(valid, "Node is recognized as a livemark");
-      }
-    }
-  },
+  onItemAnnotationSet: function() {},
   onItemAnnotationRemoved: function() {},
   onPageAnnotationSet: function() {},
   onPageAnnotationRemoved: function() {},
 
   // nsINavBookmarkObserver
   onItemAdded: function PSB_onItemAdded(aItemId, aFolderId, aIndex,
                                         aItemType, aURI) {
     var views = getViewsForFolder(aFolderId);
--- a/browser/components/places/tests/unit/head_bookmarks.js
+++ b/browser/components/places/tests/unit/head_bookmarks.js
@@ -97,15 +97,15 @@ let (XULAppInfo = {
 
 
 const FILENAME_BOOKMARKS_HTML = "bookmarks.html";
 let (backup_date = new Date().toLocaleFormat("%Y-%m-%d")) {
   const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json";
 }
 
 // Smart bookmarks constants.
-const SMART_BOOKMARKS_VERSION = 2;
+const SMART_BOOKMARKS_VERSION = 3;
 const SMART_BOOKMARKS_ON_TOOLBAR = 1;
 const SMART_BOOKMARKS_ON_MENU = 3; // Takes in count the additional separator.
 
 // Default bookmarks constants.
 const DEFAULT_BOOKMARKS_ON_TOOLBAR = 1;
 const DEFAULT_BOOKMARKS_ON_MENU = 1;
--- a/browser/components/places/tests/unit/test_384370.js
+++ b/browser/components/places/tests/unit/test_384370.js
@@ -31,29 +31,25 @@
  * 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 ***** */
 
-// The following components need to be initialized to perform tests without
-// asserting in debug builds (Bug 448804).
-Cc["@mozilla.org/browser/livemark-service;2"].getService(Ci.nsILivemarkService);
-Cc["@mozilla.org/feed-processor;1"].createInstance(Ci.nsIFeedProcessor);
-
 const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
 const DESCRIPTION_ANNO = "bookmarkProperties/description";
 const POST_DATA_ANNO = "bookmarkProperties/POSTData";
 
 do_check_eq(typeof PlacesUtils, "object");
 
 // main
 function run_test() {
+  do_test_pending();
   /*
     HTML+FEATURES SUMMARY:
     - import legacy bookmarks
     - export as json, import, test (tests integrity of html > json)
     - export as html, import, test (tests integrity of json > html)
 
     BACKUP/RESTORE SUMMARY:
     - create a bookmark in each root
@@ -87,31 +83,35 @@ function run_test() {
   // 2. run the test-suite
   // Note: we do not empty the db before this import to catch bugs like 380999
   try {
     importer.importHTMLFromFile(bookmarksFileOld, true);
   } catch(ex) { do_throw("couldn't import legacy bookmarks file: " + ex); }
   populate();
   validate();
 
-  // Test exporting a Places canonical json file.
-  // 1. export to bookmarks.exported.json
-  // 2. empty bookmarks db
-  // 3. import bookmarks.exported.json
-  // 4. run the test-suite
-  try {
-    PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
-  } catch(ex) { do_throw("couldn't export to file: " + ex); }
-  LOG("exported json"); 
-  try {
-    PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
-  } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
-  LOG("imported json"); 
-  validate();
-  LOG("validated import"); 
+  waitForAsyncUpdates(function () {
+    // Test exporting a Places canonical json file.
+    // 1. export to bookmarks.exported.json
+    // 2. empty bookmarks db
+    // 3. import bookmarks.exported.json
+    // 4. run the test-suite
+    try {
+      PlacesUtils.backups.saveBookmarksToJSONFile(jsonFile);
+    } catch(ex) { do_throw("couldn't export to file: " + ex); }
+    LOG("exported json");
+    try {
+      PlacesUtils.restoreBookmarksFromJSONFile(jsonFile);
+    } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
+    LOG("imported json");
+    validate();
+    LOG("validated import");
+
+    waitForAsyncUpdates(do_test_finished);
+  });
 }
 
 var tagData = [
   { uri: uri("http://slint.us"), tags: ["indie", "kentucky", "music"] },
   { uri: uri("http://en.wikipedia.org/wiki/Diplodocus"), tags: ["dinosaur", "dj", "rad word"] }
 ];
 
 var bookmarkData = [
@@ -238,24 +238,27 @@ function testToolbarFolder() {
 
   // child count (add 2 for pre-existing items)
   do_check_eq(toolbar.childCount, bookmarkData.length + 2);
   
   // livemark
   var livemark = toolbar.getChild(1);
   // title
   do_check_eq("Latest Headlines", livemark.title);
-  // livemark check
-  do_check_true(PlacesUtils.livemarks.isLivemark(livemark.itemId));
-  // site url
-  do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
-              PlacesUtils.livemarks.getSiteURI(livemark.itemId).spec);
-  // feed url
-  do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
-              PlacesUtils.livemarks.getFeedURI(livemark.itemId).spec);
+
+  PlacesUtils.livemarks.getLivemark(
+    { id: livemark.itemId },
+    function (aStatus, aLivemark) {
+      do_check_true(Components.isSuccessCode(aStatus));
+      do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
+                  aLivemark.siteURI.spec);
+      do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
+                  aLivemark.feedURI.spec);
+    }
+  );
 
   // test added bookmark data
   var child = toolbar.getChild(2);
   do_check_eq(child.uri, bookmarkData[0].uri.spec);
   do_check_eq(child.title, bookmarkData[0].title);
   child = toolbar.getChild(3);
   do_check_eq(child.uri, bookmarkData[1].uri.spec);
   do_check_eq(child.title, bookmarkData[1].title);
--- a/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js
+++ b/browser/components/places/tests/unit/test_457441-import-export-corrupt-bookmarks-html.js
@@ -44,78 +44,80 @@
 // Get Services
 var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
          getService(Ci.nsINavHistoryService);
 var dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
 var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
          getService(Ci.nsINavBookmarksService);
 var as = Cc["@mozilla.org/browser/annotation-service;1"].
          getService(Ci.nsIAnnotationService);
-var lms = Cc["@mozilla.org/browser/livemark-service;2"].
-          getService(Ci.nsILivemarkService);
 var icos = Cc["@mozilla.org/browser/favicon-service;1"].
            getService(Ci.nsIFaviconService);
 var ps = Cc["@mozilla.org/preferences-service;1"].
          getService(Ci.nsIPrefBranch);
 var ies = Cc["@mozilla.org/browser/places/import-export-service;1"].
           getService(Ci.nsIPlacesImportExportService);
 
 const DESCRIPTION_ANNO = "bookmarkProperties/description";
 const LOAD_IN_SIDEBAR_ANNO = "bookmarkProperties/loadInSidebar";
 const POST_DATA_ANNO = "bookmarkProperties/POSTData";
 
 const TEST_FAVICON_PAGE_URL = "http://en-US.www.mozilla.com/en-US/firefox/central/";
 const TEST_FAVICON_DATA_URL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==";
 
-// main
 function run_test() {
+  do_test_pending();
+
   // avoid creating the places smart folder during tests
   ps.setIntPref("browser.places.smartBookmarksVersion", -1);
 
   // import bookmarks from corrupt file
   var corruptBookmarksFile = do_get_file("bookmarks.corrupt.html");
   try {
     ies.importHTMLFromFile(corruptBookmarksFile, true);
   } catch(ex) { do_throw("couldn't import corrupt bookmarks file: " + ex); }
 
   // Check that every bookmark is correct
   // Corrupt bookmarks should not have been imported
   database_check();
-
-  // Create corruption in database
-  var corruptItemId = bs.insertBookmark(bs.toolbarFolder,
-                                        uri("http://test.mozilla.org"),
-                                        bs.DEFAULT_INDEX, "We love belugas");
-  var stmt = dbConn.createStatement("UPDATE moz_bookmarks SET fk = NULL WHERE id = :itemId");
-  stmt.params.itemId = corruptItemId;
-  stmt.execute();
-  stmt.finalize();
+  waitForAsyncUpdates(function() {
+    // Create corruption in database
+    var corruptItemId = bs.insertBookmark(bs.toolbarFolder,
+                                          uri("http://test.mozilla.org"),
+                                          bs.DEFAULT_INDEX, "We love belugas");
+    var stmt = dbConn.createStatement("UPDATE moz_bookmarks SET fk = NULL WHERE id = :itemId");
+    stmt.params.itemId = corruptItemId;
+    stmt.execute();
+    stmt.finalize();
 
-  // Export bookmarks
-  var bookmarksFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
-  bookmarksFile.append("bookmarks.exported.html");
-  if (bookmarksFile.exists())
-    bookmarksFile.remove(false);
-  bookmarksFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
-  if (!bookmarksFile.exists())
-    do_throw("couldn't create file: bookmarks.exported.html");
-  try {
-    ies.exportHTMLToFile(bookmarksFile);
-  } catch(ex) { do_throw("couldn't export to bookmarks.exported.html: " + ex); }
+    // Export bookmarks
+    var bookmarksFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
+    bookmarksFile.append("bookmarks.exported.html");
+    if (bookmarksFile.exists())
+      bookmarksFile.remove(false);
+    bookmarksFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, 0600);
+    if (!bookmarksFile.exists())
+      do_throw("couldn't create file: bookmarks.exported.html");
+    try {
+      ies.exportHTMLToFile(bookmarksFile);
+    } catch(ex) { do_throw("couldn't export to bookmarks.exported.html: " + ex); }
 
-  // Clear all bookmarks
-  remove_all_bookmarks();
+    // Clear all bookmarks
+    remove_all_bookmarks();
 
-  // Import bookmarks
-  try {
-    ies.importHTMLFromFile(bookmarksFile, true);
-  } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
+    // Import bookmarks
+    try {
+      ies.importHTMLFromFile(bookmarksFile, true);
+    } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
 
-  // Check that every bookmark is correct
-  database_check();
+    // Check that every bookmark is correct
+    database_check();
+
+    waitForAsyncUpdates(do_test_finished);
+  });
 }
 
 /*
  * Check for imported bookmarks correctness
  */
 function database_check() {
   // BOOKMARKS MENU
   var query = hs.getNewQuery();
@@ -187,24 +189,26 @@ function database_check() {
   var toolbar = result.root;
   toolbar.containerOpen = true;
   do_check_eq(toolbar.childCount, 3);
   
   // livemark
   var livemark = toolbar.getChild(1);
   // title
   do_check_eq("Latest Headlines", livemark.title);
-  // livemark check
-  do_check_true(lms.isLivemark(livemark.itemId));
-  // site url
-  do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
-              lms.getSiteURI(livemark.itemId).spec);
-  // feed url
-  do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
-              lms.getFeedURI(livemark.itemId).spec);
+  PlacesUtils.livemarks.getLivemark(
+    { id: livemark.itemId },
+    function (aStatus, aLivemark) {
+      do_check_true(Components.isSuccessCode(aStatus));
+      do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
+                  aLivemark.siteURI.spec);
+      do_check_eq("http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
+                  aLivemark.feedURI.spec);
+    }
+  );
 
   // cleanup
   toolbar.containerOpen = false;
 
   // UNFILED BOOKMARKS
   query.setFolders([bs.unfiledBookmarksFolder], 1);
   result = hs.executeQuery(query, hs.getNewQueryOptions());
   var unfiledBookmarks = result.root;
--- a/browser/components/places/tests/unit/test_bookmarks_html.js
+++ b/browser/components/places/tests/unit/test_bookmarks_html.js
@@ -78,17 +78,16 @@ let test_bookmarks = {
     },
   ],
   toolbar: [
     { title: "Getting Started",
       url: "http://en-us.www.mozilla.com/en-US/firefox/central/",
       icon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="
     },
     { title: "Latest Headlines",
-      description: "Livemark test comment",
       url: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/livebookmarks/",
       feedUrl: "http://en-us.fxfeeds.mozilla.com/en-US/firefox/headlines.xml",
     }
   ],
   unfiled: [
     { title: "Example.tld",
       url: "http://example.tld/",
     },
@@ -100,16 +99,20 @@ let gBookmarksFileOld;
 // Places bookmarks.html file pointer.
 let gBookmarksFileNew;
 
 let importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
                getService(Ci.nsIPlacesImportExportService);
 
 function run_test()
 {
+  run_next_test();
+}
+
+add_test(function setup() {
   // Avoid creating smart bookmarks during the test.
   Services.prefs.setIntPref("browser.places.smartBookmarksVersion", -1);
 
   // File pointer to legacy bookmarks file.
   gBookmarksFileOld = do_get_file("bookmarks.preplaces.html");
 
   // File pointer to a new Places-exported bookmarks file.
   gBookmarksFileNew = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
@@ -126,41 +129,49 @@ function run_test()
   // Test importing a pre-Places canonical bookmarks file.
   // 1. import bookmarks.preplaces.html
   // 2. run the test-suite
   // Note: we do not empty the db before this import to catch bugs like 380999
   try {
     importer.importHTMLFromFile(gBookmarksFileOld, true);
   } catch(ex) { do_throw("couldn't import legacy bookmarks file: " + ex); }
 
-  testImportedBookmarks();
+  waitForAsyncUpdates(function () {
+    testImportedBookmarks();
 
-  // Prepare for next tests.
-  try {
-    importer.exportHTMLToFile(gBookmarksFileNew);
-  } catch(ex) { do_throw("couldn't export to file: " + ex); }
+    // Prepare for next tests.
+    try {
+      importer.exportHTMLToFile(gBookmarksFileNew);
+    } catch(ex) { do_throw("couldn't export to file: " + ex); }
 
-  remove_all_bookmarks();
-  run_next_test();
-}
+    waitForAsyncUpdates(function () {
+      remove_all_bookmarks();
+      run_next_test();
+    });
+  });
+});
 
 add_test(function test_import_new()
 {
   // Test importing a Places bookmarks.html file.
   // 1. import bookmarks.exported.html
   // 2. run the test-suite
 
   try {
     importer.importHTMLFromFile(gBookmarksFileNew, true);
   } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
 
-  testImportedBookmarks();
+  waitForAsyncUpdates(function () {
+    testImportedBookmarks();
 
-  remove_all_bookmarks();
-  run_next_test();
+    waitForAsyncUpdates(function () {
+      remove_all_bookmarks();
+      run_next_test();
+    });
+  });
 });
 
 add_test(function test_emptytitle_export()
 {
   // Test exporting and importing with an empty-titled bookmark.
   // 1. import bookmarks
   // 1. create an empty-titled bookmark.
   // 2. export to bookmarks.exported.html
@@ -184,28 +195,32 @@ add_test(function test_emptytitle_export
   } catch(ex) { do_throw("couldn't export to file: " + ex); }
 
   remove_all_bookmarks();
 
   try {
     importer.importHTMLFromFile(gBookmarksFileNew, true);
   } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
 
-  testImportedBookmarks();
+  waitForAsyncUpdates(function () {
+    testImportedBookmarks();
 
-  // Cleanup.
-  test_bookmarks.unfiled.pop();
-  PlacesUtils.bookmarks.removeItem(id);
+    // Cleanup.
+    test_bookmarks.unfiled.pop();
+    PlacesUtils.bookmarks.removeItem(id);
 
-  try {
-    importer.exportHTMLToFile(gBookmarksFileNew);
-  } catch(ex) { do_throw("couldn't export to file: " + ex); }
+    try {
+      importer.exportHTMLToFile(gBookmarksFileNew);
+    } catch(ex) { do_throw("couldn't export to file: " + ex); }
 
-  remove_all_bookmarks();
-  run_next_test();
+    waitForAsyncUpdates(function () {
+      remove_all_bookmarks();
+      run_next_test();
+    });
+  });
 });
 
 add_test(function test_import_preplaces_to_folder()
 {
   // Test importing a pre-Places canonical bookmarks file to a specific folder.
   // 1. create a new folder
   // 2. import bookmarks.preplaces.html to that folder
   // 3. run the test-suite
@@ -213,21 +228,25 @@ add_test(function test_import_preplaces_
   let testFolder = PlacesUtils.bookmarks.createFolder(
     PlacesUtils.bookmarksMenuFolderId, "test-import",
     PlacesUtils.bookmarks.DEFAULT_INDEX
   );
   try {
     importer.importHTMLFromFileToFolder(gBookmarksFileOld, testFolder, false);
   } catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
 
-  // Import-to-folder creates subfolders for toolbar and unfiled.
-  testImportedBookmarksToFolder(testFolder);
+  waitForAsyncUpdates(function () {
+    // Import-to-folder creates subfolders for toolbar and unfiled.
+    testImportedBookmarksToFolder(testFolder);
 
-  remove_all_bookmarks();
-  run_next_test();
+    waitForAsyncUpdates(function () {
+      remove_all_bookmarks();
+      run_next_test();
+    });
+  });
 });
 
 add_test(function test_import_to_folder()
 {
   // Test importing a Places canonical bookmarks file to a specific folder.
   // 1. create a new folder
   // 2. import bookmarks.exported.html to that folder
   // 3. run the test-suite
@@ -235,21 +254,25 @@ add_test(function test_import_to_folder(
   let testFolder = PlacesUtils.bookmarks.createFolder(
     PlacesUtils.bookmarksMenuFolderId, "test-import",
     PlacesUtils.bookmarks.DEFAULT_INDEX
   );
   try {
     importer.importHTMLFromFileToFolder(gBookmarksFileNew, testFolder, false);
   } catch(ex) { do_throw("couldn't import the exported file to folder: " + ex); }
 
-  // Import-to-folder creates subfolders for toolbar and unfiled.
-  testImportedBookmarksToFolder(testFolder);
+  waitForAsyncUpdates(function () {
+    // Import-to-folder creates subfolders for toolbar and unfiled.
+    testImportedBookmarksToFolder(testFolder);
 
-  remove_all_bookmarks();
-  run_next_test();
+    waitForAsyncUpdates(function () {
+      remove_all_bookmarks();
+      run_next_test();
+    });
+  });
 });
 
 add_test(function test_import_ontop()
 {
   // Test importing the exported bookmarks.html file *on top of* the existing
   // bookmarks.
   // 1. empty bookmarks db
   // 2. import the exported bookmarks file
@@ -262,20 +285,24 @@ add_test(function test_import_ontop()
   } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
   try {
     importer.exportHTMLToFile(gBookmarksFileNew);
   } catch(ex) { do_throw("couldn't export to file: " + ex); }
   try {
     importer.importHTMLFromFile(gBookmarksFileNew, true);
   } catch(ex) { do_throw("couldn't import the exported file: " + ex); }
 
-  testImportedBookmarks();
+  waitForAsyncUpdates(function () {
+    testImportedBookmarks();
 
-  remove_all_bookmarks();
-  run_next_test();
+    waitForAsyncUpdates(function () {
+      remove_all_bookmarks();
+      run_next_test();
+    });
+  });
 });
 
 function testImportedBookmarks()
 {
   for (let group in test_bookmarks) {
     let root;
     switch (group) {
       case "menu":
@@ -345,18 +372,24 @@ function checkItem(aExpected, aNode)
           do_check_eq(PlacesUtils.bookmarks.getItemDateAdded(id),
                       aExpected.dateAdded);
         break;
       case "lastModified":
           do_check_eq(PlacesUtils.bookmarks.getItemLastModified(id),
                       aExpected.lastModified);
         break;
       case "url":
-        if (!PlacesUtils.livemarks.isLivemark(id))
-          do_check_eq(aNode.uri, aExpected.url);
+        PlacesUtils.livemarks.getLivemark(
+          { id: id },
+          function (aStatus, aLivemark) {
+            if (!Components.isSuccessCode(aStatus)) {
+              do_check_eq(aNode.uri, aExpected.url);
+            }
+          }
+        );
         break;
       case "icon":
         let faviconURI = PlacesUtils.favicons.getFaviconForPage(
           NetUtil.newURI(aExpected.url)
         );
         let dataURL = PlacesUtils.favicons.getFaviconDataAsDataURL(faviconURI);
         // Avoid do_check_eq for console spam.
         do_check_true(dataURL == aExpected.icon);
@@ -373,21 +406,24 @@ function checkItem(aExpected, aNode)
                                .getItemAnnotation(id, PlacesUtils.POST_DATA_ANNO),
                     aExpected.postData);
         break;
       case "charset":
         do_check_eq(PlacesUtils.history.getCharsetForURI(NetUtil.newURI(aNode.uri)),
                     aExpected.charset);
         break;
       case "feedUrl":
-        do_check_true(PlacesUtils.livemarks.isLivemark(id));
-        do_check_eq(PlacesUtils.livemarks.getSiteURI(id).spec,
-                    aExpected.url);
-        do_check_eq(PlacesUtils.livemarks.getFeedURI(id).spec,
-                    aExpected.feedUrl);
+        PlacesUtils.livemarks.getLivemark(
+          { id: id },
+          function (aStatus, aLivemark) {
+            do_check_true(Components.isSuccessCode(aStatus));
+            do_check_eq(aLivemark.siteURI.spec, aExpected.url);
+            do_check_eq(aLivemark.feedURI.spec, Expected.feedUrl);
+          }
+        );
         break;
       case "children":
         let folder = aNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
         do_check_eq(folder.hasChildren, aExpected.children.length > 0);
         folder.containerOpen = true;
         do_check_eq(folder.childCount, aExpected.children.length);
 
         aExpected.children.forEach(function (item, index) checkItem(item, folder.getChild(index)));
--- a/browser/components/places/tests/unit/test_placesTxn.js
+++ b/browser/components/places/tests/unit/test_placesTxn.js
@@ -34,17 +34,16 @@
  * 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 ***** */
 
 var bmsvc = PlacesUtils.bookmarks;
-var lmsvc = PlacesUtils.livemarks;
 var ptSvc = PlacesUIUtils.ptm;
 var tagssvc = PlacesUtils.tagging;
 var annosvc = PlacesUtils.annotations;
 
 // create and add bookmarks observer
 var observer = {
   onBeginUpdateBatch: function() {
     this._beginUpdateBatch = true;
@@ -414,94 +413,16 @@ function run_test() {
   do_check_eq(observer._itemChangedId, bkmk1Id);
   do_check_eq(observer._itemChangedProperty, "keyword");
   do_check_eq(observer._itemChangedValue, "kw1"); 
   txn11.undoTransaction();
   do_check_eq(observer._itemChangedId, bkmk1Id);
   do_check_eq(observer._itemChangedProperty, "keyword");
   do_check_eq(observer._itemChangedValue, ""); 
 
-  // Testing create livemark
-  var txn12 = ptSvc.createLivemark(uri("http://feeduri.com"),
-                                   uri("http://siteuri.com"),
-                                   "Livemark1", root);
-  txn12.doTransaction();
-  var lvmkId = observer._itemAddedId;
-  do_check_true(lmsvc.isLivemark(lvmkId));
-  do_check_eq(lmsvc.getSiteURI(lvmkId).spec, "http://siteuri.com/");
-  do_check_eq(lmsvc.getFeedURI(lvmkId).spec, "http://feeduri.com/");
-  txn12.undoTransaction();
-  do_check_false(lmsvc.isLivemark(lvmkId));
-  txn12.redoTransaction();
-  lvmkId = observer._itemAddedId;
-  do_check_true(lmsvc.isLivemark(lvmkId));
-  do_check_eq(lmsvc.getSiteURI(lvmkId).spec, "http://siteuri.com/");
-  do_check_eq(lmsvc.getFeedURI(lvmkId).spec, "http://feeduri.com/");
-
-  // editLivemarkSiteURI
-  var txn13 = ptSvc.editLivemarkSiteURI(lvmkId, uri("http://new-siteuri.com/"));
-  txn13.doTransaction();
-  do_check_eq(observer._itemChangedId, lvmkId);
-  do_check_eq(observer._itemChangedProperty, "livemark/siteURI");
-  do_check_eq(lmsvc.getSiteURI(lvmkId).spec, "http://new-siteuri.com/");
-  txn13.undoTransaction();
-  do_check_eq(observer._itemChangedId, lvmkId);
-  do_check_eq(observer._itemChangedProperty, "livemark/siteURI");
-  do_check_eq(observer._itemChangedValue, "");
-  do_check_eq(lmsvc.getSiteURI(lvmkId).spec, "http://siteuri.com/");
-  txn13.redoTransaction();
-  do_check_eq(observer._itemChangedId, lvmkId);
-  do_check_eq(observer._itemChangedProperty, "livemark/siteURI");
-  do_check_eq(lmsvc.getSiteURI(lvmkId).spec, "http://new-siteuri.com/");
-  txn13.undoTransaction();
-  do_check_eq(observer._itemChangedId, lvmkId);
-  do_check_eq(observer._itemChangedProperty, "livemark/siteURI");
-  do_check_eq(observer._itemChangedValue, "");
-  do_check_eq(lmsvc.getSiteURI(lvmkId).spec, "http://siteuri.com/");
-
-  // editLivemarkFeedURI
-  var txn14 = ptSvc.editLivemarkFeedURI(lvmkId, uri("http://new-feeduri.com/"));
-  txn14.doTransaction();
-  do_check_eq(observer._itemChangedId, lvmkId);
-  do_check_eq(observer._itemChangedProperty, "livemark/feedURI");
-  do_check_eq(lmsvc.getFeedURI(lvmkId).spec, "http://new-feeduri.com/");
-  txn14.undoTransaction();
-  do_check_eq(observer._itemChangedId, lvmkId);
-  do_check_eq(observer._itemChangedProperty, "livemark/feedURI");
-  do_check_eq(observer._itemChangedValue, "");
-  do_check_eq(lmsvc.getFeedURI(lvmkId).spec, "http://feeduri.com/");
-  txn14.redoTransaction();
-  do_check_eq(observer._itemChangedId, lvmkId);
-  do_check_eq(observer._itemChangedProperty, "livemark/feedURI");
-  do_check_eq(observer._itemChangedValue, "");
-  do_check_eq(lmsvc.getFeedURI(lvmkId).spec, "http://new-feeduri.com/");
-  txn14.undoTransaction();
-  do_check_eq(observer._itemChangedId, lvmkId);
-  do_check_eq(observer._itemChangedProperty, "livemark/feedURI");
-  do_check_eq(observer._itemChangedValue, "");
-  do_check_eq(lmsvc.getFeedURI(lvmkId).spec, "http://feeduri.com/");
-
-  // Testing remove livemark
-  // Set an annotation and check that we don't lose it on undo
-  annosvc.setItemAnnotation(lvmkId, "livemark/testAnno", "testAnno",
-                            0, annosvc.EXPIRE_NEVER);
-  var txn15 = ptSvc.removeItem(lvmkId);
-  txn15.doTransaction();
-  do_check_false(lmsvc.isLivemark(lvmkId));
-  do_check_eq(observer._itemRemovedId, lvmkId);
-  txn15.undoTransaction();
-  lvmkId = observer._itemAddedId;
-  do_check_true(lmsvc.isLivemark(lvmkId));
-  do_check_eq(lmsvc.getSiteURI(lvmkId).spec, "http://siteuri.com/");
-  do_check_eq(lmsvc.getFeedURI(lvmkId).spec, "http://feeduri.com/");
-  do_check_eq(annosvc.getItemAnnotation(lvmkId, "livemark/testAnno"), "testAnno");
-  txn15.redoTransaction();
-  do_check_false(lmsvc.isLivemark(lvmkId));
-  do_check_eq(observer._itemRemovedId, lvmkId);
-
   // Test LoadInSidebar transaction.
   var txn16 = ptSvc.setLoadInSidebar(bkmk1Id, true);
   txn16.doTransaction();
   do_check_eq(observer._itemChangedId, bkmk1Id);
   do_check_eq(observer._itemChangedProperty, PlacesUIUtils.LOAD_IN_SIDEBAR_ANNO);
   do_check_eq(observer._itemChanged_isAnnotationProperty, true);
   txn16.undoTransaction();
   do_check_eq(observer._itemChangedId, bkmk1Id);
--- a/browser/components/places/tests/unit/test_txnGUIDs.js
+++ b/browser/components/places/tests/unit/test_txnGUIDs.js
@@ -36,52 +36,70 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /**
  * This test will ensure any transactions service that is going to create
  * a new item, won't replace the GUID when undoing and redoing the action.
  */
-var bmsvc = PlacesUtils.bookmarks;
-var txnsvc = PlacesUIUtils.ptm;
 
 function test_GUID_persistance(aTxn) {
   aTxn.doTransaction();
-  var itemId = bmsvc.getIdForItemAt(bmsvc.unfiledBookmarksFolder, 0);
-  var GUID = bmsvc.getItemGUID(itemId);
-  aTxn.undoTransaction();
-  aTxn.redoTransaction();
-  do_check_eq(GUID, bmsvc.getItemGUID(itemId));
-  aTxn.undoTransaction();
+  waitForAsyncUpdates(function () {
+    let itemId = PlacesUtils.bookmarks
+                            .getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
+    let GUID = PlacesUtils.bookmarks.getItemGUID(itemId);
+    aTxn.undoTransaction();
+    aTxn.redoTransaction();
+    waitForAsyncUpdates(function() {
+      let itemId = PlacesUtils.bookmarks
+                              .getIdForItemAt(PlacesUtils.unfiledBookmarksFolderId, 0);
+      do_check_eq(GUID, PlacesUtils.bookmarks.getItemGUID(itemId));
+      aTxn.undoTransaction();
+      waitForAsyncUpdates(run_next_test);
+    });
+  });
 }
 
 function run_test() {
-  // Create folder.
-  var createFolderTxn = txnsvc.createFolder("Test folder",
-                                            bmsvc.unfiledBookmarksFolder,
-                                            bmsvc.DEFAULT_INDEX);
-  test_GUID_persistance(createFolderTxn);
+  run_next_test();
+}
 
-  // Create bookmark.
-  var createBookmarkTxn = txnsvc.createItem(uri("http://www.example.com"),
-                                            bmsvc.unfiledBookmarksFolder,
-                                            bmsvc.DEFAULT_INDEX,
-                                            "Test bookmark");
-  test_GUID_persistance(createBookmarkTxn);
+add_test(function create_folder() {
+  let createFolderTxn = new PlacesCreateFolderTransaction(
+    "Test folder", PlacesUtils.unfiledBookmarksFolderId,
+    PlacesUtils.bookmarks.DEFAULT_INDEX
+  );
+  test_GUID_persistance(createFolderTxn);
+});
 
-  // Create separator.
-  var createSeparatorTxn = txnsvc.createSeparator(bmsvc.unfiledBookmarksFolder,
-                                                  bmsvc.DEFAULT_INDEX);
-  test_GUID_persistance(createFolderTxn);
+add_test(function create_bookmark() {
+  let createBookmarkTxn = new PlacesCreateBookmarkTransaction(
+    NetUtil.newURI("http://www.example.com"), PlacesUtils.unfiledBookmarksFolderId,
+    PlacesUtils.bookmarks.DEFAULT_INDEX, "Test bookmark"
+  );
+  test_GUID_persistance(createBookmarkTxn);
+});
+  
+add_test(function create_separator() {
+  let createSeparatorTxn = new PlacesCreateSeparatorTransaction(
+    PlacesUtils.unfiledBookmarksFolderId, PlacesUtils.bookmarks.DEFAULT_INDEX
+  );
+  test_GUID_persistance(createSeparatorTxn);
+});
 
-  // Create livemark.
-  var createLivemarkTxn = txnsvc.createLivemark(uri("http://feeduri.com"),
-                                               uri("http://siteuri.com"),
-                                               "Test livemark",
-                                               bmsvc.unfiledBookmarksFolder,
-                                               bmsvc.DEFAULT_INDEX);
+add_test(function tag_uri() {
+  let tagURITxn = new PlacesTagURITransaction(
+    NetUtil.newURI("http://www.example.com"), ["foo"]
+  );
+  test_GUID_persistance(tagURITxn);
+});
+
+add_test(function create_livemark() {
+  let createLivemarkTxn = new PlacesCreateLivemarkTransaction(
+    NetUtil.newURI("http://feeduri.com"), NetUtil.newURI("http://siteuri.com"),
+    "Test livemark", PlacesUtils.unfiledBookmarksFolderId,
+    PlacesUtils.bookmarks.DEFAULT_INDEX
+  );
   test_GUID_persistance(createLivemarkTxn);
+});
 
-  // Tag URI.
-  var tagURITxn = txnsvc.tagURI(uri("http://www.example.com"), ["foo"]);
-  test_GUID_persistance(tagURITxn);
-}
--- a/browser/fuel/src/fuelApplication.js
+++ b/browser/fuel/src/fuelApplication.js
@@ -50,17 +50,18 @@ var Utilities = {
     let bookmarks = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
                     getService(Ci.nsINavBookmarksService);
     this.__defineGetter__("bookmarks", function() bookmarks);
     return this.bookmarks;
   },
 
   get livemarks() {
     let livemarks = Cc["@mozilla.org/browser/livemark-service;2"].
-                    getService(Ci.nsILivemarkService);
+                    getService[Ci.mozIAsyncLivemarks].
+                    QueryInterface(Ci.nsILivemarkService);
     this.__defineGetter__("livemarks", function() livemarks);
     return this.livemarks;
   },
 
   get annotations() {
     let annotations = Cc["@mozilla.org/browser/annotation-service;1"].
                       getService(Ci.nsIAnnotationService);
     this.__defineGetter__("annotations", function() annotations);
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -208,16 +208,21 @@ menuitem.bookmark-item {
 }
 
 .bookmark-item[container][livemark] { 
   list-style-image: url("chrome://browser/skin/feeds/feedIcon16.png");
 }
 
 .bookmark-item[container][livemark] .bookmark-item {
   list-style-image: url("chrome://browser/skin/places/livemark-item.png");
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
+}
+
+.bookmark-item[container][livemark] .bookmark-item[visited] {
+  -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 .bookmark-item[container][query] {
   list-style-image: url("chrome://browser/skin/places/query.png");
 }
 
 .bookmark-item[query][tagContainer] {
   list-style-image: url("chrome://browser/skin/places/tag.png");
index 1ed34429cca0204a19332ed5d9ef421f98049629..8ef1ba4a5cd268f4549fa2b511d6d47f8b46333e
GIT binary patch
literal 3861
zc$@(h59;uVP)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^000U@X+uL$Nkc;*
zaB^>EX>4Tx0C?J+Q+HUC_ZB|i_hk=OLfG)Jmu!ImA|tE_$Pihg5Rw34gb)%y#f69p
zRumNxoJdu~g4GI0orvO~D7a@qiilc^Ra`jkAKa(4eR}Wh?fcjJyyu+f{LXpL4}cL8
zCXwc%Y5+M>g*-agACFH+#L2yY0u@N$1RxOR%fe>`#Q*^C19^CUbg)1C0k3ZW0swH;
zE+i7i;s1lWP$pLZAdvvzA`<5d0gzGv$SzdK6adH=0I*ZDWC{S3003-xd_p1ssto|_
z^hrJi0NAOM+!p}Yq8zCR0F40vnJ7mj0zkU}U{!%qECRs70HCZuA}$2Lt^t5qwlYTo
zfV~9(c8*w(4?ti5fSE!p%m5%b0suoE6U_r4Oaq`W(!b!TUvP!ENC5!A%azTSOVTqG
zxRuZvck=My;vwR~Y_URN7by^C3FIQ2mzyIKNaq7g&I|wm8u`(|{y0C7=jP<$=4R(?
z@ASo@{%i1WB0eGU-~POe0t5gMPS5Y!U*+Z218~Oyuywy{sapWrRsd+<`CT*H37}dE
z(0cicc{uz)9-g64$UGe!3JVMEC1RnyFyo6p|1;rl;ER6t{6HT5+j{T-ahgDxt-zy$
z{c&M#cCJ#6=gR~_F>d$gBmT#QfBlXr(c(0*Tr3re@mPttP$EsodAU-NL?OwQ;u7h9
zGVvdl{RxwI4FIf$Pry#L2er#=z<%xl0*ek<(slqqe)BDi8VivC5N9+pdG`PSlfU_o
zKq~<N&6lL(006w`7+k277fi+o002awfhw>;2Moa!tiTSO!5zH77Xo1hL_iEAz&sE_
z2IPPo3ZWR5K^auQI@koYumc*P5t`u;w81er4d>tzT!HIw7Y1M$p28Tsh6w~g$Osc*
zAv%Z=Vvg7%&IlKojszlMNHmgwq#)^t6j36@$a16tsX}UzT}UJHEpik&ja)$bklV;0
zGK&0)yhkyVfwEBp)B<%txu_o+ipHRG(R4HqU4WLNYtb6C9zB4zqNmYI=yh}eeTt4_
zfYC7yW{lZkT#ScBV2M~7CdU?I<ybXVk2PZ*ST}YR8^E4n?+7FUi+~gC2wsE`!fb+&
zkVjZdSVO2K>?5=ix(HVZgM=}{CnA%mPqZa^68Xe<Vmh&qSVpWS?jar_o+Vx<4ijIK
zNF)x)lH^VbAtjJ9NefA9NZUv)q*J6m(hzB!OeX7)ZOPu`2(o~zAeWK1kPnbglKaWS
z<hK+$#faie38ExYq?8g$HDy2L1f`!cLYbhdQO&8I)Cj7GI-goeZJ>5gFH?u96Et<2
zCC!@_L(8Nsqt(!wX=iEoXfNq>x(VHb9z~bXm(pwK2kGbOgY<U{4TcSa$4Fu*8EYAP
z8K)Sx884YkrUlcNnaETy*D@QKXP6I|Z&g?-_9}c8k;)R4I+a$HewF8{R8@0TKh=4v
z3skFB5362QeWpfLvryxy3Dg#=)u|m-yQwy=&Qf<$k5JE1U!%TX{et>q4YG!XMxcgB
zqf}$J#u<$v7REAV@mNCEa#jQDENhreVq3EL>`ZnA`x|yIdrVV9bE;;nW|3x{=5fsd
z4#u(I@HyF>O3oq94bFQl11&!-vDRv>X03j$H`;pIzS?5#a_tuF>)P*iaGgM%ES>c_
zZ94aL3A#4AQM!e?+jY<CKGS3CdFcuD%JmNE-O)$&ZS<q{7wYfU@6jJOFf<4@kQr<-
zIAie4kYng;m}$7t@Py&05zA=0k;G`D(Mh8xxF+t0XX7<^7d~dJZyaK*G~Q+0Ydm3M
zX)@cS#H7XKzA4R=Yno=d(X`Wa%*@Cv+^pEF$?T3f)tqadVZPbC+x(4%rA3^@N{cp&
z$Clcbe9HxvO_ukpm{vYkc~<pS*Q`m_T<a|BZPr(8P#ag944XQe%eJVko2|rln{D3|
z;uMc5(kb;*ZrU;I{Ok(sn(PMcIrd@pCH8Ih&mGJh5*^k%bUS=<bal*jY;e5mq~SEf
zsl=(n=~rhPXQ6YQ^EDTyOOVSFmv)yIQ*Eb;r*5Bm%a!FC?z+;o)Agg9yPMpt*=^L_
z%ss_@tNTqZn;Xep!#(do^zips;&II5ou`|p!t;>lFJ5+DSzi0S9#6BJCZ5(XZOGfi
zTj0IRdtf>~J!SgN=>tB-J_4V5pNGDtz9Qc}z9W9tewls;{GR(e`pf-~_`l(K@)q$<
z1z-We0p$U`ff|9c18V~x1epY-2Q>wa1-k|>3_cY?3<(WcA99m#z!&lx`C~KOXDpi0
z70L*m6<QnmFw7=Q9@Y_#hR+D!5Pol_`Aq4|wg`yeM{J0=A88qx7x{e@DJn9mF6vRV
zQ*?23_bk?|<XQV?y^isZsf@Wh+iJFQc4w?=Y*K7v?3=iNxT?5;c!&5!@s|>G6C?@k
ziR8rC#65}Qa{}jVnlqf_npBo_W3J`gqPZ95>CVfZcRX1&S&)1<g_shTvOnd6AVN?t
z7*FM=ZcQB%@`Rg(Pes0>jiOPpx423?lIEROmG(H@JAFg?XogQlb;dIZPf{y+kr|S?
zBlAsGMAqJ{&)IR=Ejg5&l$@hd4QZCNE7vf$D7Q~$D=U)?<ay?8${Ul1%J<|W`E&Ez
z6>Nn}(WA6du22pZOfRS_cv~1-c(_QtNLti0-)8>m`6CO07JR*suu!<Lv)H(JS@GZ^
zzeT$iBa2fPcP=qqQo3Y#Y4Fm0%V^88mi<uTSW;E;YI)r9j#7itrKLkFf>$(^sg%jf
zZm#rNxnmV!m1I@#YM0epR(~oNm0zrItf;Q|utvD%;#W>z)qM4NZQ9!2O1H}G>qzUQ
z>u#*~S--DJy=p<#(1!30tsC);<r`mZO5Sv#dTRBK&9u$R%>y-IHSJr>wyfLop*ExT
zdYyk=%U1oZtGB+{Cfe4&-FJKQ4uc&PJKpb<?7X!rcvow^MSb;d((Z!Yj~Zedy1(Xr
z-MB}0PsN^(d!>5^_C@dOYIJXG+^@gCvI%WcHjN%gI&kHifN$EH?V5MBa9S!3!a?Q1
zC*P)gd*e{(q0YnH!_D8Bf4B7r>qvPk(mKC&tSzH$pgp0z@92!9ogH2sN4~fJe(y2k
zV|B+hk5`_cohUu=`Q(C=<ELb&o}ErVJ=B@pdG}2GnQL89UA<>R&z?UQbnZ;IU-!xL
z-sg{9@Vs#JBKKn3CAUkhJ+3`ResKNaNUvLO>t*-L?N>ambo5Q@JJIjcfBI^`)pOVQ
z*DhV3dA;w(>>IakCfyvkCA#(acJ}QTcM9%I++BK)c(44v+WqPW`VZ=VwEnSWz-{38
zV8CF{!&wjS4he^z{*?dIhvCvk%tzHDMk9@nogW_?4H~`jWX_Y}r?RIL&&qyQ|9R_k
ztLNYS;`>X_Sp3-V3;B!Bzpi<y^K$R2sjoW6BgY@S&UroYru?nW+kNl2@4DZ|y&st<
z{6PLt^U?Za$EVOw_de%*{`@cZg!B7=IVBMQ000SaNLh0L01FcU01FcV0GgZ_00007
zbV*G`2iyS;5H}ZlWv=u9000JJOGiWi{{a60|De66lK=n&Q%OWYR7gvel}l_JRTzbh
zvH&3#kQEyeRAqtGq=0DRAVJ#=VgZXv?2%xJ$c80rB*ca)Z2C@U^R|=NZXEKe6Ud`!
zn~>%OeWYz1Cw82fvB&W|Jf0bI`2QOxlcFrbNJsb1_4)2SbMNmN-|h`x1%lO;2)<c^
zXq_M7nzE`7wbkA|d)P}1vp(;7>3?eP;)(vb>HEqV`5aE95zehfxFjdyKe}a+7s0oh
zm=%+~eeU(?`->R)<L<G<US<S~_KF%OdJd&T7$sLP%MfxM{m|GUB|>0^S)L>|J%?mk
zf?FybOYCK4FF^PmzY}VNZOO1K6PB_J%XUz7NYq+~#ADprmISBY4`z9ip@~^IZV9Gk
zV@FY6V2%=dnJEXT_B(xkSmrjY^eo)SDU>4b!k+#T#dsJ6%Ys#OgbHO@W*W?JP4Fax
zu^BPxR$4*Vt(Z`3W&uw(QX*905X)jOGvxp^ekb6EsgqfgV6FZP`|h_Cq#mW-Q*eep
zML}MHVHL}=VHzp80WZM7*c5EXg{qlY_-hT5_m>cePM|Y9hRE0qwq;dt`(iIMUVtt?
z3@rs+*I~+!pqsQ%UO{pGN4OnzaC;kJq*uhaZd$_YbT%9Wh>T9sak<Fr7SeJ~_|&|C
zdk-GsX5SEcXh%{z*)m@gUS_-i?G4cKTQHI{aD#PldOt*A_6KOYSr|*La9e9(_nsB^
zdBcLHCBe*ofY9*o;%wtd3GJa#diogd{JDxOg;@OiDSizOA{ZSP_sp}G8LtLzG$2m_
zcGWb@2Nz&Rzkqv<7VY?i#v~L*zk_?V7RKTg<n#i0H^B_EJW2o1gg9GS)iAgGn6`HY
zEj<GW4BQrDx2fX!eqnV@@a$#A+kut_<kSQuG@+_lWOKXFR{G#JpM){|J=F9DoGb66
z*#DXE<Z=|C#oK}4;J7F@{!Py5P)N&<p5sb;h>CF@DXM|izySK`soBF`X1oB`8lYwq
zP^CB(7rkgYKSnmApb-8BPIEo7yBf^M*Kn`bl4pZLCcw=84)Bv21sh2zht9|tx=1@2
z4Zn@w!S(J41u_t&s&DOyQkb0ZGUElfT#rm<0~u)(rSA9Ow0!_YP9s0x0r$d5WH%o|
zoB9cE3k7&SDZKWj`hx(xpw0nk^0xkAQFtk37xOD?xZKu<^`wlcxfQeoqIeQd2`@9=
zi|ArK<V+kpbYAjK0<x5(z79#+M&{W)NQy$^Nhs^or=5|NIGEXg5p{+}piy-*vni?A
zqMhLW76p1t3#ODjjj4FDkwz+$7hYz(SMk-eP?x%Cp><OHKU(+3<#n+*dzsmP6$b}n
zSc@l-r@!cN#9n6h0tDZvMDwdn_Qf-BeyJy&7OmZUT4=w&_glGt=?u{PS`)Kkk`o_Q
z@tL;K)*naW{D~3l-siZYlAngR^u^EdQJ-Y;u$P#F&++;5)Sh_RS5@`OvBX}%_<a8Y
X?5nX&f{nAe00000NkvXXu0mjfkCJEf
--- a/browser/themes/gnomestripe/places/places.css
+++ b/browser/themes/gnomestripe/places/places.css
@@ -23,16 +23,21 @@ treechildren::-moz-tree-image(title) {
   margin: 0px 2px;
   width: 16px;
   height: 16px;
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
 }
 
 treechildren::-moz-tree-image(title, livemarkItem) {
   list-style-image: url("chrome://browser/skin/places/livemark-item.png");
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
+}
+
+treechildren::-moz-tree-image(title, livemarkItem, visited) {
+  -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 treechildren::-moz-tree-image(title, separator) {
   list-style-image: none;
   width: 0;
   height: 0;
 }
 
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -253,17 +253,22 @@ toolbarbutton.bookmark-item > menupopup 
   list-style-image: url("chrome://global/skin/tree/folder.png");
 }
 
 .bookmark-item[query][hostContainer][open] {
   list-style-image: url("chrome://global/skin/tree/folder.png");
 }
 
 .bookmark-item[livemark] .menuitem-iconic {
-  list-style-image: url("chrome://browser/skin/livemark-item.png");
+  list-style-image: url("chrome://browser/skin/places/livemark-item.png");
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
+}
+
+.bookmark-item[livemark] .menuitem-iconic[visited] {
+  -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 .bookmark-item menuitem[openInTabs],
 .bookmark-item menuitem[siteURI] {
   list-style-image: none;
 }
 
 #wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box {
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -24,17 +24,16 @@ browser.jar:
   skin/classic/browser/hud-style-twisties.png
   skin/classic/browser/identity.png
   skin/classic/browser/Info.png
   skin/classic/browser/KUI-background.png
   skin/classic/browser/KUI-close.png
   skin/classic/browser/menu-back.png
   skin/classic/browser/menu-forward.png
   skin/classic/browser/page-livemarks.png
-  skin/classic/browser/livemark-item.png
   skin/classic/browser/pageInfo.css
   skin/classic/browser/Privacy-16.png
   skin/classic/browser/Privacy-48.png
   skin/classic/browser/reload-stop-go.png
   skin/classic/browser/searchbar-dropmarker.png
   skin/classic/browser/searchbar.css
   skin/classic/browser/Search.png
   skin/classic/browser/section_collapsed.png
@@ -85,16 +84,17 @@ browser.jar:
   skin/classic/browser/places/twisty-open.gif               (places/twisty-open.gif)
   skin/classic/browser/places/twisty-closed.gif             (places/twisty-closed.gif)
   skin/classic/browser/places/tag.png                       (places/tag.png)
   skin/classic/browser/places/downloads.png                 (places/downloads.png)
   skin/classic/browser/places/expander-closed-active.png    (places/expander-closed-active.png)
   skin/classic/browser/places/expander-closed.png           (places/expander-closed.png)
   skin/classic/browser/places/expander-open-active.png      (places/expander-open-active.png)
   skin/classic/browser/places/expander-open.png             (places/expander-open.png)
+  skin/classic/browser/places/livemark-item.png             (places/livemark-item.png)
   skin/classic/browser/preferences/alwaysAsk.png            (preferences/alwaysAsk.png)
   skin/classic/browser/preferences/application.png          (preferences/application.png)
   skin/classic/browser/preferences/Options.png              (preferences/Options.png)
 #ifdef MOZ_SERVICES_SYNC
   skin/classic/browser/preferences/Options-sync.png         (preferences/Options-sync.png)
 #endif
   skin/classic/browser/preferences/saveFile.png             (preferences/saveFile.png)
 * skin/classic/browser/preferences/preferences.css          (preferences/preferences.css)
deleted file mode 100644
index 32af074ad846aad169f5953d8dad64e10feb2350..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..8ef1ba4a5cd268f4549fa2b511d6d47f8b46333e
GIT binary patch
literal 3861
zc$@(h59;uVP)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^000U@X+uL$Nkc;*
zaB^>EX>4Tx0C?J+Q+HUC_ZB|i_hk=OLfG)Jmu!ImA|tE_$Pihg5Rw34gb)%y#f69p
zRumNxoJdu~g4GI0orvO~D7a@qiilc^Ra`jkAKa(4eR}Wh?fcjJyyu+f{LXpL4}cL8
zCXwc%Y5+M>g*-agACFH+#L2yY0u@N$1RxOR%fe>`#Q*^C19^CUbg)1C0k3ZW0swH;
zE+i7i;s1lWP$pLZAdvvzA`<5d0gzGv$SzdK6adH=0I*ZDWC{S3003-xd_p1ssto|_
z^hrJi0NAOM+!p}Yq8zCR0F40vnJ7mj0zkU}U{!%qECRs70HCZuA}$2Lt^t5qwlYTo
zfV~9(c8*w(4?ti5fSE!p%m5%b0suoE6U_r4Oaq`W(!b!TUvP!ENC5!A%azTSOVTqG
zxRuZvck=My;vwR~Y_URN7by^C3FIQ2mzyIKNaq7g&I|wm8u`(|{y0C7=jP<$=4R(?
z@ASo@{%i1WB0eGU-~POe0t5gMPS5Y!U*+Z218~Oyuywy{sapWrRsd+<`CT*H37}dE
z(0cicc{uz)9-g64$UGe!3JVMEC1RnyFyo6p|1;rl;ER6t{6HT5+j{T-ahgDxt-zy$
z{c&M#cCJ#6=gR~_F>d$gBmT#QfBlXr(c(0*Tr3re@mPttP$EsodAU-NL?OwQ;u7h9
zGVvdl{RxwI4FIf$Pry#L2er#=z<%xl0*ek<(slqqe)BDi8VivC5N9+pdG`PSlfU_o
zKq~<N&6lL(006w`7+k277fi+o002awfhw>;2Moa!tiTSO!5zH77Xo1hL_iEAz&sE_
z2IPPo3ZWR5K^auQI@koYumc*P5t`u;w81er4d>tzT!HIw7Y1M$p28Tsh6w~g$Osc*
zAv%Z=Vvg7%&IlKojszlMNHmgwq#)^t6j36@$a16tsX}UzT}UJHEpik&ja)$bklV;0
zGK&0)yhkyVfwEBp)B<%txu_o+ipHRG(R4HqU4WLNYtb6C9zB4zqNmYI=yh}eeTt4_
zfYC7yW{lZkT#ScBV2M~7CdU?I<ybXVk2PZ*ST}YR8^E4n?+7FUi+~gC2wsE`!fb+&
zkVjZdSVO2K>?5=ix(HVZgM=}{CnA%mPqZa^68Xe<Vmh&qSVpWS?jar_o+Vx<4ijIK
zNF)x)lH^VbAtjJ9NefA9NZUv)q*J6m(hzB!OeX7)ZOPu`2(o~zAeWK1kPnbglKaWS
z<hK+$#faie38ExYq?8g$HDy2L1f`!cLYbhdQO&8I)Cj7GI-goeZJ>5gFH?u96Et<2
zCC!@_L(8Nsqt(!wX=iEoXfNq>x(VHb9z~bXm(pwK2kGbOgY<U{4TcSa$4Fu*8EYAP
z8K)Sx884YkrUlcNnaETy*D@QKXP6I|Z&g?-_9}c8k;)R4I+a$HewF8{R8@0TKh=4v
z3skFB5362QeWpfLvryxy3Dg#=)u|m-yQwy=&Qf<$k5JE1U!%TX{et>q4YG!XMxcgB
zqf}$J#u<$v7REAV@mNCEa#jQDENhreVq3EL>`ZnA`x|yIdrVV9bE;;nW|3x{=5fsd
z4#u(I@HyF>O3oq94bFQl11&!-vDRv>X03j$H`;pIzS?5#a_tuF>)P*iaGgM%ES>c_
zZ94aL3A#4AQM!e?+jY<CKGS3CdFcuD%JmNE-O)$&ZS<q{7wYfU@6jJOFf<4@kQr<-
zIAie4kYng;m}$7t@Py&05zA=0k;G`D(Mh8xxF+t0XX7<^7d~dJZyaK*G~Q+0Ydm3M
zX)@cS#H7XKzA4R=Yno=d(X`Wa%*@Cv+^pEF$?T3f)tqadVZPbC+x(4%rA3^@N{cp&
z$Clcbe9HxvO_ukpm{vYkc~<pS*Q`m_T<a|BZPr(8P#ag944XQe%eJVko2|rln{D3|
z;uMc5(kb;*ZrU;I{Ok(sn(PMcIrd@pCH8Ih&mGJh5*^k%bUS=<bal*jY;e5mq~SEf
zsl=(n=~rhPXQ6YQ^EDTyOOVSFmv)yIQ*Eb;r*5Bm%a!FC?z+;o)Agg9yPMpt*=^L_
z%ss_@tNTqZn;Xep!#(do^zips;&II5ou`|p!t;>lFJ5+DSzi0S9#6BJCZ5(XZOGfi
zTj0IRdtf>~J!SgN=>tB-J_4V5pNGDtz9Qc}z9W9tewls;{GR(e`pf-~_`l(K@)q$<
z1z-We0p$U`ff|9c18V~x1epY-2Q>wa1-k|>3_cY?3<(WcA99m#z!&lx`C~KOXDpi0
z70L*m6<QnmFw7=Q9@Y_#hR+D!5Pol_`Aq4|wg`yeM{J0=A88qx7x{e@DJn9mF6vRV
zQ*?23_bk?|<XQV?y^isZsf@Wh+iJFQc4w?=Y*K7v?3=iNxT?5;c!&5!@s|>G6C?@k
ziR8rC#65}Qa{}jVnlqf_npBo_W3J`gqPZ95>CVfZcRX1&S&)1<g_shTvOnd6AVN?t
z7*FM=ZcQB%@`Rg(Pes0>jiOPpx423?lIEROmG(H@JAFg?XogQlb;dIZPf{y+kr|S?
zBlAsGMAqJ{&)IR=Ejg5&l$@hd4QZCNE7vf$D7Q~$D=U)?<ay?8${Ul1%J<|W`E&Ez
z6>Nn}(WA6du22pZOfRS_cv~1-c(_QtNLti0-)8>m`6CO07JR*suu!<Lv)H(JS@GZ^
zzeT$iBa2fPcP=qqQo3Y#Y4Fm0%V^88mi<uTSW;E;YI)r9j#7itrKLkFf>$(^sg%jf
zZm#rNxnmV!m1I@#YM0epR(~oNm0zrItf;Q|utvD%;#W>z)qM4NZQ9!2O1H}G>qzUQ
z>u#*~S--DJy=p<#(1!30tsC);<r`mZO5Sv#dTRBK&9u$R%>y-IHSJr>wyfLop*ExT
zdYyk=%U1oZtGB+{Cfe4&-FJKQ4uc&PJKpb<?7X!rcvow^MSb;d((Z!Yj~Zedy1(Xr
z-MB}0PsN^(d!>5^_C@dOYIJXG+^@gCvI%WcHjN%gI&kHifN$EH?V5MBa9S!3!a?Q1
zC*P)gd*e{(q0YnH!_D8Bf4B7r>qvPk(mKC&tSzH$pgp0z@92!9ogH2sN4~fJe(y2k
zV|B+hk5`_cohUu=`Q(C=<ELb&o}ErVJ=B@pdG}2GnQL89UA<>R&z?UQbnZ;IU-!xL
z-sg{9@Vs#JBKKn3CAUkhJ+3`ResKNaNUvLO>t*-L?N>ambo5Q@JJIjcfBI^`)pOVQ
z*DhV3dA;w(>>IakCfyvkCA#(acJ}QTcM9%I++BK)c(44v+WqPW`VZ=VwEnSWz-{38
zV8CF{!&wjS4he^z{*?dIhvCvk%tzHDMk9@nogW_?4H~`jWX_Y}r?RIL&&qyQ|9R_k
ztLNYS;`>X_Sp3-V3;B!Bzpi<y^K$R2sjoW6BgY@S&UroYru?nW+kNl2@4DZ|y&st<
z{6PLt^U?Za$EVOw_de%*{`@cZg!B7=IVBMQ000SaNLh0L01FcU01FcV0GgZ_00007
zbV*G`2iyS;5H}ZlWv=u9000JJOGiWi{{a60|De66lK=n&Q%OWYR7gvel}l_JRTzbh
zvH&3#kQEyeRAqtGq=0DRAVJ#=VgZXv?2%xJ$c80rB*ca)Z2C@U^R|=NZXEKe6Ud`!
zn~>%OeWYz1Cw82fvB&W|Jf0bI`2QOxlcFrbNJsb1_4)2SbMNmN-|h`x1%lO;2)<c^
zXq_M7nzE`7wbkA|d)P}1vp(;7>3?eP;)(vb>HEqV`5aE95zehfxFjdyKe}a+7s0oh
zm=%+~eeU(?`->R)<L<G<US<S~_KF%OdJd&T7$sLP%MfxM{m|GUB|>0^S)L>|J%?mk
zf?FybOYCK4FF^PmzY}VNZOO1K6PB_J%XUz7NYq+~#ADprmISBY4`z9ip@~^IZV9Gk
zV@FY6V2%=dnJEXT_B(xkSmrjY^eo)SDU>4b!k+#T#dsJ6%Ys#OgbHO@W*W?JP4Fax
zu^BPxR$4*Vt(Z`3W&uw(QX*905X)jOGvxp^ekb6EsgqfgV6FZP`|h_Cq#mW-Q*eep
zML}MHVHL}=VHzp80WZM7*c5EXg{qlY_-hT5_m>cePM|Y9hRE0qwq;dt`(iIMUVtt?
z3@rs+*I~+!pqsQ%UO{pGN4OnzaC;kJq*uhaZd$_YbT%9Wh>T9sak<Fr7SeJ~_|&|C
zdk-GsX5SEcXh%{z*)m@gUS_-i?G4cKTQHI{aD#PldOt*A_6KOYSr|*La9e9(_nsB^
zdBcLHCBe*ofY9*o;%wtd3GJa#diogd{JDxOg;@OiDSizOA{ZSP_sp}G8LtLzG$2m_
zcGWb@2Nz&Rzkqv<7VY?i#v~L*zk_?V7RKTg<n#i0H^B_EJW2o1gg9GS)iAgGn6`HY
zEj<GW4BQrDx2fX!eqnV@@a$#A+kut_<kSQuG@+_lWOKXFR{G#JpM){|J=F9DoGb66
z*#DXE<Z=|C#oK}4;J7F@{!Py5P)N&<p5sb;h>CF@DXM|izySK`soBF`X1oB`8lYwq
zP^CB(7rkgYKSnmApb-8BPIEo7yBf^M*Kn`bl4pZLCcw=84)Bv21sh2zht9|tx=1@2
z4Zn@w!S(J41u_t&s&DOyQkb0ZGUElfT#rm<0~u)(rSA9Ow0!_YP9s0x0r$d5WH%o|
zoB9cE3k7&SDZKWj`hx(xpw0nk^0xkAQFtk37xOD?xZKu<^`wlcxfQeoqIeQd2`@9=
zi|ArK<V+kpbYAjK0<x5(z79#+M&{W)NQy$^Nhs^or=5|NIGEXg5p{+}piy-*vni?A
zqMhLW76p1t3#ODjjj4FDkwz+$7hYz(SMk-eP?x%Cp><OHKU(+3<#n+*dzsmP6$b}n
zSc@l-r@!cN#9n6h0tDZvMDwdn_Qf-BeyJy&7OmZUT4=w&_glGt=?u{PS`)Kkk`o_Q
z@tL;K)*naW{D~3l-siZYlAngR^u^EdQJ-Y;u$P#F&++;5)Sh_RS5@`OvBX}%_<a8Y
X?5nX&f{nAe00000NkvXXu0mjfkCJEf
--- a/browser/themes/pinstripe/places/places.css
+++ b/browser/themes/pinstripe/places/places.css
@@ -92,17 +92,22 @@ treechildren::-moz-tree-image(title) {
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
   -moz-padding-end: 2px;
   margin: 0px 2px;
   width: 16px;
   height: 16px;
 }
 
 treechildren::-moz-tree-image(title, livemarkItem) {
-  list-style-image: url("chrome://browser/skin/livemark-item.png");
+  list-style-image: url("chrome://browser/skin/places/livemark-item.png");
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
+}
+
+treechildren::-moz-tree-image(title, livemarkItem, visited) {
+  -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 treechildren::-moz-tree-image(title, container),
 treechildren::-moz-tree-image(title, open) {
   list-style-image: url("chrome://global/skin/tree/folder.png");
   -moz-image-region: rect(0, 16px, 16px, 0);
 }
 
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -604,18 +604,22 @@ menuitem.bookmark-item {
 }
 
 .bookmark-item[container][livemark] { 
   list-style-image: url("chrome://browser/skin/livemark-folder.png");
   -moz-image-region: auto;
 }
 
 .bookmark-item[container][livemark] .bookmark-item {
-  list-style-image: url("chrome://browser/skin/livemark-item.png");
-  -moz-image-region: auto;
+  list-style-image: url("chrome://browser/skin/places/livemark-item.png");
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
+}
+
+.bookmark-item[container][livemark] .bookmark-item[visited] {
+  -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 .bookmark-item[container][query] {
   list-style-image: url("chrome://browser/skin/places/query.png");
   -moz-image-region: auto;
 }
 
 .bookmark-item[query][tagContainer] {
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -22,17 +22,16 @@ browser.jar:
         skin/classic/browser/Info.png                                (Info.png)
         skin/classic/browser/identity.png                            (identity.png)
         skin/classic/browser/keyhole-forward-mask.svg
         skin/classic/browser/KUI-background.png
         skin/classic/browser/KUI-close.png
         skin/classic/browser/pageInfo.css
         skin/classic/browser/pageInfo.png                            (pageInfo.png)
         skin/classic/browser/page-livemarks.png                      (feeds/feedIcon16.png)
-        skin/classic/browser/livemark-item.png                       (livemark-item.png)
         skin/classic/browser/livemark-folder.png                     (livemark-folder.png)
         skin/classic/browser/Privacy-16.png
         skin/classic/browser/Privacy-48.png
         skin/classic/browser/reload-stop-go.png
         skin/classic/browser/Secure24.png                            (Secure24.png)
         skin/classic/browser/Toolbar.png                             (Toolbar.png)
         skin/classic/browser/Toolbar-inverted.png
         skin/classic/browser/toolbarbutton-dropdown-arrow.png
@@ -75,16 +74,17 @@ browser.jar:
         skin/classic/browser/places/libraryToolbar.png               (places/libraryToolbar.png)
         skin/classic/browser/places/starred48.png                    (places/starred48.png)
         skin/classic/browser/places/unstarred48.png                  (places/unstarred48.png)
         skin/classic/browser/places/tag.png                          (places/tag.png)
         skin/classic/browser/places/history.png                      (places/history.png)
         skin/classic/browser/places/allBookmarks.png                 (places/allBookmarks.png)
         skin/classic/browser/places/unsortedBookmarks.png            (places/unsortedBookmarks.png)
         skin/classic/browser/places/downloads.png                    (places/downloads.png)
+        skin/classic/browser/places/livemark-item.png                (places/livemark-item.png)
         skin/classic/browser/preferences/alwaysAsk.png               (preferences/alwaysAsk.png)
         skin/classic/browser/preferences/application.png             (preferences/application.png)
         skin/classic/browser/preferences/mail.png                    (preferences/mail.png)
         skin/classic/browser/preferences/Options.png                 (preferences/Options.png)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/browser/preferences/Options-sync.png            (preferences/Options-sync.png)
 #endif
         skin/classic/browser/preferences/saveFile.png                (preferences/saveFile.png)
@@ -191,17 +191,16 @@ browser.jar:
         skin/classic/aero/browser/Info.png                           (Info-aero.png)
         skin/classic/aero/browser/identity.png                       (identity-aero.png)
         skin/classic/aero/browser/keyhole-forward-mask.svg
         skin/classic/aero/browser/KUI-background.png
         skin/classic/aero/browser/KUI-close.png
         skin/classic/aero/browser/pageInfo.css
         skin/classic/aero/browser/pageInfo.png                       (pageInfo-aero.png)
         skin/classic/aero/browser/page-livemarks.png                 (feeds/feedIcon16-aero.png)
-        skin/classic/aero/browser/livemark-item.png                  (livemark-item-aero.png)
         skin/classic/aero/browser/livemark-folder.png                (livemark-folder-aero.png)
         skin/classic/aero/browser/Privacy-16.png                     (Privacy-16-aero.png)
         skin/classic/aero/browser/Privacy-48.png                     (Privacy-48-aero.png)
         skin/classic/aero/browser/reload-stop-go.png
         skin/classic/aero/browser/Secure24.png                       (Secure24-aero.png)
         skin/classic/aero/browser/Toolbar.png
         skin/classic/aero/browser/Toolbar-inverted.png
         skin/classic/aero/browser/toolbarbutton-dropdown-arrow.png
@@ -244,16 +243,17 @@ browser.jar:
         skin/classic/aero/browser/places/libraryToolbar.png          (places/libraryToolbar-aero.png)
         skin/classic/aero/browser/places/starred48.png               (places/starred48-aero.png)
         skin/classic/aero/browser/places/unstarred48.png             (places/unstarred48.png)
         skin/classic/aero/browser/places/tag.png                     (places/tag-aero.png)
         skin/classic/aero/browser/places/history.png                 (places/history-aero.png)
         skin/classic/aero/browser/places/allBookmarks.png            (places/allBookmarks-aero.png)
         skin/classic/aero/browser/places/unsortedBookmarks.png       (places/unsortedBookmarks-aero.png)
         skin/classic/aero/browser/places/downloads.png               (places/downloads.png)
+        skin/classic/aero/browser/places/livemark-item.png           (places/livemark-item.png)
         skin/classic/aero/browser/preferences/alwaysAsk.png          (preferences/alwaysAsk-aero.png)
         skin/classic/aero/browser/preferences/application.png        (preferences/application-aero.png)
         skin/classic/aero/browser/preferences/mail.png               (preferences/mail-aero.png)
         skin/classic/aero/browser/preferences/Options.png            (preferences/Options-aero.png)
 #ifdef MOZ_SERVICES_SYNC
         skin/classic/aero/browser/preferences/Options-sync.png       (preferences/Options-sync.png)
 #endif
         skin/classic/aero/browser/preferences/saveFile.png           (preferences/saveFile-aero.png)
deleted file mode 100644
index 1fa03b78bc21c957fcd50614653988c524230707..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 83139be73329171d44e5baea573c43c482c77ec6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..8ef1ba4a5cd268f4549fa2b511d6d47f8b46333e
GIT binary patch
literal 3861
zc$@(h59;uVP)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^000U@X+uL$Nkc;*
zaB^>EX>4Tx0C?J+Q+HUC_ZB|i_hk=OLfG)Jmu!ImA|tE_$Pihg5Rw34gb)%y#f69p
zRumNxoJdu~g4GI0orvO~D7a@qiilc^Ra`jkAKa(4eR}Wh?fcjJyyu+f{LXpL4}cL8
zCXwc%Y5+M>g*-agACFH+#L2yY0u@N$1RxOR%fe>`#Q*^C19^CUbg)1C0k3ZW0swH;
zE+i7i;s1lWP$pLZAdvvzA`<5d0gzGv$SzdK6adH=0I*ZDWC{S3003-xd_p1ssto|_
z^hrJi0NAOM+!p}Yq8zCR0F40vnJ7mj0zkU}U{!%qECRs70HCZuA}$2Lt^t5qwlYTo
zfV~9(c8*w(4?ti5fSE!p%m5%b0suoE6U_r4Oaq`W(!b!TUvP!ENC5!A%azTSOVTqG
zxRuZvck=My;vwR~Y_URN7by^C3FIQ2mzyIKNaq7g&I|wm8u`(|{y0C7=jP<$=4R(?
z@ASo@{%i1WB0eGU-~POe0t5gMPS5Y!U*+Z218~Oyuywy{sapWrRsd+<`CT*H37}dE
z(0cicc{uz)9-g64$UGe!3JVMEC1RnyFyo6p|1;rl;ER6t{6HT5+j{T-ahgDxt-zy$
z{c&M#cCJ#6=gR~_F>d$gBmT#QfBlXr(c(0*Tr3re@mPttP$EsodAU-NL?OwQ;u7h9
zGVvdl{RxwI4FIf$Pry#L2er#=z<%xl0*ek<(slqqe)BDi8VivC5N9+pdG`PSlfU_o
zKq~<N&6lL(006w`7+k277fi+o002awfhw>;2Moa!tiTSO!5zH77Xo1hL_iEAz&sE_
z2IPPo3ZWR5K^auQI@koYumc*P5t`u;w81er4d>tzT!HIw7Y1M$p28Tsh6w~g$Osc*
zAv%Z=Vvg7%&IlKojszlMNHmgwq#)^t6j36@$a16tsX}UzT}UJHEpik&ja)$bklV;0
zGK&0)yhkyVfwEBp)B<%txu_o+ipHRG(R4HqU4WLNYtb6C9zB4zqNmYI=yh}eeTt4_
zfYC7yW{lZkT#ScBV2M~7CdU?I<ybXVk2PZ*ST}YR8^E4n?+7FUi+~gC2wsE`!fb+&
zkVjZdSVO2K>?5=ix(HVZgM=}{CnA%mPqZa^68Xe<Vmh&qSVpWS?jar_o+Vx<4ijIK
zNF)x)lH^VbAtjJ9NefA9NZUv)q*J6m(hzB!OeX7)ZOPu`2(o~zAeWK1kPnbglKaWS
z<hK+$#faie38ExYq?8g$HDy2L1f`!cLYbhdQO&8I)Cj7GI-goeZJ>5gFH?u96Et<2
zCC!@_L(8Nsqt(!wX=iEoXfNq>x(VHb9z~bXm(pwK2kGbOgY<U{4TcSa$4Fu*8EYAP
z8K)Sx884YkrUlcNnaETy*D@QKXP6I|Z&g?-_9}c8k;)R4I+a$HewF8{R8@0TKh=4v
z3skFB5362QeWpfLvryxy3Dg#=)u|m-yQwy=&Qf<$k5JE1U!%TX{et>q4YG!XMxcgB
zqf}$J#u<$v7REAV@mNCEa#jQDENhreVq3EL>`ZnA`x|yIdrVV9bE;;nW|3x{=5fsd
z4#u(I@HyF>O3oq94bFQl11&!-vDRv>X03j$H`;pIzS?5#a_tuF>)P*iaGgM%ES>c_
zZ94aL3A#4AQM!e?+jY<CKGS3CdFcuD%JmNE-O)$&ZS<q{7wYfU@6jJOFf<4@kQr<-
zIAie4kYng;m}$7t@Py&05zA=0k;G`D(Mh8xxF+t0XX7<^7d~dJZyaK*G~Q+0Ydm3M
zX)@cS#H7XKzA4R=Yno=d(X`Wa%*@Cv+^pEF$?T3f)tqadVZPbC+x(4%rA3^@N{cp&
z$Clcbe9HxvO_ukpm{vYkc~<pS*Q`m_T<a|BZPr(8P#ag944XQe%eJVko2|rln{D3|
z;uMc5(kb;*ZrU;I{Ok(sn(PMcIrd@pCH8Ih&mGJh5*^k%bUS=<bal*jY;e5mq~SEf
zsl=(n=~rhPXQ6YQ^EDTyOOVSFmv)yIQ*Eb;r*5Bm%a!FC?z+;o)Agg9yPMpt*=^L_
z%ss_@tNTqZn;Xep!#(do^zips;&II5ou`|p!t;>lFJ5+DSzi0S9#6BJCZ5(XZOGfi
zTj0IRdtf>~J!SgN=>tB-J_4V5pNGDtz9Qc}z9W9tewls;{GR(e`pf-~_`l(K@)q$<
z1z-We0p$U`ff|9c18V~x1epY-2Q>wa1-k|>3_cY?3<(WcA99m#z!&lx`C~KOXDpi0
z70L*m6<QnmFw7=Q9@Y_#hR+D!5Pol_`Aq4|wg`yeM{J0=A88qx7x{e@DJn9mF6vRV
zQ*?23_bk?|<XQV?y^isZsf@Wh+iJFQc4w?=Y*K7v?3=iNxT?5;c!&5!@s|>G6C?@k
ziR8rC#65}Qa{}jVnlqf_npBo_W3J`gqPZ95>CVfZcRX1&S&)1<g_shTvOnd6AVN?t
z7*FM=ZcQB%@`Rg(Pes0>jiOPpx423?lIEROmG(H@JAFg?XogQlb;dIZPf{y+kr|S?
zBlAsGMAqJ{&)IR=Ejg5&l$@hd4QZCNE7vf$D7Q~$D=U)?<ay?8${Ul1%J<|W`E&Ez
z6>Nn}(WA6du22pZOfRS_cv~1-c(_QtNLti0-)8>m`6CO07JR*suu!<Lv)H(JS@GZ^
zzeT$iBa2fPcP=qqQo3Y#Y4Fm0%V^88mi<uTSW;E;YI)r9j#7itrKLkFf>$(^sg%jf
zZm#rNxnmV!m1I@#YM0epR(~oNm0zrItf;Q|utvD%;#W>z)qM4NZQ9!2O1H}G>qzUQ
z>u#*~S--DJy=p<#(1!30tsC);<r`mZO5Sv#dTRBK&9u$R%>y-IHSJr>wyfLop*ExT
zdYyk=%U1oZtGB+{Cfe4&-FJKQ4uc&PJKpb<?7X!rcvow^MSb;d((Z!Yj~Zedy1(Xr
z-MB}0PsN^(d!>5^_C@dOYIJXG+^@gCvI%WcHjN%gI&kHifN$EH?V5MBa9S!3!a?Q1
zC*P)gd*e{(q0YnH!_D8Bf4B7r>qvPk(mKC&tSzH$pgp0z@92!9ogH2sN4~fJe(y2k
zV|B+hk5`_cohUu=`Q(C=<ELb&o}ErVJ=B@pdG}2GnQL89UA<>R&z?UQbnZ;IU-!xL
z-sg{9@Vs#JBKKn3CAUkhJ+3`ResKNaNUvLO>t*-L?N>ambo5Q@JJIjcfBI^`)pOVQ
z*DhV3dA;w(>>IakCfyvkCA#(acJ}QTcM9%I++BK)c(44v+WqPW`VZ=VwEnSWz-{38
zV8CF{!&wjS4he^z{*?dIhvCvk%tzHDMk9@nogW_?4H~`jWX_Y}r?RIL&&qyQ|9R_k
ztLNYS;`>X_Sp3-V3;B!Bzpi<y^K$R2sjoW6BgY@S&UroYru?nW+kNl2@4DZ|y&st<
z{6PLt^U?Za$EVOw_de%*{`@cZg!B7=IVBMQ000SaNLh0L01FcU01FcV0GgZ_00007
zbV*G`2iyS;5H}ZlWv=u9000JJOGiWi{{a60|De66lK=n&Q%OWYR7gvel}l_JRTzbh
zvH&3#kQEyeRAqtGq=0DRAVJ#=VgZXv?2%xJ$c80rB*ca)Z2C@U^R|=NZXEKe6Ud`!
zn~>%OeWYz1Cw82fvB&W|Jf0bI`2QOxlcFrbNJsb1_4)2SbMNmN-|h`x1%lO;2)<c^
zXq_M7nzE`7wbkA|d)P}1vp(;7>3?eP;)(vb>HEqV`5aE95zehfxFjdyKe}a+7s0oh
zm=%+~eeU(?`->R)<L<G<US<S~_KF%OdJd&T7$sLP%MfxM{m|GUB|>0^S)L>|J%?mk
zf?FybOYCK4FF^PmzY}VNZOO1K6PB_J%XUz7NYq+~#ADprmISBY4`z9ip@~^IZV9Gk
zV@FY6V2%=dnJEXT_B(xkSmrjY^eo)SDU>4b!k+#T#dsJ6%Ys#OgbHO@W*W?JP4Fax
zu^BPxR$4*Vt(Z`3W&uw(QX*905X)jOGvxp^ekb6EsgqfgV6FZP`|h_Cq#mW-Q*eep
zML}MHVHL}=VHzp80WZM7*c5EXg{qlY_-hT5_m>cePM|Y9hRE0qwq;dt`(iIMUVtt?
z3@rs+*I~+!pqsQ%UO{pGN4OnzaC;kJq*uhaZd$_YbT%9Wh>T9sak<Fr7SeJ~_|&|C
zdk-GsX5SEcXh%{z*)m@gUS_-i?G4cKTQHI{aD#PldOt*A_6KOYSr|*La9e9(_nsB^
zdBcLHCBe*ofY9*o;%wtd3GJa#diogd{JDxOg;@OiDSizOA{ZSP_sp}G8LtLzG$2m_
zcGWb@2Nz&Rzkqv<7VY?i#v~L*zk_?V7RKTg<n#i0H^B_EJW2o1gg9GS)iAgGn6`HY
zEj<GW4BQrDx2fX!eqnV@@a$#A+kut_<kSQuG@+_lWOKXFR{G#JpM){|J=F9DoGb66
z*#DXE<Z=|C#oK}4;J7F@{!Py5P)N&<p5sb;h>CF@DXM|izySK`soBF`X1oB`8lYwq
zP^CB(7rkgYKSnmApb-8BPIEo7yBf^M*Kn`bl4pZLCcw=84)Bv21sh2zht9|tx=1@2
z4Zn@w!S(J41u_t&s&DOyQkb0ZGUElfT#rm<0~u)(rSA9Ow0!_YP9s0x0r$d5WH%o|
zoB9cE3k7&SDZKWj`hx(xpw0nk^0xkAQFtk37xOD?xZKu<^`wlcxfQeoqIeQd2`@9=
zi|ArK<V+kpbYAjK0<x5(z79#+M&{W)NQy$^Nhs^or=5|NIGEXg5p{+}piy-*vni?A
zqMhLW76p1t3#ODjjj4FDkwz+$7hYz(SMk-eP?x%Cp><OHKU(+3<#n+*dzsmP6$b}n
zSc@l-r@!cN#9n6h0tDZvMDwdn_Qf-BeyJy&7OmZUT4=w&_glGt=?u{PS`)Kkk`o_Q
z@tL;K)*naW{D~3l-siZYlAngR^u^EdQJ-Y;u$P#F&++;5)Sh_RS5@`OvBX}%_<a8Y
X?5nX&f{nAe00000NkvXXu0mjfkCJEf
--- a/browser/themes/winstripe/places/places.css
+++ b/browser/themes/winstripe/places/places.css
@@ -25,17 +25,22 @@ treechildren::-moz-tree-image(title) {
   list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
   padding-right: 2px;
   margin: 0px 2px;
   width: 16px;
   height: 16px;
 }
 
 treechildren::-moz-tree-image(title, livemarkItem) {
-  list-style-image: url("chrome://browser/skin/livemark-item.png");
+  list-style-image: url("chrome://browser/skin/places/livemark-item.png");
+  -moz-image-region: rect(0px, 16px, 16px, 0px);
+}
+
+treechildren::-moz-tree-image(title, livemarkItem, visited) {
+  -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 treechildren::-moz-tree-image(title, separator) {
   list-style-image: none;
   width: 0;
   height: 0;
 }
 
--- a/build/unix/build-toolchain/build-gcc.py
+++ b/build/unix/build-toolchain/build-gcc.py
@@ -1,15 +1,15 @@
 #!/usr/bin/python
 
 # The directories end up in the debug info, so the easy way of getting
 # a reproducible build is to run it in a know absolute directory.
 # We use a directory in /builds/slave because the mozilla infrastructure
 # cleans it up automatically.
-base_dir = "/builds/slave/moz-toolschain"
+base_dir = "/builds/slave/moz-toolchain"
 
 source_dir = base_dir + "/src"
 build_dir  = base_dir + "/build"
 aux_inst_dir = build_dir + '/aux_inst'
 old_make = aux_inst_dir + '/bin/make'
 
 ##############################################
 
@@ -53,16 +53,20 @@ def build_package(package_source_dir, pa
            ["%s/configure" % package_source_dir] + configure_args)
     run_in(package_build_dir, [make, "-j8"])
     run_in(package_build_dir, [make, "install"])
 
 def build_aux_tools(base_dir):
     make_build_dir = base_dir + '/make_build'
     build_package(make_source_dir, make_build_dir,
                   ["--prefix=%s" % aux_inst_dir], "make")
+
+    run_in(unifdef_source_dir, ["make"])
+    run_in(unifdef_source_dir, ["make", "prefix=%s" % aux_inst_dir, "install"])
+
     tar_build_dir = base_dir + '/tar_build'
     build_package(tar_source_dir, tar_build_dir,
                   ["--prefix=%s" % aux_inst_dir])
 
 def with_env(env, f):
     old_env = os.environ.copy()
     os.environ.update(env)
     f()
@@ -79,22 +83,27 @@ def build_glibc_aux(stage_dir, inst_dir)
     build_package(glibc_source_dir, glibc_build_dir,
                   ["--disable-profile",
                    "--enable-add-ons=nptl",
                    "--without-selinux",
                    "--enable-kernel=%s" % linux_version,
                    "--libdir=%s/lib64" % inst_dir,
                    "--prefix=%s" % inst_dir])
 
-def build_linux_headers(inst_dir):
+def build_linux_headers_aux(inst_dir):
     run_in(linux_source_dir, [old_make, "headers_check"])
     run_in(linux_source_dir, [old_make, "INSTALL_HDR_PATH=dest",
                                "headers_install"])
     shutil.move(linux_source_dir + "/dest", inst_dir)
 
+def build_linux_headers(inst_dir):
+    def f():
+        build_linux_headers_aux(inst_dir)
+    with_env({"PATH" : aux_inst_dir + "/bin:%s" % os.environ["PATH"]}, f)
+
 def build_one_stage(env, stage_dir, is_stage_one):
     def f():
         build_one_stage_aux(stage_dir, is_stage_one)
     with_env(env, f)
 
 def build_one_stage_aux(stage_dir, is_stage_one):
     os.mkdir(stage_dir)
 
@@ -162,65 +171,71 @@ binutils_version = "2.21.1"
 glibc_version = "2.5.1"
 linux_version = "2.6.18"
 tar_version = "1.26"
 make_version = "3.81"
 gcc_version = "4.5.2"
 mpfr_version = "2.4.2"
 gmp_version = "5.0.1"
 mpc_version = "0.8.1"
+unifdef_version = "2.6"
 
 binutils_source_uri = "http://ftp.gnu.org/gnu/binutils/binutils-%sa.tar.bz2" % \
     binutils_version
 glibc_source_uri = "http://ftp.gnu.org/gnu/glibc/glibc-%s.tar.bz2" % \
     glibc_version
 linux_source_uri = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-%s.tar.bz2" % \
     linux_version
 tar_source_uri = "http://ftp.gnu.org/gnu/tar/tar-%s.tar.bz2" % \
     tar_version
 make_source_uri = "http://ftp.gnu.org/gnu/make/make-%s.tar.bz2" % \
     make_version
+unifdef_source_uri = "http://dotat.at/prog/unifdef/unifdef-%s.tar.gz" % \
+    unifdef_version
 gcc_source_uri = "http://ftp.gnu.org/gnu/gcc/gcc-%s/gcc-%s.tar.bz2" % \
     (gcc_version, gcc_version)
 mpfr_source_uri = "http://www.mpfr.org/mpfr-%s/mpfr-%s.tar.bz2" % \
     (mpfr_version, mpfr_version)
 gmp_source_uri = "http://ftp.gnu.org/gnu/gmp/gmp-%s.tar.bz2" % gmp_version
 mpc_source_uri = "http://www.multiprecision.org/mpc/download/mpc-%s.tar.gz" % \
     mpc_version
 
 binutils_source_tar = download_uri(binutils_source_uri)
 glibc_source_tar = download_uri(glibc_source_uri)
 linux_source_tar = download_uri(linux_source_uri)
 tar_source_tar = download_uri(tar_source_uri)
 make_source_tar = download_uri(make_source_uri)
+unifdef_source_tar = download_uri(unifdef_source_uri)
 mpc_source_tar = download_uri(mpc_source_uri)
 mpfr_source_tar = download_uri(mpfr_source_uri)
 gmp_source_tar = download_uri(gmp_source_uri)
 gcc_source_tar = download_uri(gcc_source_uri)
 
 binutils_source_dir  = build_source_dir('binutils-', binutils_version)
 glibc_source_dir  = build_source_dir('glibc-', glibc_version)
 linux_source_dir  = build_source_dir('linux-', linux_version)
 tar_source_dir  = build_source_dir('tar-', tar_version)
 make_source_dir  = build_source_dir('make-', make_version)
+unifdef_source_dir  = build_source_dir('unifdef-', unifdef_version)
 mpc_source_dir  = build_source_dir('mpc-', mpc_version)
 mpfr_source_dir = build_source_dir('mpfr-', mpfr_version)
 gmp_source_dir  = build_source_dir('gmp-', gmp_version)
 gcc_source_dir  = build_source_dir('gcc-', gcc_version)
 
 if not os.path.exists(source_dir):
     os.makedirs(source_dir)
     extract(binutils_source_tar, source_dir)
     patch('binutils-deterministic.patch', 1, binutils_source_dir)
     extract(glibc_source_tar, source_dir)
     extract(linux_source_tar, source_dir)
     patch('glibc-deterministic.patch', 1, glibc_source_dir)
     run_in(glibc_source_dir, ["autoconf"])
     extract(tar_source_tar, source_dir)
     extract(make_source_tar, source_dir)
+    extract(unifdef_source_tar, source_dir)
     extract(mpc_source_tar, source_dir)
     extract(mpfr_source_tar, source_dir)
     extract(gmp_source_tar, source_dir)
     extract(gcc_source_tar, source_dir)
     patch('plugin_finish_decl.diff', 0, gcc_source_dir)
     patch('pr49911.diff', 1, gcc_source_dir)
     patch('r159628-r163231-r171807.patch', 1, gcc_source_dir)
 
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -898,23 +898,16 @@ nsEventSource::SetupHttpChannel()
 
   nsCOMPtr<nsIURI> codebase;
   nsresult rv = GetBaseURI(getter_AddRefs(codebase));
   if (NS_SUCCEEDED(rv)) {
     rv = mHttpChannel->SetReferrer(codebase);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  nsCOMPtr<nsIInterfaceRequestor> notificationCallbacks;
-  mHttpChannel->GetNotificationCallbacks(getter_AddRefs(notificationCallbacks));
-  if (notificationCallbacks != this) {
-    mNotificationCallbacks = notificationCallbacks;
-    mHttpChannel->SetNotificationCallbacks(this);
-  }
-
   return NS_OK;
 }
 
 nsresult
 nsEventSource::InitChannelAndRequestEventSource()
 {
   if (mReadyState == nsIEventSource::CLOSED) {
     return NS_ERROR_ABORT;
@@ -947,16 +940,23 @@ nsEventSource::InitChannelAndRequestEven
   NS_ENSURE_SUCCESS(rv, rv);
 
   mHttpChannel = do_QueryInterface(channel);
   NS_ENSURE_TRUE(mHttpChannel, NS_ERROR_NO_INTERFACE);
 
   rv = SetupHttpChannel();
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsCOMPtr<nsIInterfaceRequestor> notificationCallbacks;
+  mHttpChannel->GetNotificationCallbacks(getter_AddRefs(notificationCallbacks));
+  if (notificationCallbacks != this) {
+    mNotificationCallbacks = notificationCallbacks;
+    mHttpChannel->SetNotificationCallbacks(this);
+  }
+
   nsCOMPtr<nsIStreamListener> listener =
     new nsCORSListenerProxy(this, mPrincipal, mHttpChannel,
                             mWithCredentials, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Start reading from the channel
   rv = mHttpChannel->AsyncOpen(listener, nsnull);
   if (NS_SUCCEEDED(rv)) {
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -481,18 +481,23 @@ include $(topsrcdir)/config/rules.mk
 		test_plugin_freezing.html \
 		test_bug638112.html \
 		bug638112-response.txt \
 		bug638112.sjs \
 		test_bug656283.html \
 		test_blobbuilder.html \
 		fileutils.js \
 		test_bug338583.html \
+		test_EventSource_redirects.html \
 		eventsource.resource \
 		eventsource.resource^headers^ \
+		eventsource_redirect.resource \
+		eventsource_redirect.resource^headers^ \
+		eventsource_redirect_to.resource \
+		eventsource_redirect_to.resource^headers^ \
 		badContentType.eventsource \
 		badContentType.eventsource^headers^ \
 		badEventFieldName.eventsource \
 		badEventFieldName.eventsource^headers^ \
 		badHTTPResponseCode.eventsource \
 		badHTTPResponseCode.eventsource^headers^ \
 		badMessageEvent.eventsource \
 		badMessageEvent.eventsource^headers^ \
new file mode 100644
--- /dev/null
+++ b/content/base/test/eventsource_redirect.resource
@@ -0,0 +1,2 @@
+redirected
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/eventsource_redirect.resource^headers^
@@ -0,0 +1,3 @@
+HTTP 301 Moved Permanently
+Location: eventsource_redirect_to.resource
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/eventsource_redirect_to.resource
@@ -0,0 +1,3 @@
+retry:500
+data: 1
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/eventsource_redirect_to.resource^headers^
@@ -0,0 +1,3 @@
+Content-Type: text/event-stream
+Cache-Control: no-cache, must-revalidate
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_EventSource_redirects.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=716841
+-->
+<head>
+  <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
+  <title>Test for Bug 338583</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+</head>
+<body bgColor=white>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=716841">Mozilla Bug 716841</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+  function doTest(test_id) {
+    oldPrefVal = SpecialPowers.getBoolPref("dom.server-events.enabled");
+    SpecialPowers.setBoolPref("dom.server-events.enabled", true);
+
+    ok(true, "here we go");
+
+    source = new EventSource("eventsource_redirect.resource");
+    ok(source.url == "http://mochi.test:8888/tests/content/base/test/eventsource_redirect.resource", "Test failed.");
+    ok(source.readyState == 0 || source.readyState == 1, "Test failed.");
+
+    source.onopen = function (event) {
+      ok(true, "opened");
+    };
+
+    source.onmessage = function (event) {
+      ok(true, "event received");
+      source.close();
+      SimpleTest.finish();
+    };
+
+    source.onerror = function (event) {
+      ok(false, "received onError: " + event);
+      source.close();
+      SimpleTest.finish();
+    };
+
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  addLoadEvent(doTest);
+
+</script>
+</pre>
+
+</body>
+</html>
+
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -267,17 +267,17 @@ nsIDOMCanvasRenderingContext2D_CreateIma
 
         uint32_t data_width, data_height;
         if (!GetImageDataDimensions(cx, dataObject, &data_width, &data_height))
             return false;
 
         return CreateImageData(cx, data_width, data_height, NULL, 0, 0, vp);
     }
 
-    jsdouble width, height;
+    double width, height;
     if (!JS_ValueToNumber(cx, argv[0], &width) ||
         !JS_ValueToNumber(cx, argv[1], &height))
         return false;
 
     if (!NS_finite(width) || !NS_finite(height))
         return xpc_qsThrow(cx, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 
     if (!width || !height)
@@ -306,17 +306,17 @@ nsIDOMCanvasRenderingContext2D_GetImageD
     if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, tvr.jsval_addr(), nsnull))
         return JS_FALSE;
 
     if (argc < 4)
         return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
 
     jsval *argv = JS_ARGV(cx, vp);
 
-    jsdouble xd, yd, width, height;
+    double xd, yd, width, height;
     if (!JS_ValueToNumber(cx, argv[0], &xd) ||
         !JS_ValueToNumber(cx, argv[1], &yd) ||
         !JS_ValueToNumber(cx, argv[2], &width) ||
         !JS_ValueToNumber(cx, argv[3], &height))
         return false;
 
     if (!NS_finite(xd) || !NS_finite(yd) ||
         !NS_finite(width) || !NS_finite(height))
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -484,25 +484,19 @@ WebGLContext::SetDimensions(PRInt32 widt
         }
         LogMessage("Using software rendering via OSMesa (THIS WILL BE SLOW)");
     }
 
 #ifdef XP_WIN
     // if we want EGL, try it now
     if (!gl && (preferEGL || useANGLE) && !preferOpenGL) {
         gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
-        if (gl) {
-            if (InitAndValidateGL()) {
-                if (useANGLE) {
-                    gl->SetFlushGuaranteesResolve(true);
-                }
-            } else {
-                LogMessage("Error during ANGLE OpenGL ES initialization");
-                return NS_ERROR_FAILURE;
-            }
+        if (gl && !InitAndValidateGL()) {
+            LogMessage("Error during ANGLE OpenGL ES initialization");
+            return NS_ERROR_FAILURE;
         }
     }
 #endif
 
     // try the default provider, whatever that is
     if (!gl && useOpenGL) {
         gl = gl::GLContextProvider::CreateOffscreen(gfxIntSize(width, height), format);
         if (gl && !InitAndValidateGL()) {
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -955,19 +955,16 @@ nsGenericHTMLElement::InsertAdjacentHTML
       static_cast<nsINode*>(this)->InsertBefore(fragment, GetFirstChild(), &rv);
       break;
     case eBeforeEnd:
       static_cast<nsINode*>(this)->AppendChild(fragment, &rv);
       break;
     case eAfterEnd:
       destination->InsertBefore(fragment, GetNextSibling(), &rv);
       break;
-    default:
-      NS_NOTREACHED("Bad position.");
-      break;
   }
   return rv;
 }
 
 nsresult
 nsGenericHTMLElement::ScrollIntoView(bool aTop, PRUint8 optional_argc)
 {
   nsIDocument *document = GetCurrentDoc();
--- a/content/html/content/src/nsHTMLOptionElement.cpp
+++ b/content/html/content/src/nsHTMLOptionElement.cpp
@@ -188,51 +188,35 @@ nsHTMLOptionElement::SetSelected(bool aV
 }
 
 NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, DefaultSelected, selected)
 // GetText returns a whitespace compressed .textContent value.
 NS_IMPL_STRING_ATTR_WITH_FALLBACK(nsHTMLOptionElement, Label, label, GetText)
 NS_IMPL_STRING_ATTR_WITH_FALLBACK(nsHTMLOptionElement, Value, value, GetText)
 NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, Disabled, disabled)
 
-NS_IMETHODIMP 
+NS_IMETHODIMP
 nsHTMLOptionElement::GetIndex(PRInt32* aIndex)
 {
-  NS_ENSURE_ARG_POINTER(aIndex);
-
-  *aIndex = -1; // -1 indicates the index was not found
-
-  // Get our containing select content object.
-  nsHTMLSelectElement* selectElement = GetSelect();
-
-  if (selectElement) {
-    // Get the options from the select object.
-    nsCOMPtr<nsIDOMHTMLOptionsCollection> options;
-    selectElement->GetOptions(getter_AddRefs(options));
+  // When the element is not in a list of options, the index is 0.
+  *aIndex = 0;
 
-    if (options) {
-      // Walk the options to find out where we are in the list (ick, O(n))
-      PRUint32 length = 0;
-      options->GetLength(&length);
-
-      nsCOMPtr<nsIDOMNode> thisOption;
-
-      for (PRUint32 i = 0; i < length; i++) {
-        options->Item(i, getter_AddRefs(thisOption));
-
-        if (thisOption.get() == static_cast<nsIDOMNode *>(this)) {
-          *aIndex = i;
-
-          break;
-        }
-      }
-    }
+  // Only select elements can contain a list of options.
+  nsHTMLSelectElement* selectElement = GetSelect();
+  if (!selectElement) {
+    return NS_OK;
   }
 
-  return NS_OK;
+  nsHTMLOptionCollection* options = selectElement->GetOptions();
+  if (!options) {
+    return NS_OK;
+  }
+
+  // aIndex will not be set if GetOptionsIndex fails.
+  return options->GetOptionIndex(this, 0, true, aIndex);
 }
 
 bool
 nsHTMLOptionElement::Selected() const
 {
   // If we haven't been explictly selected or deselected, use our default value
   if (!mSelectedChanged) {
     return DefaultSelected();
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -1987,16 +1987,18 @@ nsHTMLOptionCollection::DropReference()
 }
 
 nsresult
 nsHTMLOptionCollection::GetOptionIndex(mozilla::dom::Element* aOption,
                                        PRInt32 aStartIndex,
                                        bool aForward,
                                        PRInt32* aIndex)
 {
+  // NOTE: aIndex shouldn't be set if the returned value isn't NS_OK.
+
   PRInt32 index;
 
   // Make the common case fast
   if (aStartIndex == 0 && aForward) {
     index = mElements.IndexOf(aOption);
     if (index == -1) {
       return NS_ERROR_FAILURE;
     }
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -138,17 +138,19 @@ public:
   }
 
   /**
    * Drop the reference to the select.  Called during select destruction.
    */
   void DropReference();
 
   /**
-   * Finds the index of a given option element
+   * Finds the index of a given option element.
+   * If the option isn't part of the collection, return NS_ERROR_FAILURE
+   * without setting aIndex.
    *
    * @param aOption the option to get the index of
    * @param aStartIndex the index to start looking at
    * @param aForward TRUE to look forward, FALSE to look backward
    * @return the option index
    */
   nsresult GetOptionIndex(mozilla::dom::Element* aOption,
                           PRInt32 aStartIndex, bool aForward,
--- a/content/html/content/test/forms/Makefile.in
+++ b/content/html/content/test/forms/Makefile.in
@@ -59,13 +59,14 @@ include $(topsrcdir)/config/rules.mk
 		test_label_control_attribute.html \
 		test_output_element.html \
 		test_button_attributes_reflection.html \
 		test_textarea_attributes_reflection.html \
 		test_validation.html \
 		test_maxlength_attribute.html \
 		test_datalist_element.html \
 		test_form_attributes_reflection.html \
+		test_option_index_attribute.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
new file mode 100644
--- /dev/null
+++ b/content/html/content/test/forms/test_option_index_attribute.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+See those bugs:
+https://bugzilla.mozilla.org/show_bug.cgi?id=720385
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for option.index</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720385">Mozilla Bug 720385</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <datalist>
+    <option></option>
+    <option></option>
+  </datalist>
+  <select>
+    <option></option>
+    <foo>
+      <option></option>
+      <optgroup>
+        <option></option>
+      </optgroup>
+      <option></option>
+    </foo>
+    <option></option>
+  </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 720385 **/
+
+var initialIndexes = [ 0, 0, 0, 1, 2, 3, 4 ];
+var options = document.getElementsByTagName('option');
+
+is(options.length, initialIndexes.length,
+   "Must have " + initialIndexes.length +" options");
+
+for (var i=0; i<options.length; ++i) {
+  is(options[i].index, initialIndexes[i], "test");
+}
+
+var o = document.createElement('option');
+is(o.index, 0, "option outside of a document have index=0");
+
+document.body.appendChild(o);
+is(o.index, 0, "option outside of a select have index=0");
+
+var datalist = document.getElementsByTagName('datalist')[0];
+
+datalist.appendChild(o);
+is(o.index, 0, "option outside of a select have index=0");
+
+datalist.removeChild(o);
+is(o.index, 0, "option outside of a select have index=0");
+
+var select = document.getElementsByTagName('select')[0];
+
+select.appendChild(o);
+is(o.index, 5, "option inside a select have an index");
+
+select.removeChild(select.options[0]);
+is(o.index, 4, "option inside a select have an index");
+
+select.insertBefore(o, select.options[0]);
+is(o.index, 0, "option inside a select have an index");
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/html/content/test/test_bug353415-2.html
+++ b/content/html/content/test/test_bug353415-2.html
@@ -1,16 +1,16 @@
 <!DOCTYPE html>
 <html>
 <head>
   <title>Test</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
 </head>
 <body>
-<iframe name="submit_frame" onLoad="doCheck();"></iframe>
+<iframe name="submit_frame"></iframe>
 <form method="get" id="form1" target="submit_frame" action="../../../../../blah">
 <table>
 <tr><td>
 <input type="text" name="field1" value="teststring"><br>
 <input type="radio" name="field2" value="0" checked> 0
 <input type="radio" name="field3" value="1"> 1<br>
 <input type="checkbox" name="field4" value="1" checked> 1
 <input type="checkbox" name="field5" value="2"> 2
@@ -47,18 +47,19 @@
 <label name="field11-2"></label>
 <input name="field12-2">
 <input type="button" name="field13-2" value="button">
 <input type="hidden" name="field14-2" value="14">
 </tr>
 </table>
 </form>
 <script>
-	document.forms[0].submit();
+  SimpleTest.waitForExplicitFinish();
 
-	SimpleTest.waitForExplicitFinish();
-        function doCheck(){
-		is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1-2=teststring&field2-2=0&field4-2=1&field6-2=3&field7-2=2&field8-2=8&field9-2=9&field12-2=&field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=&field14=14&field14-2=14", "Submit string was correct.");
-                SimpleTest.finish();
-	}
+  frames['submit_frame'].onload = function() {
+    is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1-2=teststring&field2-2=0&field4-2=1&field6-2=3&field7-2=2&field8-2=8&field9-2=9&field12-2=&field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=&field14=14&field14-2=14", "Submit string was correct.");
+    SimpleTest.finish();
+  }
+
+  document.forms[0].submit();
 </script>
 </body>
 </html>
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -2195,21 +2195,18 @@ nsSMILTimedElement::GetNextMilestone(nsS
         return true;
       }
 
       return false;
     }
 
   case STATE_POSTACTIVE:
     return false;
-
-  default:
-    NS_ABORT_IF_FALSE(false, "Invalid element state");
-    return false;
   }
+  MOZ_NOT_REACHED("Invalid element state");
 }
 
 void
 nsSMILTimedElement::NotifyNewInterval()
 {
   NS_ABORT_IF_FALSE(mCurrentInterval,
       "Attempting to notify dependents of a new interval but the interval "
       "is not set");
@@ -2270,21 +2267,18 @@ nsSMILTimedElement::GetEffectiveBeginIns
     return mCurrentInterval->Begin();
 
   case STATE_WAITING:
   case STATE_POSTACTIVE:
     {
       const nsSMILInterval* prevInterval = GetPreviousInterval();
       return prevInterval ? prevInterval->Begin() : nsnull;
     }
-
-  default:
-    NS_NOTREACHED("Invalid element state");
-    return nsnull;
   }
+  MOZ_NOT_REACHED("Invalid element state");
 }
 
 const nsSMILInterval*
 nsSMILTimedElement::GetPreviousInterval() const
 {
   return mOldIntervals.IsEmpty()
     ? nsnull
     : mOldIntervals[mOldIntervals.Length()-1].get();
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -159,25 +159,25 @@ DestroyMatchList(nsISupports* aKey, nsTe
         aMatch = next;
     }
 
     return PL_DHASH_REMOVE;
 }
 
 nsXULTemplateBuilder::~nsXULTemplateBuilder(void)
 {
+    Uninit(true);
+
     if (--gRefCnt == 0) {
         NS_IF_RELEASE(gRDFService);
         NS_IF_RELEASE(gRDFContainerUtils);
         NS_IF_RELEASE(gSystemPrincipal);
         NS_IF_RELEASE(gScriptSecurityManager);
         NS_IF_RELEASE(gObserverService);
     }
-
-    Uninit(true);
 }
 
 
 nsresult
 nsXULTemplateBuilder::InitGlobals()
 {
     nsresult rv;
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -4467,17 +4467,17 @@ nsDOMClassInfo::GetArrayIndexFromId(JSCo
 
   jsint i;
   if (JSID_IS_INT(id)) {
       i = JSID_TO_INT(id);
   } else {
       JSAutoRequest ar(cx);
 
       jsval idval;
-      jsdouble array_index;
+      double array_index;
       if (!::JS_IdToValue(cx, id, &idval) ||
           !::JS_ValueToNumber(cx, idval, &array_index) ||
           !::JS_DoubleIsInt32(array_index, &i)) {
         return -1;
       }
   }
 
   if (aIsNumber) {
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -1445,10 +1445,10 @@ CountHelper::DoDatabaseWork(mozIStorageC
   mCount = stmt->AsInt64(0);
   return NS_OK;
 }
 
 nsresult
 CountHelper::GetSuccessResult(JSContext* aCx,
                               jsval* aVal)
 {
-  return JS_NewNumberValue(aCx, static_cast<jsdouble>(mCount), aVal);
+  return JS_NewNumberValue(aCx, static_cast<double>(mCount), aVal);
 }
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -895,30 +895,30 @@ SwapBytes(PRUint32 u)
          ((u & 0x0000ff00U) << 8) |                                           
          ((u & 0x00ff0000U) >> 8) |                                           
          ((u & 0xff000000U) >> 24);
 #else
   return u;
 #endif
 }
 
-static inline jsdouble
+static inline double
 SwapBytes(PRUint64 u)
 {
 #ifdef IS_BIG_ENDIAN
   return ((u & 0x00000000000000ffLLU) << 56) |
          ((u & 0x000000000000ff00LLU) << 40) |
          ((u & 0x0000000000ff0000LLU) << 24) |
          ((u & 0x00000000ff000000LLU) << 8) |
          ((u & 0x000000ff00000000LLU) >> 8) |
          ((u & 0x0000ff0000000000LLU) >> 24) |
          ((u & 0x00ff000000000000LLU) >> 40) |
          ((u & 0xff00000000000000LLU) >> 56);
 #else
-  return jsdouble(u);
+  return double(u);
 #endif
 }
 
 static inline bool
 StructuredCloneReadString(JSStructuredCloneReader* aReader,
                           nsCString& aString)
 {
   PRUint32 length;
@@ -2014,17 +2014,17 @@ AddHelper::DoDatabaseWork(mozIStorageCon
 
     if (keyUnset && !keyPath.IsEmpty()) {
       // Special case where someone put an object into an autoIncrement'ing
       // objectStore with no key in its keyPath set. We needed to figure out
       // which row id we would get above before we could set that properly.
 
       // This is a duplicate of the js engine's byte munging here
       union {
-        jsdouble d;
+        double d;
         PRUint64 u;
       } pun;
     
       pun.d = SwapBytes(static_cast<PRUint64>(autoIncrementNum));
 
       JSAutoStructuredCloneBuffer& buffer = mCloneWriteInfo.mCloneBuffer;
       PRUint64 offsetToKeyProp = mCloneWriteInfo.mOffsetToKeyProp;
 
@@ -2846,10 +2846,10 @@ CountHelper::DoDatabaseWork(mozIStorageC
   mCount = stmt->AsInt64(0);
   return NS_OK;
 }
 
 nsresult
 CountHelper::GetSuccessResult(JSContext* aCx,
                               jsval* aVal)
 {
-  return JS_NewNumberValue(aCx, static_cast<jsdouble>(mCount), aVal);
+  return JS_NewNumberValue(aCx, static_cast<double>(mCount), aVal);
 }
--- a/dom/indexedDB/Key.cpp
+++ b/dom/indexedDB/Key.cpp
@@ -243,17 +243,17 @@ Key::DecodeJSVal(const unsigned char*& a
   else if (*aPos - aTypeOffset == eString) {
     nsString key;
     DecodeString(aPos, aEnd, key);
     if (!xpc::StringToJsval(aCx, key, aVal)) {
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
   }
   else if (*aPos - aTypeOffset == eDate) {
-    jsdouble msec = static_cast<jsdouble>(DecodeNumber(aPos, aEnd));
+    double msec = static_cast<double>(DecodeNumber(aPos, aEnd));
     JSObject* date = JS_NewDateObjectMsec(aCx, msec);
     if (!date) {
       NS_WARNING("Failed to make date!");
       return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
     *aVal = OBJECT_TO_JSVAL(date);
   }
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -452,17 +452,17 @@ JSValToNPVariant(NPP npp, JSContext *cx,
       VOID_TO_NPVARIANT(*variant);
     } else if (JSVAL_IS_NULL(val)) {
       NULL_TO_NPVARIANT(*variant);
     } else if (JSVAL_IS_BOOLEAN(val)) {
       BOOLEAN_TO_NPVARIANT(JSVAL_TO_BOOLEAN(val), *variant);
     } else if (JSVAL_IS_INT(val)) {
       INT32_TO_NPVARIANT(JSVAL_TO_INT(val), *variant);
     } else if (JSVAL_IS_DOUBLE(val)) {
-      jsdouble d = JSVAL_TO_DOUBLE(val);
+      double d = JSVAL_TO_DOUBLE(val);
       jsint i;
       if (JS_DoubleIsInt32(d, &i)) {
         INT32_TO_NPVARIANT(i, *variant);
       } else {
         DOUBLE_TO_NPVARIANT(d, *variant);
       }
     } else if (JSVAL_IS_STRING(val)) {
       JSString *jsstr = JSVAL_TO_STRING(val);
--- a/dom/sms/src/SmsMessage.cpp
+++ b/dom/sms/src/SmsMessage.cpp
@@ -103,17 +103,17 @@ SmsMessage::Create(PRInt32 aId,
     if (!JS_ObjectIsDate(aCx, &obj)) {
       return NS_ERROR_INVALID_ARG;
     }
     data.timestamp() = js_DateGetMsecSinceEpoch(aCx, &obj);
   } else {
     if (!aTimestamp.isNumber()) {
       return NS_ERROR_INVALID_ARG;
     }
-    jsdouble number = aTimestamp.toNumber();
+    double number = aTimestamp.toNumber();
     if (static_cast<PRUint64>(number) != number) {
       return NS_ERROR_INVALID_ARG;
     }
     data.timestamp() = static_cast<PRUint64>(number);
   }
 
   nsCOMPtr<nsIDOMMozSmsMessage> message = new SmsMessage(data);
   message.swap(*aMessage);
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -36,36 +36,43 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "Telephony.h"
 
 #include "nsIDocument.h"
 #include "nsIURI.h"
+#include "nsIURL.h"
 #include "nsPIDOMWindow.h"
 
 #include "jsapi.h"
 #include "mozilla/Preferences.h"
+#include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfo.h"
 #include "nsIInterfaceRequestorUtils.h"
+#include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "SystemWorkerManager.h"
 
 #include "CallEvent.h"
 #include "TelephonyCall.h"
 
 USING_TELEPHONY_NAMESPACE
 using mozilla::Preferences;
 
 #define DOM_TELEPHONY_APP_PHONE_URL_PREF "dom.telephony.app.phone.url"
 
 namespace {
 
+typedef nsAutoTArray<Telephony*, 2> TelephonyList;
+
+TelephonyList* gTelephonyList;
+
 template <class T>
 inline nsresult
 nsTArrayToJSArray(JSContext* aCx, JSObject* aGlobal,
                   const nsTArray<nsRefPtr<T> >& aSourceArray,
                   JSObject** aResultArray)
 {
   NS_ASSERTION(aCx, "Null context!");
   NS_ASSERTION(aGlobal, "Null global!");
@@ -105,25 +112,46 @@ nsTArrayToJSArray(JSContext* aCx, JSObje
   }
 
   *aResultArray = arrayObj;
   return NS_OK;
 }
 
 } // anonymous namespace
 
+Telephony::Telephony()
+: mActiveCall(nsnull), mCallsArray(nsnull), mRooted(false)
+{
+  if (!gTelephonyList) {
+    gTelephonyList = new TelephonyList();
+  }
+
+  gTelephonyList->AppendElement(this);
+}
+
 Telephony::~Telephony()
 {
   if (mRIL && mRILTelephonyCallback) {
     mRIL->UnregisterCallback(mRILTelephonyCallback);
   }
 
   if (mRooted) {
     NS_DROP_JS_OBJECTS(this, Telephony);
   }
+
+  NS_ASSERTION(gTelephonyList, "This should never be null!");
+  NS_ASSERTION(gTelephonyList->Contains(this), "Should be in the list!");
+
+  if (gTelephonyList->Length() == 1) {
+    delete gTelephonyList;
+    gTelephonyList = nsnull;
+  }
+  else {
+    gTelephonyList->RemoveElement(this);
+  }
 }
 
 // static
 already_AddRefed<Telephony>
 Telephony::Create(nsPIDOMWindow* aOwner, nsIRadioInterfaceLayer* aRIL)
 {
   NS_ASSERTION(aOwner, "Null owner!");
   NS_ASSERTION(aRIL, "Null RIL!");
@@ -145,46 +173,71 @@ Telephony::Create(nsPIDOMWindow* aOwner,
   NS_ENSURE_SUCCESS(rv, nsnull);
 
   rv = aRIL->RegisterCallback(telephony->mRILTelephonyCallback);
   NS_ENSURE_SUCCESS(rv, nsnull);
 
   return telephony.forget();
 }
 
+already_AddRefed<TelephonyCall>
+Telephony::CreateNewDialingCall(const nsAString& aNumber)
+{
+  nsRefPtr<TelephonyCall> call =
+    TelephonyCall::Create(this, aNumber,
+                          nsIRadioInterfaceLayer::CALL_STATE_DIALING);
+  NS_ASSERTION(call, "This should never fail!");
+
+  NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
+
+  return call.forget();
+}
+
 void
-Telephony::SwitchActiveCall(TelephonyCall* aCall)
+Telephony::NoteDialedCallFromOtherInstance(const nsAString& aNumber)
 {
-  if (mActiveCall) {
-    // Put the call on hold?
-    NS_NOTYETIMPLEMENTED("Implement me!");
-  }
-  mActiveCall = aCall;
+  // We don't need to hang on to this call object, it is held alive by mCalls.
+  nsRefPtr<TelephonyCall> call = CreateNewDialingCall(aNumber);
+}
+
+nsresult
+Telephony::NotifyCallsChanged(TelephonyCall* aCall)
+{
+  nsRefPtr<CallEvent> event = CallEvent::Create(aCall);
+  NS_ASSERTION(event, "This should never fail!");
+
+  nsresult rv =
+    event->Dispatch(ToIDOMEventTarget(), NS_LITERAL_STRING("callschanged"));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(Telephony)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Telephony,
                                                   nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(incoming)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(callschanged)
   for (PRUint32 index = 0; index < tmp->mCalls.Length(); index++) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCalls[i]");
     cb.NoteXPCOMChild(tmp->mCalls[index]->ToISupports());
   }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(Telephony,
                                                nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->mCallsArray, "mCallsArray")
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Telephony,
                                                 nsDOMEventTargetHelper)
   NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(incoming)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(callschanged)
   tmp->mCalls.Clear();
   tmp->mActiveCall = nsnull;
   tmp->mCallsArray = nsnull;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Telephony)
   NS_INTERFACE_MAP_ENTRY(nsIDOMTelephony)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Telephony)
@@ -211,21 +264,26 @@ Telephony::Dial(const nsAString& aNumber
       NS_WARNING("Only permitted to dial one call at a time!");
       return NS_ERROR_NOT_AVAILABLE;
     }
   }
 
   nsresult rv = mRIL->Dial(aNumber);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsRefPtr<TelephonyCall> call =
-    TelephonyCall::Create(this, aNumber, nsIRadioInterfaceLayer::CALL_STATE_DIALING);
-  NS_ASSERTION(call, "This should never fail!");
+  nsRefPtr<TelephonyCall> call = CreateNewDialingCall(aNumber);
 
-  NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
+  // Notify other telephony objects that we just dialed.
+  for (PRUint32 index = 0; index < gTelephonyList->Length(); index++) {
+    Telephony*& telephony = gTelephonyList->ElementAt(index);
+    if (telephony != this) {
+      nsRefPtr<Telephony> kungFuDeathGrip = telephony;
+      telephony->NoteDialedCallFromOtherInstance(aNumber);
+    }
+  }
 
   call.forget(aResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Telephony::GetMuted(bool* aMuted)
 {
@@ -275,42 +333,16 @@ Telephony::GetActive(jsval* aActive)
                                mScriptContext->GetNativeGlobal(),
                                mActiveCall->ToISupports(), aActive);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Telephony::SetActive(const jsval& aActive)
-{
-  if (aActive.isObject()) {
-    nsIXPConnect* xpc = nsContentUtils::XPConnect();
-    NS_ASSERTION(xpc, "This should never be null!");
-
-    nsISupports* native =
-      xpc->GetNativeOfWrapper(mScriptContext->GetNativeContext(),
-                              &aActive.toObject());
-
-    nsCOMPtr<nsIDOMTelephonyCall> call = do_QueryInterface(native);
-    if (call) {
-      // See if this call has the same telephony object. Otherwise we can't use
-      // it.
-      TelephonyCall* concreteCall = static_cast<TelephonyCall*>(call.get());
-      if (this == concreteCall->mTelephony) {
-        SwitchActiveCall(concreteCall);
-        return NS_OK;
-      }
-    }
-  }
-
-  return NS_ERROR_INVALID_ARG;
-}
-
-NS_IMETHODIMP
 Telephony::GetCalls(jsval* aCalls)
 {
   JSObject* calls = mCallsArray;
   if (!calls) {
     nsresult rv =
       nsTArrayToJSArray(mScriptContext->GetNativeContext(),
                         mScriptContext->GetNativeGlobal(), mCalls, &calls);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -349,41 +381,35 @@ NS_IMETHODIMP
 Telephony::StopTone()
 {
   nsresult rv = mRIL->StopTone();
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-Telephony::SendTones(const nsAString& aTones, PRUint32 aToneDuration,
-                     PRUint32 aIntervalDuration)
-{
-  NS_NOTYETIMPLEMENTED("Implement me!");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 NS_IMPL_EVENT_HANDLER(Telephony, incoming)
+NS_IMPL_EVENT_HANDLER(Telephony, callschanged)
 
 NS_IMETHODIMP
 Telephony::CallStateChanged(PRUint32 aCallIndex, PRUint16 aCallState,
                             const nsAString& aNumber)
 {
   NS_ASSERTION(aCallIndex != kOutgoingPlaceholderCallIndex,
                "This should never happen!");
 
   nsRefPtr<TelephonyCall> modifiedCall;
   nsRefPtr<TelephonyCall> outgoingCall;
 
   for (PRUint32 index = 0; index < mCalls.Length(); index++) {
     nsRefPtr<TelephonyCall>& tempCall = mCalls[index];
     if (tempCall->CallIndex() == kOutgoingPlaceholderCallIndex) {
       NS_ASSERTION(!outgoingCall, "More than one outgoing call not supported!");
-      NS_ASSERTION(tempCall->CallState() == nsIRadioInterfaceLayer::CALL_STATE_DIALING,
+      NS_ASSERTION(tempCall->CallState() ==
+                   nsIRadioInterfaceLayer::CALL_STATE_DIALING,
                    "Something really wrong here!");
       // Stash this for later, we may need it if aCallIndex doesn't match one of
       // our other calls.
       outgoingCall = tempCall;
     } else if (tempCall->CallIndex() == aCallIndex) {
       // We already know about this call so just update its state.
       modifiedCall = tempCall;
       outgoingCall = nsnull;
@@ -402,17 +428,17 @@ Telephony::CallStateChanged(PRUint32 aCa
   }
 
   if (modifiedCall) {
     // Change state.
     modifiedCall->ChangeState(aCallState);
 
     // See if this should replace our current active call.
     if (aCallState == nsIRadioInterfaceLayer::CALL_STATE_CONNECTED) {
-      SwitchActiveCall(modifiedCall);
+      mActiveCall = modifiedCall;
     }
 
     return NS_OK;
   }
 
   // Didn't know anything about this call before now, must be incoming.
   NS_ASSERTION(aCallState == nsIRadioInterfaceLayer::CALL_STATE_INCOMING,
                "Serious logic problem here!");
@@ -481,32 +507,58 @@ NS_NewTelephony(nsPIDOMWindow* aWindow, 
   // Need the document in order to make security decisions.
   nsCOMPtr<nsIDocument> document =
     do_QueryInterface(innerWindow->GetExtantDocument());
   NS_ENSURE_TRUE(document, NS_NOINTERFACE);
 
   // Do security checks. We assume that chrome is always allowed and we also
   // allow a single page specified by preferences.
   if (!nsContentUtils::IsSystemPrincipal(document->NodePrincipal())) {
-    nsCOMPtr<nsIURI> documentURI;
+    nsCOMPtr<nsIURI> originalURI;
     nsresult rv =
-      document->NodePrincipal()->GetURI(getter_AddRefs(documentURI));
+      document->NodePrincipal()->GetURI(getter_AddRefs(originalURI));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIURI> documentURI;
+    rv = originalURI->Clone(getter_AddRefs(documentURI));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    nsCString documentURL;
-    rv = documentURI->GetSpec(documentURL);
-    NS_ENSURE_SUCCESS(rv, rv);
+    // Strip the query string (if there is one) before comparing.
+    nsCOMPtr<nsIURL> documentURL = do_QueryInterface(documentURI);
+    if (documentURL) {
+      rv = documentURL->SetQuery(EmptyCString());
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+
+    bool allowed = false;
 
     // The pref may not exist but in that case we deny access just as we do if
     // the url doesn't match.
-    nsCString phoneAppURL;
-    if (NS_FAILED(Preferences::GetCString(DOM_TELEPHONY_APP_PHONE_URL_PREF,
-                                          &phoneAppURL)) ||
-        !phoneAppURL.Equals(documentURL,
-                            nsCaseInsensitiveCStringComparator())) {
+    nsCString whitelist;
+    if (NS_SUCCEEDED(Preferences::GetCString(DOM_TELEPHONY_APP_PHONE_URL_PREF,
+                                             &whitelist))) {
+      nsCOMPtr<nsIIOService> ios = do_GetIOService();
+      NS_ENSURE_TRUE(ios, NS_ERROR_FAILURE);
+
+      nsCCharSeparatedTokenizer tokenizer(whitelist, ',');
+      while (tokenizer.hasMoreTokens()) {
+        nsCOMPtr<nsIURI> uri;
+        if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), tokenizer.nextToken(),
+                                   nsnull, nsnull, ios))) {
+          rv = documentURI->EqualsExceptRef(uri, &allowed);
+          NS_ENSURE_SUCCESS(rv, rv);
+
+          if (allowed) {
+            break;
+          }
+        }
+      }
+    }
+
+    if (!allowed) {
       *aTelephony = nsnull;
       return NS_OK;
     }
   }
 
   // Security checks passed, make a telephony object.
   nsIInterfaceRequestor* ireq = SystemWorkerManager::GetInterfaceRequestor();
   NS_ENSURE_TRUE(ireq, NS_ERROR_UNEXPECTED);
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -53,16 +53,17 @@ BEGIN_TELEPHONY_NAMESPACE
 
 class Telephony : public nsDOMEventTargetHelper,
                   public nsIDOMTelephony
 {
   nsCOMPtr<nsIRadioInterfaceLayer> mRIL;
   nsCOMPtr<nsIRILTelephonyCallback> mRILTelephonyCallback;
 
   NS_DECL_EVENT_HANDLER(incoming)
+  NS_DECL_EVENT_HANDLER(callschanged)
 
   TelephonyCall* mActiveCall;
   nsTArray<nsRefPtr<TelephonyCall> > mCalls;
 
   // Cached calls array object. Cleared whenever mCalls changes and then rebuilt
   // once a page looks for the liveCalls attribute.
   JSObject* mCallsArray;
 
@@ -94,24 +95,26 @@ public:
   }
 
   void
   AddCall(TelephonyCall* aCall)
   {
     NS_ASSERTION(!mCalls.Contains(aCall), "Already know about this one!");
     mCalls.AppendElement(aCall);
     mCallsArray = nsnull;
+    NotifyCallsChanged(aCall);
   }
 
   void
   RemoveCall(TelephonyCall* aCall)
   {
     NS_ASSERTION(mCalls.Contains(aCall), "Didn't know about this one!");
     mCalls.RemoveElement(aCall);
     mCallsArray = nsnull;
+    NotifyCallsChanged(aCall);
   }
 
   nsIRadioInterfaceLayer*
   RIL() const
   {
     return mRIL;
   }
 
@@ -123,24 +126,27 @@ public:
 
   nsIScriptContext*
   ScriptContext() const
   {
     return mScriptContext;
   }
 
 private:
-  Telephony()
-  : mActiveCall(nsnull), mCallsArray(nsnull), mRooted(false)
-  { }
-
+  Telephony();
   ~Telephony();
 
+  already_AddRefed<TelephonyCall>
+  CreateNewDialingCall(const nsAString& aNumber);
+
   void
-  SwitchActiveCall(TelephonyCall* aCall);
+  NoteDialedCallFromOtherInstance(const nsAString& aNumber);
+
+  nsresult
+  NotifyCallsChanged(TelephonyCall* aCall);
 
   class RILTelephonyCallback : public nsIRILTelephonyCallback
   {
     Telephony* mTelephony;
 
   public:
     NS_DECL_ISUPPORTS
     NS_FORWARD_NSIRILTELEPHONYCALLBACK(mTelephony->)
--- a/dom/telephony/nsIDOMTelephony.idl
+++ b/dom/telephony/nsIDOMTelephony.idl
@@ -38,31 +38,29 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMEventTarget.idl"
 
 interface nsIDOMEventListener;
 interface nsIDOMTelephonyCall;
 
-[scriptable, builtinclass, uuid(047be0d8-a9cd-49aa-8948-2f60ff3a7a18)]
+[scriptable, builtinclass, uuid(0de46b73-be83-4970-ad15-45f92cb0902a)]
 interface nsIDOMTelephony : nsIDOMEventTarget
 {
   nsIDOMTelephonyCall dial(in DOMString number);
 
   attribute boolean muted;
   attribute boolean speakerEnabled;
 
   // The call that is "active", i.e. receives microphone input and tones
   // generated via startTone.
-  attribute jsval active;
+  readonly attribute jsval active;
 
   // Array of all calls that are currently connected.
   readonly attribute jsval calls;
 
   void startTone(in DOMString tone);
   void stopTone();
-  void sendTones(in DOMString tones,
-                 [optional] in unsigned long toneDuration,
-                 [optional] in unsigned long intervalDuration);
 
   attribute nsIDOMEventListener onincoming;
+  attribute nsIDOMEventListener oncallschanged;
 };
--- a/dom/workers/Events.cpp
+++ b/dom/workers/Events.cpp
@@ -845,17 +845,17 @@ public:
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto)
   {
     return JS_InitClass(aCx, aObj, aParentProto, &sClass, Construct, 0,
                         sProperties, sFunctions, NULL, NULL);
   }
 
   static JSObject*
   Create(JSContext* aCx, JSObject* aParent, JSString* aType,
-         bool aLengthComputable, jsdouble aLoaded, jsdouble aTotal)
+         bool aLengthComputable, double aLoaded, double aTotal)
   {
     JSString* type = JS_InternJSString(aCx, aType);
     if (!type) {
       return NULL;
     }
 
     JSObject* obj = JS_NewObject(aCx, &sClass, NULL, aParent);
     if (!obj) {
@@ -902,18 +902,18 @@ private:
                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
                          classPtr->name);
     return NULL;
   }
 
   static void
   InitProgressEventCommon(JSObject* aObj, Event* aEvent, JSString* aType,
                           JSBool aBubbles, JSBool aCancelable,
-                          JSBool aLengthComputable, jsdouble aLoaded,
-                          jsdouble aTotal, bool aIsTrusted)
+                          JSBool aLengthComputable, double aLoaded,
+                          double aTotal, bool aIsTrusted)
   {
     Event::InitEventCommon(aObj, aEvent, aType, aBubbles, aCancelable,
                            aIsTrusted);
     JS_SetReservedSlot(aObj, SLOT_lengthComputable,
                        aLengthComputable ? JSVAL_TRUE : JSVAL_FALSE);
     JS_SetReservedSlot(aObj, SLOT_loaded, DOUBLE_TO_JSVAL(aLoaded));
     JS_SetReservedSlot(aObj, SLOT_total, DOUBLE_TO_JSVAL(aTotal));
   }
@@ -962,17 +962,17 @@ private:
 
     ProgressEvent* event = GetInstancePrivate(aCx, obj, sFunctions[0].name);
     if (!event) {
       return false;
     }
 
     JSString* type;
     JSBool bubbles, cancelable, lengthComputable;
-    jsdouble loaded, total;
+    double loaded, total;
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "Sbbbdd", &type,
                              &bubbles, &cancelable, &lengthComputable, &loaded,
                              &total)) {
       return false;
     }
 
     InitProgressEventCommon(obj, event, type, bubbles, cancelable,
                             lengthComputable, loaded, total, false);
@@ -1060,17 +1060,17 @@ CreateErrorEvent(JSContext* aCx, JSStrin
 {
   JSObject* global = JS_GetGlobalForScopeChain(aCx);
   return ErrorEvent::Create(aCx, global, aMessage, aFilename, aLineNumber,
                             aMainRuntime);
 }
 
 JSObject*
 CreateProgressEvent(JSContext* aCx, JSString* aType, bool aLengthComputable,
-                    jsdouble aLoaded, jsdouble aTotal)
+                    double aLoaded, double aTotal)
 {
   JSObject* global = JS_GetGlobalForScopeChain(aCx);
   return ProgressEvent::Create(aCx, global, aType, aLengthComputable, aLoaded,
                                aTotal);
 }
 
 bool
 IsSupportedEventClass(JSObject* aEvent)
--- a/dom/workers/Events.h
+++ b/dom/workers/Events.h
@@ -64,17 +64,17 @@ CreateMessageEvent(JSContext* aCx, JSAut
                    bool aMainRuntime);
 
 JSObject*
 CreateErrorEvent(JSContext* aCx, JSString* aMessage, JSString* aFilename,
                  uint32 aLineNumber, bool aMainRuntime);
 
 JSObject*
 CreateProgressEvent(JSContext* aCx, JSString* aType, bool aLengthComputable,
-                    jsdouble aLoaded, jsdouble aTotal);
+                    double aLoaded, double aTotal);
 
 bool
 IsSupportedEventClass(JSObject* aEvent);
 
 void
 SetEventTarget(JSObject* aEvent, JSObject* aTarget);
 
 bool
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -135,17 +135,17 @@ private:
       return false;
     }
 
     PRUint64 size;
     if (NS_FAILED(blob->GetSize(&size))) {
       ThrowFileExceptionForCode(aCx, FILE_NOT_READABLE_ERR);
     }
 
-    if (!JS_NewNumberValue(aCx, jsdouble(size), aVp)) {
+    if (!JS_NewNumberValue(aCx, double(size), aVp)) {
       return false;
     }
 
     return true;
   }
 
   static JSBool
   GetType(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
@@ -178,17 +178,17 @@ private:
       return false;
     }
 
     nsIDOMBlob* blob = GetInstancePrivate(aCx, obj, "slice");
     if (!blob) {
       return false;
     }
 
-    jsdouble start = 0, end = 0;
+    double start = 0, end = 0;
     JSString* jsContentType = JS_GetEmptyString(JS_GetRuntime(aCx));
     if (!JS_ConvertArguments(aCx, aArgc, JS_ARGV(aCx, aVp), "/IIS", &start,
                              &end, &jsContentType)) {
       return false;
     }
 
     nsDependentJSString contentType;
     if (!contentType.init(aCx, jsContentType)) {
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3528,17 +3528,17 @@ WorkerPrivate::SetTimeout(JSContext* aCx
   else {
     JS_ReportError(aCx, "Useless %s call (missing quotes around argument?)",
                    aIsInterval ? "setInterval" : "setTimeout");
     return false;
   }
 
   // See if any of the optional arguments were passed.
   if (aArgc > 1) {
-    jsdouble intervalMS = 0;
+    double intervalMS = 0;
     if (!JS_ValueToNumber(aCx, argv[1], &intervalMS)) {
       return false;
     }
     newInfo->mInterval = TimeDuration::FromMilliseconds(intervalMS);
 
     if (aArgc > 2 && JSVAL_IS_OBJECT(newInfo->mTimeoutVal)) {
       nsTArray<jsval> extraArgVals(aArgc - 2);
       for (uintN index = 2; index < aArgc; index++) {
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -5,16 +5,18 @@ Current revision: r963
 == Applied local patches ==
 
 In this order:
   angle-renaming-debug.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
   angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
   angle-limit-identifiers-to-250-chars.patch - see bug 675625
   angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands.
   angle-castrate-bug-241.patch - see bug 699033 / angle bug 241
+  angle-enforce-readpixels-spec.patch - see bug 724476.
+  angle-impl-read-bgra.patch - see bug 724476.
 
 In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE.
 
 == How to update this ANGLE copy ==
 
 1. Unapply patches
 2. Apply diff with new ANGLE version
 3. Reapply patches.
new file mode 100644
--- /dev/null
+++ b/gfx/angle/angle-enforce-readpixels-spec.patch
@@ -0,0 +1,34 @@
+From: Jeff Gilbert <jgilbert@mozilla.com>
+Bug 724476 - ANGLE Bug 293 - Enforce readPixels format/type semantics
+
+diff --git a/gfx/angle/src/libGLESv2/libGLESv2.cpp b/gfx/angle/src/libGLESv2/libGLESv2.cpp
+--- a/gfx/angle/src/libGLESv2/libGLESv2.cpp
++++ b/gfx/angle/src/libGLESv2/libGLESv2.cpp
+@@ -98,27 +98,16 @@ bool validReadFormatType(GLenum format, 
+         switch (type)
+         {
+           case GL_UNSIGNED_BYTE:
+             break;
+           default:
+             return false;
+         }
+         break;
+-      case GL_BGRA_EXT:
+-        switch (type)
+-        {
+-          case GL_UNSIGNED_BYTE:
+-          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+-          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+-            break;
+-          default:
+-            return false;
+-        }
+-        break;
+       case gl::IMPLEMENTATION_COLOR_READ_FORMAT:
+         switch (type)
+         {
+           case gl::IMPLEMENTATION_COLOR_READ_TYPE:
+             break;
+           default:
+             return false;
+         }
new file mode 100644
--- /dev/null
+++ b/gfx/angle/angle-impl-read-bgra.patch
@@ -0,0 +1,71 @@
+From: Jeff Gilbert <jgilbert@mozilla.com>
+Bug 724476 - ANGLE Bug 294 - Use BGRA/UBYTE as exposed fast format/type for readPixels
+
+diff --git a/gfx/angle/src/libGLESv2/Context.cpp b/gfx/angle/src/libGLESv2/Context.cpp
+--- a/gfx/angle/src/libGLESv2/Context.cpp
++++ b/gfx/angle/src/libGLESv2/Context.cpp
+@@ -2520,16 +2520,17 @@ void Context::readPixels(GLint x, GLint 
+     {
+         if (desc.Format == D3DFMT_A8R8G8B8 &&
+             format == GL_BGRA_EXT &&
+             type == GL_UNSIGNED_BYTE)
+         {
+             // Fast path for EXT_read_format_bgra, given
+             // an RGBA source buffer.  Note that buffers with no
+             // alpha go through the slow path below.
++            // Note that this is also the combo exposed by IMPLEMENTATION_COLOR_READ_TYPE/FORMAT
+             memcpy(dest + j * outputPitch,
+                    source + j * inputPitch,
+                    (rect.right - rect.left) * 4);
+             continue;
+         }
+ 
+         for (int i = 0; i < rect.right - rect.left; i++)
+         {
+@@ -2666,20 +2667,20 @@ void Context::readPixels(GLint x, GLint 
+                         ((unsigned short)(     a + 0.5f) << 15) |
+                         ((unsigned short)(31 * r + 0.5f) << 10) |
+                         ((unsigned short)(31 * g + 0.5f) << 5) |
+                         ((unsigned short)(31 * b + 0.5f) << 0);
+                     break;
+                   default: UNREACHABLE();
+                 }
+                 break;
+-              case GL_RGB:   // IMPLEMENTATION_COLOR_READ_FORMAT
++              case GL_RGB:
+                 switch (type)
+                 {
+-                  case GL_UNSIGNED_SHORT_5_6_5:   // IMPLEMENTATION_COLOR_READ_TYPE
++                  case GL_UNSIGNED_SHORT_5_6_5:
+                     dest16[i + j * outputPitch / sizeof(unsigned short)] = 
+                         ((unsigned short)(31 * b + 0.5f) << 0) |
+                         ((unsigned short)(63 * g + 0.5f) << 5) |
+                         ((unsigned short)(31 * r + 0.5f) << 11);
+                     break;
+                   default: UNREACHABLE();
+                 }
+                 break;
+diff --git a/gfx/angle/src/libGLESv2/Context.h b/gfx/angle/src/libGLESv2/Context.h
+--- a/gfx/angle/src/libGLESv2/Context.h
++++ b/gfx/angle/src/libGLESv2/Context.h
+@@ -69,18 +69,18 @@ enum
+     MAX_VARYING_VECTORS_SM3 = 10,
+     MAX_TEXTURE_IMAGE_UNITS = 16,
+     MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF = 4,   // For devices supporting vertex texture fetch
+     MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF,    
+     MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3,    // Reserve space for dx_Coord, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers.
+     MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3,
+     MAX_DRAW_BUFFERS = 1,
+ 
+-    IMPLEMENTATION_COLOR_READ_FORMAT = GL_RGB,
+-    IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5
++    IMPLEMENTATION_COLOR_READ_FORMAT = GL_BGRA_EXT,
++    IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_BYTE
+ };
+ 
+ enum QueryType
+ {
+     QUERY_ANY_SAMPLES_PASSED,
+     QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE,
+ 
+     QUERY_TYPE_COUNT
--- a/gfx/angle/src/libGLESv2/Context.cpp
+++ b/gfx/angle/src/libGLESv2/Context.cpp
@@ -2520,16 +2520,17 @@ void Context::readPixels(GLint x, GLint 
     {
         if (desc.Format == D3DFMT_A8R8G8B8 &&
             format == GL_BGRA_EXT &&
             type == GL_UNSIGNED_BYTE)
         {
             // Fast path for EXT_read_format_bgra, given
             // an RGBA source buffer.  Note that buffers with no
             // alpha go through the slow path below.
+            // Note that this is also the combo exposed by IMPLEMENTATION_COLOR_READ_TYPE/FORMAT
             memcpy(dest + j * outputPitch,
                    source + j * inputPitch,
                    (rect.right - rect.left) * 4);
             continue;
         }
 
         for (int i = 0; i < rect.right - rect.left; i++)
         {
@@ -2666,20 +2667,20 @@ void Context::readPixels(GLint x, GLint 
                         ((unsigned short)(     a + 0.5f) << 15) |
                         ((unsigned short)(31 * r + 0.5f) << 10) |
                         ((unsigned short)(31 * g + 0.5f) << 5) |
                         ((unsigned short)(31 * b + 0.5f) << 0);
                     break;
                   default: UNREACHABLE();
                 }
                 break;
-              case GL_RGB:   // IMPLEMENTATION_COLOR_READ_FORMAT
+              case GL_RGB:
                 switch (type)
                 {
-                  case GL_UNSIGNED_SHORT_5_6_5:   // IMPLEMENTATION_COLOR_READ_TYPE
+                  case GL_UNSIGNED_SHORT_5_6_5:
                     dest16[i + j * outputPitch / sizeof(unsigned short)] = 
                         ((unsigned short)(31 * b + 0.5f) << 0) |
                         ((unsigned short)(63 * g + 0.5f) << 5) |
                         ((unsigned short)(31 * r + 0.5f) << 11);
                     break;
                   default: UNREACHABLE();
                 }
                 break;
--- a/gfx/angle/src/libGLESv2/Context.h
+++ b/gfx/angle/src/libGLESv2/Context.h
@@ -69,18 +69,18 @@ enum
     MAX_VARYING_VECTORS_SM3 = 10,
     MAX_TEXTURE_IMAGE_UNITS = 16,
     MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF = 4,   // For devices supporting vertex texture fetch
     MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF = MAX_TEXTURE_IMAGE_UNITS + MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF,    
     MAX_FRAGMENT_UNIFORM_VECTORS_SM2 = 32 - 3,    // Reserve space for dx_Coord, dx_Depth, and dx_DepthRange. dx_PointOrLines and dx_FrontCCW use separate bool registers.
     MAX_FRAGMENT_UNIFORM_VECTORS_SM3 = 224 - 3,
     MAX_DRAW_BUFFERS = 1,
 
-    IMPLEMENTATION_COLOR_READ_FORMAT = GL_RGB,
-    IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5
+    IMPLEMENTATION_COLOR_READ_FORMAT = GL_BGRA_EXT,
+    IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_BYTE
 };
 
 enum QueryType
 {
     QUERY_ANY_SAMPLES_PASSED,
     QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE,
 
     QUERY_TYPE_COUNT
--- a/gfx/angle/src/libGLESv2/libGLESv2.cpp
+++ b/gfx/angle/src/libGLESv2/libGLESv2.cpp
@@ -98,27 +98,16 @@ bool validReadFormatType(GLenum format, 
         switch (type)
         {
           case GL_UNSIGNED_BYTE:
             break;
           default:
             return false;
         }
         break;
-      case GL_BGRA_EXT:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
-          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
-            break;
-          default:
-            return false;
-        }
-        break;
       case gl::IMPLEMENTATION_COLOR_READ_FORMAT:
         switch (type)
         {
           case gl::IMPLEMENTATION_COLOR_READ_TYPE:
             break;
           default:
             return false;
         }
--- a/gfx/ots/README.mozilla
+++ b/gfx/ots/README.mozilla
@@ -1,8 +1,8 @@
 This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
 
-Current revision: r77
+Current revision: r81
 
 Applied local patches:
     ots-fix-vc10.patch - workaround for VS10 STL wrappers (bug 602558)
 
     ots-fix-sparc64.patch - fix alignment error on sparc64 (bug 643137)
--- a/gfx/ots/include/opentype-sanitiser.h
+++ b/gfx/ots/include/opentype-sanitiser.h
@@ -72,18 +72,19 @@ class OTSStream {
         std::min(length, static_cast<size_t>(4) - chksum_buffer_offset_);
       std::memcpy(chksum_buffer_ + chksum_buffer_offset_, data, l);
       chksum_buffer_offset_ += l;
       offset += l;
       length -= l;
     }
 
     if (chksum_buffer_offset_ == 4) {
-      // TODO(yusukes): This cast breaks the strict-aliasing rule.
-      chksum_ += ntohl(*reinterpret_cast<const uint32_t*>(chksum_buffer_));
+      uint32_t chksum;
+      std::memcpy(&chksum, chksum_buffer_, 4);
+      chksum_ += ntohl(chksum);
       chksum_buffer_offset_ = 0;
     }
 
     while (length >= 4) {
       uint32_t tmp;
       std::memcpy(&tmp, reinterpret_cast<const uint8_t *>(data) + offset,
         sizeof(uint32_t));
       chksum_ += ntohl(tmp);
--- a/gfx/ots/src/cff.cc
+++ b/gfx/ots/src/cff.cc
@@ -755,24 +755,23 @@ bool ParseDictData(const uint8_t *data, 
             return OTS_FAILURE();
           }
           const uint32_t private_offset = operands.back().first;
           operands.pop_back();
           if (operands.back().second != DICT_OPERAND_INTEGER) {
             return OTS_FAILURE();
           }
           const uint32_t private_length = operands.back().first;
-          if (private_offset >= table_length) {
+          if (private_offset > table_length) {
             return OTS_FAILURE();
           }
           if (private_length >= table_length) {
             return OTS_FAILURE();
           }
           if (private_length + private_offset > table_length) {
-            // does not overflow since table_length < 1GB
             return OTS_FAILURE();
           }
           // parse "15. Private DICT Data"
           if (!ParsePrivateDictData(data, table_length,
                                     private_offset, private_length,
                                     type, out_cff)) {
             return OTS_FAILURE();
           }
--- a/gfx/ots/src/ots.cc
+++ b/gfx/ots/src/ots.cc
@@ -5,16 +5,17 @@
 #include "ots.h"
 
 #include <sys/types.h>
 #include <zlib.h>
 
 #include <algorithm>
 #include <cstdlib>
 #include <cstring>
+#include <limits>
 #include <map>
 #include <vector>
 
 // The OpenType Font File
 // http://www.microsoft.com/typography/otspec/cmap.htm
 
 namespace {
 
@@ -23,19 +24,22 @@ bool g_debug_output = true;
 struct OpenTypeTable {
   uint32_t tag;
   uint32_t chksum;
   uint32_t offset;
   uint32_t length;
   uint32_t uncompressed_length;
 };
 
-// Round a value up to the nearest multiple of 4. Note that this can overflow
-// and return zero.
+// Round a value up to the nearest multiple of 4. Don't round the value in the
+// case that rounding up overflows.
 template<typename T> T Round4(T value) {
+  if (std::numeric_limits<T>::max() - value < 3) {
+    return value;
+  }
   return (value + 3) & ~3;
 }
 
 bool CheckTag(uint32_t tag_value) {
   for (unsigned i = 0; i < 4; ++i) {
     const uint32_t check = tag_value & 0xff;
     if (check < 32 || check > 126) {
       return false;  // non-ASCII character found.
@@ -275,48 +279,135 @@ bool ProcessWOFF(ots::OpenTypeFile *head
   header->entry_selector = 0;
   header->range_shift = 0;
 
   uint32_t reported_length;
   if (!file.ReadU32(&reported_length) || length != reported_length) {
     return OTS_FAILURE();
   }
 
-  if (!file.ReadU16(&header->num_tables)) {
+  if (!file.ReadU16(&header->num_tables) || !header->num_tables) {
     return OTS_FAILURE();
   }
 
   uint16_t reserved_value;
   if (!file.ReadU16(&reserved_value) || reserved_value) {
     return OTS_FAILURE();
   }
 
+  uint32_t reported_total_sfnt_size;
+  if (!file.ReadU32(&reported_total_sfnt_size)) {
+    return OTS_FAILURE();
+  }
+
   // We don't care about these fields of the header:
-  //   uint32_t uncompressed_size;
   //   uint16_t major_version, minor_version
-  //   uint32_t meta_offset, meta_length, meta_length_orig
-  //   uint32_t priv_offset, priv_length
-  if (!file.Skip(6 * 4 + 2 * 2)) {
+  if (!file.Skip(2 * 2)) {
+    return OTS_FAILURE();
+  }
+
+  // Checks metadata block size.
+  uint32_t meta_offset;
+  uint32_t meta_length;
+  uint32_t meta_length_orig;
+  if (!file.ReadU32(&meta_offset) ||
+      !file.ReadU32(&meta_length) ||
+      !file.ReadU32(&meta_length_orig)) {
     return OTS_FAILURE();
   }
+  if (meta_offset) {
+    if (meta_offset >= length || length - meta_offset < meta_length) {
+      return OTS_FAILURE();
+    }
+  }
+
+  // Checks private data block size.
+  uint32_t priv_offset;
+  uint32_t priv_length;
+  if (!file.ReadU32(&priv_offset) ||
+      !file.ReadU32(&priv_length)) {
+    return OTS_FAILURE();
+  }
+  if (priv_offset) {
+    if (priv_offset >= length || length - priv_offset < priv_length) {
+      return OTS_FAILURE();
+    }
+  }
 
   // Next up is the list of tables.
   std::vector<OpenTypeTable> tables;
 
+  uint32_t first_index = 0;
+  uint32_t last_index = 0;
+  // Size of sfnt header plus size of table records.
+  uint64_t total_sfnt_size = 12 + 16 * header->num_tables;
   for (unsigned i = 0; i < header->num_tables; ++i) {
     OpenTypeTable table;
     if (!file.ReadTag(&table.tag) ||
         !file.ReadU32(&table.offset) ||
         !file.ReadU32(&table.length) ||
         !file.ReadU32(&table.uncompressed_length) ||
         !file.ReadU32(&table.chksum)) {
       return OTS_FAILURE();
     }
 
+    total_sfnt_size += Round4(table.uncompressed_length);
+    if (total_sfnt_size > std::numeric_limits<uint32_t>::max()) {
+      return OTS_FAILURE();
+    }
     tables.push_back(table);
+    if (i == 0 || tables[first_index].offset > table.offset)
+      first_index = i;
+    if (i == 0 || tables[last_index].offset < table.offset)
+      last_index = i;
+  }
+
+  if (reported_total_sfnt_size != total_sfnt_size) {
+    return OTS_FAILURE();
+  }
+
+  // Table data must follow immediately after the header.
+  if (tables[first_index].offset != Round4(file.offset())) {
+    return OTS_FAILURE();
+  }
+
+  if (tables[last_index].offset >= length ||
+      length - tables[last_index].offset < tables[last_index].length) {
+    return OTS_FAILURE();
+  }
+  // Blocks must follow immediately after the previous block.
+  // (Except for padding with a maximum of three null bytes)
+  uint64_t block_end = Round4(
+      static_cast<uint64_t>(tables[last_index].offset) +
+      static_cast<uint64_t>(tables[last_index].length));
+  if (block_end > std::numeric_limits<uint32_t>::max()) {
+    return OTS_FAILURE();
+  }
+  if (meta_offset) {
+    if (block_end != meta_offset) {
+      return OTS_FAILURE();
+    }
+    block_end = Round4(static_cast<uint64_t>(meta_offset) +
+                       static_cast<uint64_t>(meta_length));
+    if (block_end > std::numeric_limits<uint32_t>::max()) {
+      return OTS_FAILURE();
+    }
+  }
+  if (priv_offset) {
+    if (block_end != priv_offset) {
+      return OTS_FAILURE();
+    }
+    block_end = Round4(static_cast<uint64_t>(priv_offset) +
+                       static_cast<uint64_t>(priv_length));
+    if (block_end > std::numeric_limits<uint32_t>::max()) {
+      return OTS_FAILURE();
+    }
+  }
+  if (block_end != Round4(length)) {
+    return OTS_FAILURE();
   }
 
   return ProcessGeneric(header, output, data, length, tables, file);
 }
 
 bool ProcessGeneric(ots::OpenTypeFile *header, ots::OTSStream *output,
                     const uint8_t *data, size_t length,
                     const std::vector<OpenTypeTable>& tables,
@@ -373,21 +464,21 @@ bool ProcessGeneric(ots::OpenTypeFile *h
       if (uncompressed_sum + tables[i].uncompressed_length < uncompressed_sum) {
         return OTS_FAILURE();
       }
 
       uncompressed_sum += tables[i].uncompressed_length;
     }
     // since we required that the file be < 1GB in length, and that the table
     // length is < 1GB, the following addtion doesn't overflow
-    const uint32_t end_byte = Round4(tables[i].offset + tables[i].length);
+    const uint32_t end_byte = tables[i].offset + tables[i].length;
     // Some fonts which are automatically generated by a font generator
     // called TTX seems not to add 0-padding to the final table. It might be
     // ok to accept these fonts so we round up the length of the font file.
-    if (!end_byte || end_byte > Round4(length)) {
+    if (!end_byte || end_byte > length) {
       return OTS_FAILURE();
     }
   }
 
   // All decompressed tables uncompressed must be <= 30MB.
   if (uncompressed_sum > 30 * 1024 * 1024) {
     return OTS_FAILURE();
   }
--- a/gfx/thebes/gfx2DGlue.h
+++ b/gfx/thebes/gfx2DGlue.h
@@ -117,33 +117,31 @@ inline gfxContext::GraphicsLineCap Thebe
 {
   switch (aStyle) {
   case CAP_BUTT:
     return gfxContext::LINE_CAP_BUTT;
   case CAP_ROUND:
     return gfxContext::LINE_CAP_ROUND;
   case CAP_SQUARE:
     return gfxContext::LINE_CAP_SQUARE;
-  default:
-    return gfxContext::LINE_CAP_BUTT;
   }
+  MOZ_NOT_REACHED("Incomplete switch");
 }
 
 inline CapStyle ToCapStyle(gfxContext::GraphicsLineCap aStyle)
 {
   switch (aStyle) {
   case gfxContext::LINE_CAP_BUTT:
     return CAP_BUTT;
   case gfxContext::LINE_CAP_ROUND:
     return CAP_ROUND;
   case gfxContext::LINE_CAP_SQUARE:
     return CAP_SQUARE;
-  default:
-    return CAP_BUTT;
   }
+  MOZ_NOT_REACHED("Incomplete switch");
 }
 
 inline gfxContext::GraphicsLineJoin ThebesLineJoin(JoinStyle aStyle)
 {
   switch (aStyle) {
   case JOIN_MITER:
     return gfxContext::LINE_JOIN_MITER;
   case JOIN_BEVEL:
@@ -159,19 +157,18 @@ inline JoinStyle ToJoinStyle(gfxContext:
 {
   switch (aStyle) {
   case gfxContext::LINE_JOIN_MITER:
     return JOIN_MITER;
   case gfxContext::LINE_JOIN_BEVEL:
     return JOIN_BEVEL;
   case gfxContext::LINE_JOIN_ROUND:
     return JOIN_ROUND;
-  default:
-    return JOIN_MITER;
   }
+  MOZ_NOT_REACHED("Incomplete switch");
 }
 
 inline gfxMatrix ThebesMatrix(const Matrix &aMatrix)
 {
   return gfxMatrix(aMatrix._11, aMatrix._12, aMatrix._21,
                    aMatrix._22, aMatrix._31, aMatrix._32);
 }
 
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -155,20 +155,18 @@ GetBackendName(mozilla::gfx::BackendType
       case mozilla::gfx::BACKEND_COREGRAPHICS:
         return "quartz";
       case mozilla::gfx::BACKEND_CAIRO:
         return "cairo";
       case mozilla::gfx::BACKEND_SKIA:
         return "skia";
       case mozilla::gfx::BACKEND_NONE:
         return "none";
-      default:
-        NS_ERROR("Invalid backend type!");
-        return "";
   }
+  MOZ_NOT_REACHED("Incomplet switch");
 }
 
 class THEBES_API gfxPlatform {
 public:
     /**
      * Return a pointer to the current active platform.
      * This is a singleton; it contains mostly convenience
      * functions to obtain platform-specific objects.
--- a/gfx/thebes/gfxRect.h
+++ b/gfx/thebes/gfxRect.h
@@ -40,16 +40,17 @@
 
 #include "nsAlgorithm.h"
 #include "gfxTypes.h"
 #include "gfxPoint.h"
 #include "gfxCore.h"
 #include "nsDebug.h"
 #include "mozilla/gfx/BaseMargin.h"
 #include "mozilla/gfx/BaseRect.h"
+#include "mozilla/Assertions.h"
 #include "nsRect.h"
 
 struct gfxMargin : public mozilla::gfx::BaseMargin<gfxFloat, gfxMargin> {
   typedef mozilla::gfx::BaseMargin<gfxFloat, gfxMargin> Super;
 
   // Constructors
   gfxMargin() : Super() {}
   gfxMargin(const gfxMargin& aMargin) : Super(aMargin) {}
@@ -121,34 +122,28 @@ struct THEBES_API gfxRect :
     }
 
     gfxPoint CCWCorner(mozilla::css::Side side) const {
         switch (side) {
             case NS_SIDE_TOP: return TopLeft();
             case NS_SIDE_RIGHT: return TopRight();
             case NS_SIDE_BOTTOM: return BottomRight();
             case NS_SIDE_LEFT: return BottomLeft();
-            default:
-                NS_ERROR("Invalid side!");
-                break;
         }
-        return gfxPoint(0.0, 0.0);
+        MOZ_NOT_REACHED("Incomplet switch");
     }
 
     gfxPoint CWCorner(mozilla::css::Side side) const {
         switch (side) {
             case NS_SIDE_TOP: return TopRight();
             case NS_SIDE_RIGHT: return BottomRight();
             case NS_SIDE_BOTTOM: return BottomLeft();
             case NS_SIDE_LEFT: return TopLeft();
-            default:
-                NS_ERROR("Invalid side!");
-                break;
         }
-        return gfxPoint(0.0, 0.0);
+        MOZ_NOT_REACHED("Incomplet switch");
     }
 
     /* Conditions this border to Cairo's max coordinate space.
      * The caller can check IsEmpty() after Condition() -- if it's TRUE,
      * the caller can possibly avoid doing any extra rendering.
      */
     void Condition();
 
--- a/js/ipc/PObjectWrapper.ipdl
+++ b/js/ipc/PObjectWrapper.ipdl
@@ -50,18 +50,18 @@ namespace mozilla {
 namespace jsipc {
 
 union JSVariant {
     void_t;
     nullable PObjectWrapper;
     nsString;
     int;
     double;
-    bool; // We'd like to use JSBool here, but JSBool is really JSIntn,
-          // and IPC::ParamTraits mistakes JSIntn for int.
+    bool; // We'd like to use JSBool here, but IPC::ParamTraits would
+          // treat JSBool as int.
 };
 
 union OperationStatus {
     JSBool;
     JSVariant; // Exception thrown.
 };
 
 rpc protocol PObjectWrapper
--- a/js/jsd/jsd.h
+++ b/js/jsd/jsd.h
@@ -205,22 +205,22 @@ struct JSDScript
 struct JSDProfileData
 {
     JSDProfileData* caller;
     int64_t  lastCallStart;
     int64_t  runningTime;
     uintN    callCount;
     uintN    recurseDepth;
     uintN    maxRecurseDepth;
-    jsdouble minExecutionTime;
-    jsdouble maxExecutionTime;
-    jsdouble totalExecutionTime;
-    jsdouble minOwnExecutionTime;
-    jsdouble maxOwnExecutionTime;
-    jsdouble totalOwnExecutionTime;
+    double minExecutionTime;
+    double maxExecutionTime;
+    double totalExecutionTime;
+    double minOwnExecutionTime;
+    double maxOwnExecutionTime;
+    double totalOwnExecutionTime;
 };
 
 struct JSDSourceText
 {
     JSCList          links;      /* we are part of a JSCList */
     char*            url;
     char*            text;
     uintN            textLength;
@@ -412,32 +412,32 @@ extern void
 jsd_SetScriptFlags(JSDContext *jsdc, JSDScript *script, uint32_t flags);
 
 extern uintN
 jsd_GetScriptCallCount(JSDContext* jsdc, JSDScript *script);
 
 extern  uintN
 jsd_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script);
 
-extern jsdouble
+extern double
 jsd_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script);
 
-extern jsdouble
+extern double
 jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script);
 
-extern jsdouble
+extern double
 jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script);
 
-extern jsdouble
+extern double
 jsd_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
 
-extern jsdouble
+extern double
 jsd_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
 
-extern jsdouble
+extern double
 jsd_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
 
 extern void
 jsd_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script);
 
 extern JSScript *
 jsd_GetJSScript (JSDContext *jsdc, JSDScript *script);
 
@@ -967,17 +967,17 @@ jsd_IsValueNative(JSDContext* jsdc, JSDV
 /**************************************************/
 
 extern JSBool
 jsd_GetValueBoolean(JSDContext* jsdc, JSDValue* jsdval);
 
 extern int32_t
 jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval);
 
-extern jsdouble
+extern double
 jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval);
 
 extern JSString*
 jsd_GetValueString(JSDContext* jsdc, JSDValue* jsdval);
 
 extern JSString*
 jsd_GetValueFunctionId(JSDContext* jsdc, JSDValue* jsdval);
 
--- a/js/jsd/jsd_scpt.c
+++ b/js/jsd/jsd_scpt.c
@@ -362,62 +362,62 @@ uintN
 jsd_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script)
 {
     if (script->profileData)
         return script->profileData->maxRecurseDepth;
 
     return 0;
 }
 
-jsdouble
+double
 jsd_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     if (script->profileData)
         return script->profileData->minExecutionTime;
 
     return 0.0;
 }
 
-jsdouble
+double
 jsd_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     if (script->profileData)
         return script->profileData->maxExecutionTime;
 
     return 0.0;
 }
 
-jsdouble
+double
 jsd_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     if (script->profileData)
         return script->profileData->totalExecutionTime;
 
     return 0.0;
 }
 
-jsdouble
+double
 jsd_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     if (script->profileData)
         return script->profileData->minOwnExecutionTime;
 
     return 0.0;
 }
 
-jsdouble
+double
 jsd_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     if (script->profileData)
         return script->profileData->maxOwnExecutionTime;
 
     return 0.0;
 }
 
-jsdouble
+double
 jsd_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     if (script->profileData)
         return script->profileData->totalOwnExecutionTime;
 
     return 0.0;
 }
 
--- a/js/jsd/jsd_step.c
+++ b/js/jsd/jsd_step.c
@@ -182,17 +182,17 @@ JSBool
                         } else {
                             if (++pdata->recurseDepth > pdata->maxRecurseDepth)
                                 pdata->maxRecurseDepth = pdata->recurseDepth;
                         }
                         /* make sure we're called for the return too. */
                         hookresult = JS_TRUE;
                     } else if (!pdata->recurseDepth && pdata->lastCallStart) {
                         int64_t now, ll_delta;
-                        jsdouble delta;
+                        double delta;
                         now = JS_Now();
                         ll_delta = now - pdata->lastCallStart;
                         delta = ll_delta;
                         delta /= 1000.0;
                         pdata->totalExecutionTime += delta;
                         /* minExecutionTime starts as 0, so we need to overwrite
                          * it on the first call always. */
                         if ((0 == pdata->callCount) ||
--- a/js/jsd/jsd_val.c
+++ b/js/jsd/jsd_val.c
@@ -192,17 +192,17 @@ int32_t
 jsd_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
 {
     jsval val = jsdval->val;
     if(!JSVAL_IS_INT(val))
         return 0;
     return JSVAL_TO_INT(val);
 }
 
-jsdouble
+double
 jsd_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
 {
     if(!JSVAL_IS_DOUBLE(jsdval->val))
         return 0;
     return JSVAL_TO_DOUBLE(jsdval->val);
 }
 
 JSString*
--- a/js/jsd/jsdebug.c
+++ b/js/jsd/jsdebug.c
@@ -206,52 +206,52 @@ JSD_GetScriptCallCount(JSDContext* jsdc,
 JSD_PUBLIC_API(uintN)
 JSD_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_GetScriptMaxRecurseDepth(jsdc, script);
 }
     
 
-JSD_PUBLIC_API(jsdouble)
+JSD_PUBLIC_API(double)
 JSD_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_GetScriptMinExecutionTime(jsdc, script);
 }
     
-JSD_PUBLIC_API(jsdouble)
+JSD_PUBLIC_API(double)
 JSD_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_GetScriptMaxExecutionTime(jsdc, script);
 }
 
-JSD_PUBLIC_API(jsdouble)
+JSD_PUBLIC_API(double)
 JSD_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_GetScriptTotalExecutionTime(jsdc, script);
 }
 
-JSD_PUBLIC_API(jsdouble)
+JSD_PUBLIC_API(double)
 JSD_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_GetScriptMinOwnExecutionTime(jsdc, script);
 }
     
-JSD_PUBLIC_API(jsdouble)
+JSD_PUBLIC_API(double)
 JSD_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_GetScriptMaxOwnExecutionTime(jsdc, script);
 }
 
-JSD_PUBLIC_API(jsdouble)
+JSD_PUBLIC_API(double)
 JSD_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     return jsd_GetScriptTotalOwnExecutionTime(jsdc, script);
 }
 
 JSD_PUBLIC_API(void)
 JSD_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script)
@@ -1105,17 +1105,17 @@ JSD_GetValueBoolean(JSDContext* jsdc, JS
 JSD_PUBLIC_API(int32_t)
 JSD_GetValueInt(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     JSD_ASSERT_VALID_VALUE(jsdval);
     return jsd_GetValueInt(jsdc, jsdval);
 }
 
-JSD_PUBLIC_API(jsdouble)
+JSD_PUBLIC_API(double)
 JSD_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval)
 {
     JSD_ASSERT_VALID_CONTEXT(jsdc);
     JSD_ASSERT_VALID_VALUE(jsdval);
     return jsd_GetValueDouble(jsdc, jsdval);
 }
 
 JSD_PUBLIC_API(JSString*)
--- a/js/jsd/jsdebug.h
+++ b/js/jsd/jsdebug.h
@@ -328,50 +328,50 @@ JSD_GetScriptCallCount(JSDContext* jsdc,
 * Get the max number of times this script called itself, directly or indirectly.
 */
 extern JSD_PUBLIC_API(uintN)
 JSD_GetScriptMaxRecurseDepth(JSDContext* jsdc, JSDScript *script);
 
 /*
 * Get the shortest execution time recorded.
 */
-extern JSD_PUBLIC_API(jsdouble)
+extern JSD_PUBLIC_API(double)
 JSD_GetScriptMinExecutionTime(JSDContext* jsdc, JSDScript *script);
 
 /*
 * Get the longest execution time recorded.
 */
-extern JSD_PUBLIC_API(jsdouble)
+extern JSD_PUBLIC_API(double)
 JSD_GetScriptMaxExecutionTime(JSDContext* jsdc, JSDScript *script);
 
 /*
 * Get the total amount of time spent in this script.
 */
-extern JSD_PUBLIC_API(jsdouble)
+extern JSD_PUBLIC_API(double)
 JSD_GetScriptTotalExecutionTime(JSDContext* jsdc, JSDScript *script);
 
 /*
 * Get the shortest execution time recorded, excluding time spent in called
 * functions.
 */
-extern JSD_PUBLIC_API(jsdouble)
+extern JSD_PUBLIC_API(double)
 JSD_GetScriptMinOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
 
 /*
 * Get the longest execution time recorded, excluding time spent in called
 * functions.
 */
-extern JSD_PUBLIC_API(jsdouble)
+extern JSD_PUBLIC_API(double)
 JSD_GetScriptMaxOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
 
 /*
 * Get the total amount of time spent in this script, excluding time spent
 * in called functions.
 */
-extern JSD_PUBLIC_API(jsdouble)
+extern JSD_PUBLIC_API(double)
 JSD_GetScriptTotalOwnExecutionTime(JSDContext* jsdc, JSDScript *script);
 
 /*
 * Clear profile data for this script.
 */
 extern JSD_PUBLIC_API(void)
 JSD_ClearScriptProfileData(JSDContext* jsdc, JSDScript *script);
 
@@ -1288,17 +1288,17 @@ JSD_GetValueBoolean(JSDContext* jsdc, JS
 */
 extern JSD_PUBLIC_API(int32_t)
 JSD_GetValueInt(JSDContext* jsdc, JSDValue* jsdval);
 
 /*
 * Return double value (does NOT do conversion).
 * *** new for version 1.1 ****
 */
-extern JSD_PUBLIC_API(jsdouble)
+extern JSD_PUBLIC_API(double)
 JSD_GetValueDouble(JSDContext* jsdc, JSDValue* jsdval);
 
 /*
 * Return JSString value (DOES do conversion if necessary).
 * NOTE that the JSString returned is not protected from garbage
 * collection. It should be immediately read or wrapped using
 * JSD_NewValue(jsdc,STRING_TO_JSVAL(str)) if necessary.
 * *** new for version 1.1 ****
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -149,16 +149,17 @@ CPPSRCS		= \
 		jsxdrapi.cpp \
 		jsxml.cpp \
 		prmjtime.cpp \
 		sharkctl.cpp \
 		ScopeObject.cpp \
 		Debugger.cpp \
 		GlobalObject.cpp \
 		MethodGuard.cpp \
+		ObjectImpl.cpp \
 		Stack.cpp \
 		String.cpp \
 		BytecodeCompiler.cpp \
 		BytecodeEmitter.cpp \
 		FoldConstants.cpp \
 		ParseMaps.cpp \
 		ParseNode.cpp \
 		Parser.cpp \
--- a/js/src/assembler/jit/ExecutableAllocatorWin.cpp
+++ b/js/src/assembler/jit/ExecutableAllocatorWin.cpp
@@ -89,16 +89,18 @@ RandomizeIsBrokenImpl()
     // http://msdn.microsoft.com/en-us/library/ms724832%28v=vs.85%29.aspx
     // We disable everything before Vista, for now.
     return osvi.dwMajorVersion <= 5;
 }
 
 static bool
 RandomizeIsBroken()
 {
+    // Use the compiler's intrinsic guards for |static type value = expr| to avoid some potential
+    // races if runtimes are created from multiple threads.
     static int result = RandomizeIsBrokenImpl();
     return !!result;
 }
 
 ExecutablePool::Allocation ExecutableAllocator::systemAlloc(size_t n)
 {
     void *allocation = NULL;
     if (allocBehavior == AllocationCanRandomize && !RandomizeIsBroken()) {
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -81,17 +81,17 @@ HashableValue::setValue(JSContext *cx, c
 {
     if (v.isString() && v.toString()->isRope()) {
         /* Flatten this rope so that equals() is infallible. */
         JSString *str = v.toString()->ensureLinear(cx);
         if (!str)
             return false;
         value = StringValue(str);
     } else if (v.isDouble()) {
-        jsdouble d = v.toDouble();
+        double d = v.toDouble();
         int32_t i;
         if (JSDOUBLE_IS_INT32(d, &i)) {
             /* Normalize int32-valued doubles to int32 for faster hashing and testing. */
             value = Int32Value(i);
         } else if (JSDOUBLE_IS_NaN(d)) {
             /* NaNs with different bits must hash and test identically. */
             value = DoubleValue(js_NaN);
         } else {
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -597,17 +597,17 @@ ExecuteRegExp(JSContext *cx, Native nati
         return false;
     const jschar *chars = linearInput->chars();
     size_t length = input->length();
 
     /* Step 4. */
     const Value &lastIndex = reobj.getLastIndex();
 
     /* Step 5. */
-    jsdouble i;
+    double i;
     if (!ToInteger(cx, lastIndex, &i))
         return false;
 
     /* Steps 6-7 (with sticky extension). */
     if (!re->global() && !re->sticky())
         i = 0;
 
     /* Step 9a. */
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -452,17 +452,17 @@ static JSFunctionSpec sUInt64Functions[]
 static JSFunctionSpec sModuleFunctions[] = {
   JS_FN("open", Library::Open, 1, CTYPESFN_FLAGS),
   JS_FN("cast", CData::Cast, 2, CTYPESFN_FLAGS),
   JS_FN("getRuntime", CData::GetRuntime, 1, CTYPESFN_FLAGS),
   JS_FN("libraryName", Library::Name, 1, CTYPESFN_FLAGS),
   JS_FS_END
 };
 
-static inline bool FloatIsFinite(jsdouble f) {
+static inline bool FloatIsFinite(double f) {
 #ifdef WIN32
   return _finite(f) != 0;
 #else
   return finite(f);
 #endif
 }
 
 JS_ALWAYS_INLINE JSString*
@@ -999,42 +999,42 @@ struct ConvertImpl {
     return TargetType(d);
   }
 };
 
 #ifdef _MSC_VER
 // MSVC can't perform double to unsigned __int64 conversion when the
 // double is greater than 2^63 - 1. Help it along a little.
 template<>
-struct ConvertImpl<uint64_t, jsdouble> {
-  static JS_ALWAYS_INLINE uint64_t Convert(jsdouble d) {
+struct ConvertImpl<uint64_t, double> {
+  static JS_ALWAYS_INLINE uint64_t Convert(double d) {
     return d > 0x7fffffffffffffffui64 ?
            uint64_t(d - 0x8000000000000000ui64) + 0x8000000000000000ui64 :
            uint64_t(d);
   }
 };
 #endif
 
 // C++ doesn't guarantee that exact values are the only ones that will
 // round-trip. In fact, on some platforms, including SPARC, there are pairs of
 // values, a uint64_t and a double, such that neither value is exactly
 // representable in the other type, but they cast to each other.
 #ifdef SPARC
 // Simulate x86 overflow behavior
 template<>
-struct ConvertImpl<uint64_t, jsdouble> {
-  static JS_ALWAYS_INLINE uint64_t Convert(jsdouble d) {
+struct ConvertImpl<uint64_t, double> {
+  static JS_ALWAYS_INLINE uint64_t Convert(double d) {
     return d >= 0xffffffffffffffff ?
            0x8000000000000000 : uint64_t(d);
   }
 };
 
 template<>
-struct ConvertImpl<int64_t, jsdouble> {
-  static JS_ALWAYS_INLINE int64_t Convert(jsdouble d) {
+struct ConvertImpl<int64_t, double> {
+  static JS_ALWAYS_INLINE int64_t Convert(double d) {
     return d >= 0x7fffffffffffffff ?
            0x8000000000000000 : int64_t(d);
   }
 };
 #endif
 
 template<class TargetType, class FromType>
 static JS_ALWAYS_INLINE TargetType Convert(FromType d)
@@ -1136,41 +1136,41 @@ struct IsNegativeImpl<Type, true> {
 
 // Determine whether Type 'i' is negative.
 template<class Type>
 static JS_ALWAYS_INLINE bool IsNegative(Type i)
 {
   return IsNegativeImpl<Type, numeric_limits<Type>::is_signed>::Test(i);
 }
 
-// Implicitly convert val to bool, allowing JSBool, jsint, and jsdouble
+// Implicitly convert val to bool, allowing JSBool, jsint, and double
 // arguments numerically equal to 0 or 1.
 static bool
 jsvalToBool(JSContext* cx, jsval val, bool* result)
 {
   if (JSVAL_IS_BOOLEAN(val)) {
     *result = JSVAL_TO_BOOLEAN(val) != JS_FALSE;
     return true;
   }
   if (JSVAL_IS_INT(val)) {
     jsint i = JSVAL_TO_INT(val);
     *result = i != 0;
     return i == 0 || i == 1;
   }
   if (JSVAL_IS_DOUBLE(val)) {
-    jsdouble d = JSVAL_TO_DOUBLE(val);
+    double d = JSVAL_TO_DOUBLE(val);
     *result = d != 0;
     // Allow -0.
     return d == 1 || d == 0;
   }
   // Don't silently convert null to bool. It's probably a mistake.
   return false;
 }
 
-// Implicitly convert val to IntegerType, allowing JSBool, jsint, jsdouble,
+// Implicitly convert val to IntegerType, allowing JSBool, jsint, double,
 // Int64, UInt64, and CData integer types 't' where all values of 't' are
 // representable by IntegerType.
 template<class IntegerType>
 static bool
 jsvalToInteger(JSContext* cx, jsval val, IntegerType* result)
 {
   JS_STATIC_ASSERT(numeric_limits<IntegerType>::is_exact);
 
@@ -1178,17 +1178,17 @@ jsvalToInteger(JSContext* cx, jsval val,
     // Make sure the integer fits in the alotted precision, and has the right
     // sign.
     jsint i = JSVAL_TO_INT(val);
     return ConvertExact(i, result);
   }
   if (JSVAL_IS_DOUBLE(val)) {
     // Don't silently lose bits here -- check that val really is an
     // integer value, and has the right sign.
-    jsdouble d = JSVAL_TO_DOUBLE(val);
+    double d = JSVAL_TO_DOUBLE(val);
     return ConvertExact(d, result);
   }
   if (!JSVAL_IS_PRIMITIVE(val)) {
     JSObject* obj = JSVAL_TO_OBJECT(val);
     if (CData::IsCData(obj)) {
       JSObject* typeObj = CData::GetCType(obj);
       void* data = CData::GetData(obj);
 
@@ -1241,17 +1241,17 @@ jsvalToInteger(JSContext* cx, jsval val,
     *result = JSVAL_TO_BOOLEAN(val);
     JS_ASSERT(*result == 0 || *result == 1);
     return true;
   }
   // Don't silently convert null to an integer. It's probably a mistake.
   return false;
 }
 
-// Implicitly convert val to FloatType, allowing jsint, jsdouble,
+// Implicitly convert val to FloatType, allowing jsint, double,
 // Int64, UInt64, and CData numeric types 't' where all values of 't' are
 // representable by FloatType.
 template<class FloatType>
 static bool
 jsvalToFloat(JSContext *cx, jsval val, FloatType* result)
 {
   JS_STATIC_ASSERT(!numeric_limits<FloatType>::is_exact);
 
@@ -1354,17 +1354,17 @@ StringToInteger(JSContext* cx, JSString*
     if (i / base != ii) // overflow
       return false;
   }
 
   *result = i;
   return true;
 }
 
-// Implicitly convert val to IntegerType, allowing jsint, jsdouble,
+// Implicitly convert val to IntegerType, allowing jsint, double,
 // Int64, UInt64, and optionally a decimal or hexadecimal string argument.
 // (This is common code shared by jsvalToSize and the Int64/UInt64 constructors.)
 template<class IntegerType>
 static bool
 jsvalToBigInteger(JSContext* cx,
                   jsval val,
                   bool allowString,
                   IntegerType* result)
@@ -1375,17 +1375,17 @@ jsvalToBigInteger(JSContext* cx,
     // Make sure the integer fits in the alotted precision, and has the right
     // sign.
     jsint i = JSVAL_TO_INT(val);
     return ConvertExact(i, result);
   }
   if (JSVAL_IS_DOUBLE(val)) {
     // Don't silently lose bits here -- check that val really is an
     // integer value, and has the right sign.
-    jsdouble d = JSVAL_TO_DOUBLE(val);
+    double d = JSVAL_TO_DOUBLE(val);
     return ConvertExact(d, result);
   }
   if (allowString && JSVAL_IS_STRING(val)) {
     // Allow conversion from base-10 or base-16 strings, provided the result
     // fits in IntegerType. (This allows an Int64 or UInt64 object to be passed
     // to the JS array element operator, which will automatically call
     // toString() on the object for us.)
     return StringToInteger(cx, JSVAL_TO_STRING(val), result);
@@ -1405,28 +1405,28 @@ jsvalToBigInteger(JSContext* cx,
       int64_t i = Int64Base::GetInt(obj);
       return ConvertExact(i, result);
     }
   }
   return false;
 }
 
 // Implicitly convert val to a size value, where the size value is represented
-// by size_t but must also fit in a jsdouble.
+// by size_t but must also fit in a double.
 static bool
 jsvalToSize(JSContext* cx, jsval val, bool allowString, size_t* result)
 {
   if (!jsvalToBigInteger(cx, val, allowString, result))
     return false;
 
-  // Also check that the result fits in a jsdouble.
-  return Convert<size_t>(jsdouble(*result)) == *result;
-}
-
-// Implicitly convert val to IntegerType, allowing jsint, jsdouble,
+  // Also check that the result fits in a double.
+  return Convert<size_t>(double(*result)) == *result;
+}
+
+// Implicitly convert val to IntegerType, allowing jsint, double,
 // Int64, UInt64, and optionally a decimal or hexadecimal string argument.
 // (This is common code shared by jsvalToSize and the Int64/UInt64 constructors.)
 template<class IntegerType>
 static bool
 jsidToBigInteger(JSContext* cx,
                   jsid val,
                   bool allowString,
                   IntegerType* result)
@@ -1461,50 +1461,50 @@ jsidToBigInteger(JSContext* cx,
       int64_t i = Int64Base::GetInt(obj);
       return ConvertExact(i, result);
     }
   }
   return false;
 }
 
 // Implicitly convert val to a size value, where the size value is represented
-// by size_t but must also fit in a jsdouble.
+// by size_t but must also fit in a double.
 static bool
 jsidToSize(JSContext* cx, jsid val, bool allowString, size_t* result)
 {
   if (!jsidToBigInteger(cx, val, allowString, result))
     return false;
 
-  // Also check that the result fits in a jsdouble.
-  return Convert<size_t>(jsdouble(*result)) == *result;
+  // Also check that the result fits in a double.
+  return Convert<size_t>(double(*result)) == *result;
 }
 
 // Implicitly convert a size value to a jsval, ensuring that the size_t value
-// fits in a jsdouble.
+// fits in a double.
 static JSBool
 SizeTojsval(JSContext* cx, size_t size, jsval* result)
 {
-  if (Convert<size_t>(jsdouble(size)) != size) {
+  if (Convert<size_t>(double(size)) != size) {
     JS_ReportError(cx, "size overflow");
     return false;
   }
 
-  return JS_NewNumberValue(cx, jsdouble(size), result);
+  return JS_NewNumberValue(cx, double(size), result);
 }
 
 // Forcefully convert val to IntegerType when explicitly requested.
 template<class IntegerType>
 static bool
 jsvalToIntegerExplicit(jsval val, IntegerType* result)
 {
   JS_STATIC_ASSERT(numeric_limits<IntegerType>::is_exact);
 
   if (JSVAL_IS_DOUBLE(val)) {
     // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
-    jsdouble d = JSVAL_TO_DOUBLE(val);
+    double d = JSVAL_TO_DOUBLE(val);
     *result = FloatIsFinite(d) ? IntegerType(d) : 0;
     return true;
   }
   if (!JSVAL_IS_PRIMITIVE(val)) {
     // Convert Int64 and UInt64 values by C-style cast.
     JSObject* obj = JSVAL_TO_OBJECT(val);
     if (Int64::IsInt64(obj)) {
       int64_t i = Int64Base::GetInt(obj);
@@ -1527,31 +1527,31 @@ jsvalToPtrExplicit(JSContext* cx, jsval 
   if (JSVAL_IS_INT(val)) {
     // jsint always fits in intptr_t. If the integer is negative, cast through
     // an intptr_t intermediate to sign-extend.
     jsint i = JSVAL_TO_INT(val);
     *result = i < 0 ? uintptr_t(intptr_t(i)) : uintptr_t(i);
     return true;
   }
   if (JSVAL_IS_DOUBLE(val)) {
-    jsdouble d = JSVAL_TO_DOUBLE(val);
+    double d = JSVAL_TO_DOUBLE(val);
     if (d < 0) {
       // Cast through an intptr_t intermediate to sign-extend.
       intptr_t i = Convert<intptr_t>(d);
-      if (jsdouble(i) != d)
+      if (double(i) != d)
         return false;
 
       *result = uintptr_t(i);
       return true;
     }
 
     // Don't silently lose bits here -- check that val really is an
     // integer value, and has the right sign.
     *result = Convert<uintptr_t>(d);
-    return jsdouble(*result) == d;
+    return double(*result) == d;
   }
   if (!JSVAL_IS_PRIMITIVE(val)) {
     JSObject* obj = JSVAL_TO_OBJECT(val);
     if (Int64::IsInt64(obj)) {
       int64_t i = Int64Base::GetInt(obj);
       intptr_t p = intptr_t(i);
 
       // Make sure the integer fits in the alotted precision.
@@ -1646,17 +1646,17 @@ ConvertToJS(JSContext* cx,
   case TYPE_bool:
     *result = *static_cast<bool*>(data) ? JSVAL_TRUE : JSVAL_FALSE;
     break;
 #define DEFINE_INT_TYPE(name, type, ffiType)                                   \
   case TYPE_##name: {                                                          \
     type value = *static_cast<type*>(data);                                    \
     if (sizeof(type) < 4)                                                      \
       *result = INT_TO_JSVAL(jsint(value));                                    \
-    else if (!JS_NewNumberValue(cx, jsdouble(value), result))                  \
+    else if (!JS_NewNumberValue(cx, double(value), result))                    \
       return false;                                                            \
     break;                                                                     \
   }
 #define DEFINE_WRAPPED_INT_TYPE(name, type, ffiType)                           \
   case TYPE_##name: {                                                          \
     /* Return an Int64 or UInt64 object - do not convert to a JS number. */    \
     uint64_t value;                                                            \
     JSObject* proto;                                                           \
@@ -1675,17 +1675,17 @@ ConvertToJS(JSContext* cx,
     if (!obj)                                                                  \
       return false;                                                            \
     *result = OBJECT_TO_JSVAL(obj);                                            \
     break;                                                                     \
   }
 #define DEFINE_FLOAT_TYPE(name, type, ffiType)                                 \
   case TYPE_##name: {                                                          \
     type value = *static_cast<type*>(data);                                    \
-    if (!JS_NewNumberValue(cx, jsdouble(value), result))                       \
+    if (!JS_NewNumberValue(cx, double(value), result))                         \
       return false;                                                            \
     break;                                                                     \
   }
 #define DEFINE_CHAR_TYPE(name, type, ffiType)                                  \
   case TYPE_##name:                                                            \
     /* Convert to an integer. We have no idea what character encoding to */    \
     /* use, if any. */                                                         \
     *result = INT_TO_JSVAL(*static_cast<type*>(data));                         \
@@ -2924,17 +2924,17 @@ CType::TypesEqual(JSObject* t1, JSObject
 
 bool
 CType::GetSafeSize(JSObject* obj, size_t* result)
 {
   JS_ASSERT(CType::IsCType(obj));
 
   jsval size = JS_GetReservedSlot(obj, SLOT_SIZE);
 
-  // The "size" property can be a jsint, a jsdouble, or JSVAL_VOID
+  // The "size" property can be a jsint, a double, or JSVAL_VOID
   // (for arrays of undefined length), and must always fit in a size_t.
   if (JSVAL_IS_INT(size)) {
     *result = JSVAL_TO_INT(size);
     return true;
   }
   if (JSVAL_IS_DOUBLE(size)) {
     *result = Convert<size_t>(JSVAL_TO_DOUBLE(size));
     return true;
@@ -2948,32 +2948,32 @@ size_t
 CType::GetSize(JSObject* obj)
 {
   JS_ASSERT(CType::IsCType(obj));
 
   jsval size = JS_GetReservedSlot(obj, SLOT_SIZE);
 
   JS_ASSERT(!JSVAL_IS_VOID(size));
 
-  // The "size" property can be a jsint, a jsdouble, or JSVAL_VOID
+  // The "size" property can be a jsint, a double, or JSVAL_VOID
   // (for arrays of undefined length), and must always fit in a size_t.
   // For callers who know it can never be JSVAL_VOID, return a size_t directly.
   if (JSVAL_IS_INT(size))
     return JSVAL_TO_INT(size);
   return Convert<size_t>(JSVAL_TO_DOUBLE(size));
 }
 
 bool
 CType::IsSizeDefined(JSObject* obj)
 {
   JS_ASSERT(CType::IsCType(obj));
 
   jsval size = JS_GetReservedSlot(obj, SLOT_SIZE);
 
-  // The "size" property can be a jsint, a jsdouble, or JSVAL_VOID
+  // The "size" property can be a jsint, a double, or JSVAL_VOID
   // (for arrays of undefined length), and must always fit in a size_t.
   JS_ASSERT(JSVAL_IS_INT(size) || JSVAL_IS_DOUBLE(size) || JSVAL_IS_VOID(size));
   return !JSVAL_IS_VOID(size);
 }
 
 size_t
 CType::GetAlignment(JSObject* obj)
 {
@@ -3594,17 +3594,17 @@ ArrayType::CreateInternal(JSContext* cx,
   if (!CType::GetSafeSize(baseType, &baseSize)) {
     JS_ReportError(cx, "base size must be defined");
     return NULL;
   }
 
   jsval sizeVal = JSVAL_VOID;
   jsval lengthVal = JSVAL_VOID;
   if (lengthDefined) {
-    // Check for overflow, and convert to a jsint or jsdouble as required.
+    // Check for overflow, and convert to a jsint or double as required.
     size_t size = length * baseSize;
     if (length > 0 && size / length != baseSize) {
       JS_ReportError(cx, "size overflow");
       return NULL;
     }
     if (!SizeTojsval(cx, size, &sizeVal) ||
         !SizeTojsval(cx, length, &lengthVal))
       return NULL;
@@ -3745,17 +3745,17 @@ ArrayType::GetBaseType(JSObject* obj)
 bool
 ArrayType::GetSafeLength(JSObject* obj, size_t* result)
 {
   JS_ASSERT(CType::IsCType(obj));
   JS_ASSERT(CType::GetTypeCode(obj) == TYPE_array);
 
   jsval length = JS_GetReservedSlot(obj, SLOT_LENGTH);
 
-  // The "length" property can be a jsint, a jsdouble, or JSVAL_VOID
+  // The "length" property can be a jsint, a double, or JSVAL_VOID
   // (for arrays of undefined length), and must always fit in a size_t.
   if (JSVAL_IS_INT(length)) {
     *result = JSVAL_TO_INT(length);
     return true;
   }
   if (JSVAL_IS_DOUBLE(length)) {
     *result = Convert<size_t>(JSVAL_TO_DOUBLE(length));
     return true;
@@ -3770,17 +3770,17 @@ ArrayType::GetLength(JSObject* obj)
 {
   JS_ASSERT(CType::IsCType(obj));
   JS_ASSERT(CType::GetTypeCode(obj) == TYPE_array);
 
   jsval length = JS_GetReservedSlot(obj, SLOT_LENGTH);
 
   JS_ASSERT(!JSVAL_IS_VOID(length));
 
-  // The "length" property can be a jsint, a jsdouble, or JSVAL_VOID
+  // The "length" property can be a jsint, a double, or JSVAL_VOID
   // (for arrays of undefined length), and must always fit in a size_t.
   // For callers who know it can never be JSVAL_VOID, return a size_t directly.
   if (JSVAL_IS_INT(length))
     return JSVAL_TO_INT(length);
   return Convert<size_t>(JSVAL_TO_DOUBLE(length));
 }
 
 ffi_type*
@@ -6202,17 +6202,17 @@ Int64::Lo(JSContext* cx, uintN argc, jsv
   if (argc != 1 || JSVAL_IS_PRIMITIVE(argv[0]) ||
       !Int64::IsInt64(JSVAL_TO_OBJECT(argv[0]))) {
     JS_ReportError(cx, "lo takes one Int64 argument");
     return JS_FALSE;
   }
 
   JSObject* obj = JSVAL_TO_OBJECT(argv[0]);
   int64_t u = Int64Base::GetInt(obj);
-  jsdouble d = uint32_t(INT64_LO(u));
+  double d = uint32_t(INT64_LO(u));
 
   jsval result;
   if (!JS_NewNumberValue(cx, d, &result))
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, result);
   return JS_TRUE;
 }
@@ -6224,17 +6224,17 @@ Int64::Hi(JSContext* cx, uintN argc, jsv
   if (argc != 1 || JSVAL_IS_PRIMITIVE(argv[0]) ||
       !Int64::IsInt64(JSVAL_TO_OBJECT(argv[0]))) {
     JS_ReportError(cx, "hi takes one Int64 argument");
     return JS_FALSE;
   }
 
   JSObject* obj = JSVAL_TO_OBJECT(argv[0]);
   int64_t u = Int64Base::GetInt(obj);
-  jsdouble d = int32_t(INT64_HI(u));
+  double d = int32_t(INT64_HI(u));
 
   jsval result;
   if (!JS_NewNumberValue(cx, d, &result))
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, result);
   return JS_TRUE;
 }
@@ -6369,17 +6369,17 @@ UInt64::Lo(JSContext* cx, uintN argc, js
   if (argc != 1 || JSVAL_IS_PRIMITIVE(argv[0]) ||
       !UInt64::IsUInt64(JSVAL_TO_OBJECT(argv[0]))) {
     JS_ReportError(cx, "lo takes one UInt64 argument");
     return JS_FALSE;
   }
 
   JSObject* obj = JSVAL_TO_OBJECT(argv[0]);
   uint64_t u = Int64Base::GetInt(obj);
-  jsdouble d = uint32_t(INT64_LO(u));
+  double d = uint32_t(INT64_LO(u));
 
   jsval result;
   if (!JS_NewNumberValue(cx, d, &result))
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, result);
   return JS_TRUE;
 }
@@ -6391,17 +6391,17 @@ UInt64::Hi(JSContext* cx, uintN argc, js
   if (argc != 1 || JSVAL_IS_PRIMITIVE(argv[0]) ||
       !UInt64::IsUInt64(JSVAL_TO_OBJECT(argv[0]))) {
     JS_ReportError(cx, "hi takes one UInt64 argument");
     return JS_FALSE;
   }
 
   JSObject* obj = JSVAL_TO_OBJECT(argv[0]);
   uint64_t u = Int64Base::GetInt(obj);
-  jsdouble d = uint32_t(INT64_HI(u));
+  double d = uint32_t(INT64_HI(u));
 
   jsval result;
   if (!JS_NewNumberValue(cx, d, &result))
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, result);
   return JS_TRUE;
 }
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -87,19 +87,16 @@
 using namespace js;
 using namespace js::gc;
 using namespace js::frontend;
 
 static JSBool
 NewTryNote(JSContext *cx, BytecodeEmitter *bce, JSTryNoteKind kind, uintN stackDepth,
            size_t start, size_t end);
 
-static bool
-EmitIndexOp(JSContext *cx, JSOp op, uintN index, BytecodeEmitter *bce, JSOp *psuffix = NULL);
-
 static JSBool
 SetSrcNoteOffset(JSContext *cx, BytecodeEmitter *bce, uintN index, uintN which, ptrdiff_t offset);
 
 void
 TreeContext::trace(JSTracer *trc)
 {
     bindings.trace(trc);
 }
@@ -861,133 +858,87 @@ LookupCompileTimeConstant(JSContext *cx,
                 if (shape)
                     break;
             }
         }
     } while (bce->parent && (bce = bce->parent->asBytecodeEmitter()));
     return JS_TRUE;
 }
 
-static inline bool
-FitsWithoutBigIndex(uintN index)
-{
-    return index < JS_BIT(16);
-}
-
-/*
- * Return JSOP_NOP to indicate that index fits 2 bytes and no index segment
- * reset instruction is necessary, JSOP_FALSE to indicate an error or either
- * JSOP_RESETBASE0 or JSOP_RESETBASE1 to indicate the reset bytecode to issue
- * after the main bytecode sequence.
- */
-static JSOp
-EmitBigIndexPrefix(JSContext *cx, BytecodeEmitter *bce, uintN index)
+static bool
+EmitIndex32(JSContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
 {
-    uintN indexBase;
-
-    /*
-     * We have max 3 bytes for indexes and check for INDEX_LIMIT overflow only
-     * for big indexes.
-     */
-    JS_STATIC_ASSERT(INDEX_LIMIT <= JS_BIT(24));
-    JS_STATIC_ASSERT(INDEX_LIMIT >=
-                     (JSOP_INDEXBASE3 - JSOP_INDEXBASE1 + 2) << 16);
-
-    if (FitsWithoutBigIndex(index))
-        return JSOP_NOP;
-    indexBase = index >> 16;
-    if (indexBase <= JSOP_INDEXBASE3 - JSOP_INDEXBASE1 + 1) {
-        if (Emit1(cx, bce, (JSOp)(JSOP_INDEXBASE1 + indexBase - 1)) < 0)
-            return JSOP_FALSE;
-        return JSOP_RESETBASE0;
-    }
-
-    if (index >= INDEX_LIMIT) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                             JSMSG_TOO_MANY_LITERALS);
-        return JSOP_FALSE;
-    }
-
-    if (Emit2(cx, bce, JSOP_INDEXBASE, (JSOp)indexBase) < 0)
-        return JSOP_FALSE;
-    return JSOP_RESETBASE;
+    const size_t len = 1 + UINT32_INDEX_LEN;
+    JS_ASSERT(len == size_t(js_CodeSpec[op].length));
+    ptrdiff_t offset = EmitCheck(cx, bce, len);
+    if (offset < 0)
+        return false;
+
+    jsbytecode *next = bce->next();
+    next[0] = jsbytecode(op);
+    SET_UINT32_INDEX(next, index);
+    bce->current->next = next + len;
+    UpdateDepth(cx, bce, offset);
+    CheckTypeSet(cx, bce, op);
+    return true;
 }
 
-/*
- * Emit a bytecode and its 2-byte constant index immediate operand. If the
- * index requires more than 2 bytes, emit a prefix op whose 8-bit immediate
- * operand effectively extends the 16-bit immediate of the prefixed opcode,
- * by changing index "segment" (see jsinterp.c). We optimize segments 1-3
- * with single-byte JSOP_INDEXBASE[123] codes.
- *
- * Such prefixing currently requires a suffix to restore the "zero segment"
- * register setting, but this could be optimized further.
- */
-static bool
-EmitIndexOp(JSContext *cx, JSOp op, uintN index, BytecodeEmitter *bce, JSOp *psuffix)
-{
-    JSOp bigSuffix;
-
-    bigSuffix = EmitBigIndexPrefix(cx, bce, index);
-    if (bigSuffix == JSOP_FALSE)
-        return false;
-    EMIT_UINT16_IMM_OP(op, index);
-
-    /*
-     * For decomposed ops, the suffix needs to go after the decomposed version.
-     * This means the suffix will run in the interpreter in both the base
-     * and decomposed paths, which works as suffix ops are idempotent.
-     */
-    JS_ASSERT(!!(js_CodeSpec[op].format & JOF_DECOMPOSE) == (psuffix != NULL));
-    if (psuffix) {
-        *psuffix = bigSuffix;
-        return true;
-    }
-
-    return bigSuffix == JSOP_NOP || Emit1(cx, bce, bigSuffix) >= 0;
-}
-
-/*
- * Slight sugar for EmitIndexOp, again accessing cx and bce from the macro
- * caller's lexical environment, and embedding a false return on error.
- */
-#define EMIT_INDEX_OP(op, index)                                              \
-    JS_BEGIN_MACRO                                                            \
-        if (!EmitIndexOp(cx, op, index, bce))                                 \
-            return JS_FALSE;                                                  \
-    JS_END_MACRO
-
 static bool
-EmitAtomOp(JSContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce, JSOp *psuffix = NULL)
+EmitIndexOp(JSContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
+{
+    const size_t len = js_CodeSpec[op].length;
+    JS_ASSERT(len >= 1 + UINT32_INDEX_LEN);
+    ptrdiff_t offset = EmitCheck(cx, bce, len);
+    if (offset < 0)
+        return false;
+
+    jsbytecode *next = bce->next();
+    next[0] = jsbytecode(op);
+    SET_UINT32_INDEX(next, index);
+    bce->current->next = next + len;
+    UpdateDepth(cx, bce, offset);
+    CheckTypeSet(cx, bce, op);
+    return true;
+}
+
+static bool
+EmitAtomOp(JSContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce)
 {
     JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
 
     if (op == JSOP_GETPROP && atom == cx->runtime->atomState.lengthAtom) {
         /* Specialize length accesses for the interpreter. */
         op = JSOP_LENGTH;
     }
 
     jsatomid index;
     if (!bce->makeAtomIndex(atom, &index))
         return false;
 
-    return EmitIndexOp(cx, op, index, bce, psuffix);
+    return EmitIndexOp(cx, op, index, bce);
+}
+
+static bool
+EmitAtomOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
+{
+    JS_ASSERT(pn->pn_atom != NULL);
+    return EmitAtomOp(cx, pn->pn_atom, op, bce);
 }
 
 static bool
-EmitAtomOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce, JSOp *psuffix = NULL)
+EmitAtomIncDec(JSContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce)
 {
-    JS_ASSERT(pn->pn_atom != NULL);
-    return EmitAtomOp(cx, pn->pn_atom, op, bce, psuffix);
-}
-
-static bool
-EmitIndex32(JSContext *cx, JSOp op, uint32_t index, BytecodeEmitter *bce)
-{
-    const size_t len = 1 + UINT32_INDEX_LEN;
+    JS_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
+    JS_ASSERT(js_CodeSpec[op].format & (JOF_INC | JOF_DEC));
+
+    jsatomid index;
+    if (!bce->makeAtomIndex(atom, &index))
+        return false;
+
+    const size_t len = 1 + UINT32_INDEX_LEN + 1;
     JS_ASSERT(size_t(js_CodeSpec[op].length) == len);
     ptrdiff_t offset = EmitCheck(cx, bce, len);
     if (offset < 0)
         return false;
 
     jsbytecode *next = bce->next();
     next[0] = jsbytecode(op);
     SET_UINT32_INDEX(next, index);
@@ -1021,17 +972,17 @@ EmitSlotObjectOp(JSContext *cx, JSOp op,
 {
     JS_ASSERT(JOF_OPTYPE(op) == JOF_SLOTOBJECT);
 
     ptrdiff_t off = EmitN(cx, bce, op, SLOTNO_LEN + UINT32_INDEX_LEN);
     if (off < 0)
         return false;
 
     jsbytecode *pc = bce->code(off);
-    SET_UINT16(pc, slot);
+    SET_SLOTNO(pc, slot);
     pc += SLOTNO_LEN;
     SET_UINT32_INDEX(pc, index);
     return true;
 }
 
 bool
 BytecodeEmitter::shouldNoteClosedName(ParseNode *pn)
 {
@@ -1882,16 +1833,17 @@ EmitNameOp(JSContext *cx, BytecodeEmitte
         }
     }
 
     if (op == JSOP_ARGUMENTS || op == JSOP_CALLEE) {
         if (Emit1(cx, bce, op) < 0)
             return JS_FALSE;
     } else {
         if (!pn->pn_cookie.isFree()) {
+            JS_ASSERT(JOF_OPTYPE(op) != JOF_ATOM);
             EMIT_UINT16_IMM_OP(op, pn->pn_cookie.asInteger());
         } else {
             if (!EmitAtomOp(cx, pn, op, bce))
                 return JS_FALSE;
         }
     }
 
     /* Need to provide |this| value for call */
@@ -1950,34 +1902,34 @@ EmitSpecialPropOp(JSContext *cx, ParseNo
     /*
      * Special case for obj.__proto__ to deoptimize away from fast paths in the
      * interpreter and trace recorder, which skip dense array instances by
      * going up to Array.prototype before looking up the property name.
      */
     jsatomid index;
     if (!bce->makeAtomIndex(pn->pn_atom, &index))
         return false;
-    if (!EmitIndexOp(cx, JSOP_QNAMEPART, index, bce))
+    if (!EmitIndex32(cx, JSOP_QNAMEPART, index, bce))
         return false;
 
     if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_DUP) < 0)
         return false;
 
     if (!EmitElemOpBase(cx, bce, op))
         return false;
 
     if (op == JSOP_CALLELEM && Emit1(cx, bce, JSOP_SWAP) < 0)
         return false;
 
     return true;
 }
 
 static bool
 EmitPropOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce,
-           JSBool callContext, JSOp *psuffix = NULL)
+           JSBool callContext)
 {
     ParseNode *pn2, *pndot, *pnup, *pndown;
     ptrdiff_t top;
 
     JS_ASSERT(pn->isArity(PN_NAME));
     pn2 = pn->maybeExpr();
 
     /* Special case deoptimization for __proto__. */
@@ -2048,43 +2000,37 @@ EmitPropOp(JSContext *cx, ParseNode *pn,
     }
 
     if (op == JSOP_CALLPROP && Emit1(cx, bce, JSOP_DUP) < 0)
         return false;
 
     if (NewSrcNote2(cx, bce, SRC_PCBASE, bce->offset() - pn2->pn_offset) < 0)
         return false;
 
-    if (!EmitAtomOp(cx, pn, op, bce, psuffix))
+    if (!EmitAtomOp(cx, pn, op, bce))
         return false;
 
     if (op == JSOP_CALLPROP && Emit1(cx, bce, JSOP_SWAP) < 0)
         return false;
 
     return true;
 }
 
 static bool
 EmitPropIncDec(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
-    JSOp suffix = JSOP_NOP;
-    if (!EmitPropOp(cx, pn, op, bce, false, &suffix))
-        return false;
-    if (Emit1(cx, bce, JSOP_NOP) < 0)
+    if (!EmitPropOp(cx, pn, op, bce, false))
         return false;
 
     /*
      * The stack is the same depth before/after INCPROP, so no balancing to do
      * before the decomposed version.
      */
     int start = bce->offset();
 
-    if (suffix != JSOP_NOP && Emit1(cx, bce, suffix) < 0)
-        return false;
-
     const JSCodeSpec *cs = &js_CodeSpec[op];
     JS_ASSERT(cs->format & JOF_PROP);
     JS_ASSERT(cs->format & (JOF_INC | JOF_DEC));
 
     bool post = (cs->format & JOF_POST);
     JSOp binop = (cs->format & JOF_INC) ? JSOP_ADD : JSOP_SUB;
 
                                                     // OBJ
@@ -2110,39 +2056,31 @@ EmitPropIncDec(JSContext *cx, ParseNode 
 
     if (!EmitAtomOp(cx, pn, JSOP_SETPROP, bce))     // N? N+1
         return false;
     if (post && Emit1(cx, bce, JSOP_POP) < 0)       // RESULT
         return false;
 
     UpdateDecomposeLength(bce, start);
 
-    if (suffix != JSOP_NOP && Emit1(cx, bce, suffix) < 0)
-        return false;
-
     return true;
 }
 
 static bool
 EmitNameIncDec(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
-    JSOp suffix = JSOP_NOP;
-    if (!EmitAtomOp(cx, pn, op, bce, &suffix))
-        return false;
-    if (Emit1(cx, bce, JSOP_NOP) < 0)
+    /* Emit the composite op, including the slack byte at the end. */
+    if (!EmitAtomIncDec(cx, pn->pn_atom, op, bce))
         return false;
 
     /* Remove the result to restore the stack depth before the INCNAME. */
     bce->stackDepth--;
 
     int start = bce->offset();
 
-    if (suffix != JSOP_NOP && Emit1(cx, bce, suffix) < 0)
-        return false;
-
     const JSCodeSpec *cs = &js_CodeSpec[op];
     JS_ASSERT((cs->format & JOF_NAME) || (cs->format & JOF_GNAME));
     JS_ASSERT(cs->format & (JOF_INC | JOF_DEC));
 
     bool global = (cs->format & JOF_GNAME);
     bool post = (cs->format & JOF_POST);
     JSOp binop = (cs->format & JOF_INC) ? JSOP_ADD : JSOP_SUB;
 
@@ -2168,19 +2106,16 @@ EmitNameIncDec(JSContext *cx, ParseNode 
 
     if (!EmitAtomOp(cx, pn, global ? JSOP_SETGNAME : JSOP_SETNAME, bce))    // N? N+1
         return false;
     if (post && Emit1(cx, bce, JSOP_POP) < 0)       // RESULT
         return false;
 
     UpdateDecomposeLength(bce, start);
 
-    if (suffix != JSOP_NOP && Emit1(cx, bce, suffix) < 0)
-        return false;
-
     return true;
 }
 
 static JSBool
 EmitElemOp(JSContext *cx, ParseNode *pn, JSOp op, BytecodeEmitter *bce)
 {
     ParseNode *left, *right;
 
@@ -2296,17 +2231,17 @@ EmitElemIncDec(JSContext *cx, ParseNode 
         return false;
 
     UpdateDecomposeLength(bce, start);
 
     return true;
 }
 
 static JSBool
-EmitNumberOp(JSContext *cx, jsdouble dval, BytecodeEmitter *bce)
+EmitNumberOp(JSContext *cx, double dval, BytecodeEmitter *bce)
 {
     int32_t ival;
     uint32_t u;
     ptrdiff_t off;
     jsbytecode *pc;
 
     if (JSDOUBLE_IS_INT32(dval, &ival)) {
         if (ival == 0)
@@ -2333,17 +2268,17 @@ EmitNumberOp(JSContext *cx, jsdouble dva
             SET_INT32(pc, ival);
         }
         return JS_TRUE;
     }
 
     if (!bce->constList.append(DoubleValue(dval)))
         return JS_FALSE;
 
-    return EmitIndexOp(cx, JSOP_DOUBLE, bce->constList.length() - 1, bce);
+    return EmitIndex32(cx, JSOP_DOUBLE, bce->constList.length() - 1, bce);
 }
 
 /*
  * To avoid bloating all parse nodes for the special case of switch, values are
  * allocated in the temp pool and pointed to by the parse node. These values
  * are not currently recycled (like parse nodes) and the temp pool is only
  * flushed at the end of compiling a script, so these values are technically
  * leaked. This would only be a problem for scripts containing a large number
@@ -2607,18 +2542,18 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
          */
         switchSize = (size_t)(JUMP_OFFSET_LEN * (3 + tableLength));
     } else {
         /*
          * JSOP_LOOKUPSWITCH:
          * 1 offset (len) and 1 atom index (npairs) before the table,
          * 1 atom index and 1 jump offset per entry.
          */
-        switchSize = (size_t)(JUMP_OFFSET_LEN + INDEX_LEN +
-                              (INDEX_LEN + JUMP_OFFSET_LEN) * caseCount);
+        switchSize = (size_t)(JUMP_OFFSET_LEN + UINT16_LEN +
+                              (UINT32_INDEX_LEN + JUMP_OFFSET_LEN) * caseCount);
     }
 
     /* Emit switchOp followed by switchSize bytes of jump or lookup table. */
     if (EmitN(cx, bce, switchOp, switchSize) < 0)
         return JS_FALSE;
 
     off = -1;
     if (switchOp == JSOP_CONDSWITCH) {
@@ -2706,18 +2641,18 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
                     JS_ASSERT((uint32_t)i < tableLength);
                     table[i] = pn3;
                 }
             }
         } else {
             JS_ASSERT(switchOp == JSOP_LOOKUPSWITCH);
 
             /* Fill in the number of cases. */
-            SET_INDEX(pc, caseCount);
-            pc += INDEX_LEN;
+            SET_UINT16(pc, caseCount);
+            pc += UINT16_LEN;
         }
 
         /*
          * After this point, all control flow involving JSOP_TABLESWITCH
          * must set ok and goto out to exit this function.  To keep things
          * simple, all switchOp cases exit that way.
          */
         MUST_FLOW_THROUGH("out");
@@ -2756,17 +2691,17 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
                         JS_ASSERT(!pn4->maybeExpr());
                         jsatomid index;
                         if (!bce->makeAtomIndex(pn4->pn_atom, &index))
                             goto bad;
                         bce->current->next = pc;
                         if (NewSrcNote2(cx, bce, SRC_LABEL, ptrdiff_t(index)) < 0)
                             goto bad;
                     }
-                    pc += INDEX_LEN + JUMP_OFFSET_LEN;
+                    pc += UINT32_INDEX_LEN + JUMP_OFFSET_LEN;
                 }
             }
             bce->current->next = savepc;
         }
     }
 
     /* Emit code for each case's statements, copying pn_offset up to pn3. */
     for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
@@ -2814,25 +2749,25 @@ EmitSwitch(JSContext *cx, BytecodeEmitte
         for (i = 0; i < (jsint)tableLength; i++) {
             pn3 = table[i];
             off = pn3 ? pn3->pn_offset - top : 0;
             SET_JUMP_OFFSET(pc, off);
             pc += JUMP_OFFSET_LEN;
         }
     } else if (switchOp == JSOP_LOOKUPSWITCH) {
         /* Skip over the already-initialized number of cases. */
-        pc += INDEX_LEN;
+        pc += UINT16_LEN;
 
         for (pn3 = pn2->pn_head; pn3; pn3 = pn3->pn_next) {
             if (pn3->isKind(PNK_DEFAULT))
                 continue;
             if (!bce->constList.append(*pn3->pn_pval))
                 goto bad;
-            SET_INDEX(pc, bce->constList.length() - 1);
-            pc += INDEX_LEN;
+            SET_UINT32_INDEX(pc, bce->constList.length() - 1);
+            pc += UINT32_INDEX_LEN;
 
             off = pn3->pn_offset - top;
             SET_JUMP_OFFSET(pc, off);
             pc += JUMP_OFFSET_LEN;
         }
     }
 
 out:
@@ -2906,17 +2841,18 @@ MaybeEmitVarDecl(JSContext *cx, Bytecode
 
     if (JOF_OPTYPE(pn->getOp()) == JOF_ATOM &&
         (!bce->inFunction() || (bce->flags & TCF_FUN_HEAVYWEIGHT)) &&
         !(pn->pn_dflags & PND_GVAR))
     {
         bce->switchToProlog();
         if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin.lineno))
             return false;
-        EMIT_INDEX_OP(prologOp, atomIndex);
+        if (!EmitIndexOp(cx, prologOp, atomIndex, bce))
+            return false;
         bce->switchToMain();
     }
 
     if (bce->inFunction() &&
         JOF_OPTYPE(pn->getOp()) == JOF_LOCAL &&
         pn->pn_cookie.slot() < bce->bindings.countVars() &&
         bce->shouldNoteClosedName(pn))
     {
@@ -3608,20 +3544,21 @@ EmitVariables(JSContext *cx, BytecodeEmi
             JS_ASSERT(op != JSOP_CALLEE);
             JS_ASSERT(!pn2->pn_cookie.isFree() || !pn->isOp(JSOP_NOP));
             if (!MaybeEmitVarDecl(cx, bce, pn->getOp(), pn2, &atomIndex))
                 return JS_FALSE;
 
             if (pn3) {
                 JS_ASSERT(emitOption != DefineVars);
                 JS_ASSERT_IF(emitOption == PushInitialValues, op == JSOP_SETLOCAL);
-                if (op == JSOP_SETNAME)
-                    EMIT_INDEX_OP(JSOP_BINDNAME, atomIndex);
-                else if (op == JSOP_SETGNAME)
-                    EMIT_INDEX_OP(JSOP_BINDGNAME, atomIndex);
+                if (op == JSOP_SETNAME || op == JSOP_SETGNAME) {
+                    JSOp bindOp = (op == JSOP_SETNAME) ? JSOP_BINDNAME : JSOP_BINDGNAME;
+                    if (!EmitIndex32(cx, bindOp, atomIndex, bce))
+                        return false;
+                }
                 if (pn->isOp(JSOP_DEFCONST) &&
                     !DefineCompileTimeConstant(cx, bce, pn2->pn_atom, pn3))
                 {
                     return JS_FALSE;
                 }
 
                 uintN oldflags = bce->flags;
                 bce->flags &= ~TCF_IN_FOR_INIT;
@@ -3652,17 +3589,18 @@ EmitVariables(JSContext *cx, BytecodeEmi
             return JS_FALSE;
         }
         if (op == JSOP_ARGUMENTS) {
             if (Emit1(cx, bce, op) < 0)
                 return JS_FALSE;
         } else if (!pn2->pn_cookie.isFree()) {
             EMIT_UINT16_IMM_OP(op, atomIndex);
         } else {
-            EMIT_INDEX_OP(op, atomIndex);
+            if (!EmitIndexOp(cx, op, atomIndex, bce))
+                return false;
         }
 
 #if JS_HAS_DESTRUCTURING
     emit_note_pop:
 #endif
         ptrdiff_t tmp = bce->offset();
         if (noteIndex >= 0) {
             if (!SetSrcNoteOffset(cx, bce, (uintN)noteIndex, 0, tmp-off))
@@ -3703,17 +3641,18 @@ EmitAssignment(JSContext *cx, BytecodeEm
             return false;
         if (!lhs->pn_cookie.isFree()) {
             atomIndex = lhs->pn_cookie.asInteger();
         } else {
             if (!bce->makeAtomIndex(lhs->pn_atom, &atomIndex))
                 return false;
             if (!lhs->isConst()) {
                 JSOp op = lhs->isOp(JSOP_SETGNAME) ? JSOP_BINDGNAME : JSOP_BINDNAME;
-                EMIT_INDEX_OP(op, atomIndex);
+                if (!EmitIndex32(cx, op, atomIndex, bce))
+                    return false;
                 offset++;
             }
         }
         break;
       case PNK_DOT:
         if (!EmitTree(cx, bce, lhs->expr()))
             return false;
         offset++;
@@ -3756,42 +3695,49 @@ EmitAssignment(JSContext *cx, BytecodeEm
     if (op != JSOP_NOP) {
         JS_ASSERT(rhs);
         switch (lhs->getKind()) {
           case PNK_NAME:
             if (lhs->isConst()) {
                 if (lhs->isOp(JSOP_CALLEE)) {
                     if (Emit1(cx, bce, JSOP_CALLEE) < 0)
                         return false;
+                } else if (lhs->isOp(JSOP_NAME)) {
+                    if (!EmitIndex32(cx, lhs->getOp(), atomIndex, bce))
+                        return false;
                 } else {
-                    EMIT_INDEX_OP(lhs->getOp(), atomIndex);
+                    JS_ASSERT(JOF_OPTYPE(lhs->getOp()) != JOF_ATOM);
+                    EMIT_UINT16_IMM_OP(lhs->getOp(), atomIndex);
                 }
             } else if (lhs->isOp(JSOP_SETNAME)) {
                 if (Emit1(cx, bce, JSOP_DUP) < 0)
                     return false;
-                EMIT_INDEX_OP(JSOP_GETXPROP, atomIndex);
+                if (!EmitIndex32(cx, JSOP_GETXPROP, atomIndex, bce))
+                    return false;
             } else if (lhs->isOp(JSOP_SETGNAME)) {
                 if (!BindGlobal(cx, bce, lhs, lhs->pn_atom))
                     return false;
-                EmitAtomOp(cx, lhs, JSOP_GETGNAME, bce);
+                if (!EmitAtomOp(cx, lhs, JSOP_GETGNAME, bce))
+                    return false;
             } else {
                 EMIT_UINT16_IMM_OP(lhs->isOp(JSOP_SETARG) ? JSOP_GETARG : JSOP_GETLOCAL, atomIndex);
             }
             break;
           case PNK_DOT:
             if (Emit1(cx, bce, JSOP_DUP) < 0)
                 return false;
             if (lhs->pn_atom == cx->runtime->atomState.protoAtom) {
-                if (!EmitIndexOp(cx, JSOP_QNAMEPART, atomIndex, bce))
+                if (!EmitIndex32(cx, JSOP_QNAMEPART, atomIndex, bce))
                     return false;
                 if (!EmitElemOpBase(cx, bce, JSOP_GETELEM))
                     return false;
             } else {
                 bool isLength = (lhs->pn_atom == cx->runtime->atomState.lengthAtom);
-                EMIT_INDEX_OP(isLength ? JSOP_LENGTH : JSOP_GETPROP, atomIndex);
+                if (!EmitIndex32(cx, isLength ? JSOP_LENGTH : JSOP_GETPROP, atomIndex, bce))
+                    return false;
             }
             break;
           case PNK_LB:
           case PNK_LP:
 #if JS_HAS_XML_SUPPORT
           case PNK_XMLUNARY:
 #endif
             if (Emit1(cx, bce, JSOP_DUP2) < 0)
@@ -3845,19 +3791,27 @@ EmitAssignment(JSContext *cx, BytecodeEm
         if (lhs->isConst()) {
             if (!rhs) {
                 ReportCompileErrorNumber(cx, bce->tokenStream(), lhs, JSREPORT_ERROR,
                                          JSMSG_BAD_FOR_LEFTSIDE);
                 return false;
             }
             break;
         }
-        /* FALL THROUGH */
+        if (lhs->isOp(JSOP_SETARG) || lhs->isOp(JSOP_SETLOCAL)) {
+            JS_ASSERT(atomIndex < UINT16_MAX);
+            EMIT_UINT16_IMM_OP(lhs->getOp(), atomIndex);
+        } else {
+            if (!EmitIndexOp(cx, lhs->getOp(), atomIndex, bce))
+                return false;
+        }
+        break;
       case PNK_DOT:
-        EMIT_INDEX_OP(lhs->getOp(), atomIndex);
+        if (!EmitIndexOp(cx, lhs->getOp(), atomIndex, bce))
+            return false;
         break;
       case PNK_LB:
       case PNK_LP:
         if (Emit1(cx, bce, JSOP_SETELEM) < 0)
             return false;
         break;
 #if JS_HAS_DESTRUCTURING
       case PNK_RB:
@@ -4557,17 +4511,18 @@ EmitXMLTag(JSContext *cx, BytecodeEmitte
 
     {
         jsatomid index;
         JSAtom *tagAtom = (pn->isKind(PNK_XMLETAGO))
                           ? cx->runtime->atomState.etagoAtom
                           : cx->runtime->atomState.stagoAtom;
         if (!bce->makeAtomIndex(tagAtom, &index))
             return false;
-        EMIT_INDEX_OP(JSOP_STRING, index);
+        if (!EmitIndex32(cx, JSOP_STRING, index, bce))
+            return false;
     }
 
     JS_ASSERT(pn->pn_count != 0);
     ParseNode *pn2 = pn->pn_head;
     if (pn2->isKind(PNK_XMLCURLYEXPR) && Emit1(cx, bce, JSOP_STARTXMLEXPR) < 0)
         return false;
     if (!EmitTree(cx, bce, pn2))
         return false;
@@ -4589,17 +4544,18 @@ EmitXMLTag(JSContext *cx, BytecodeEmitte
     }
 
     {
         jsatomid index;
         JSAtom *tmp = (pn->isKind(PNK_XMLPTAGC)) ? cx->runtime->atomState.ptagcAtom
                                                  : cx->runtime->atomState.tagcAtom;
         if (!bce->makeAtomIndex(tmp, &index))
             return false;
-        EMIT_INDEX_OP(JSOP_STRING, index);
+        if (!EmitIndex32(cx, JSOP_STRING, index, bce))
+            return false;
     }
     if (Emit1(cx, bce, JSOP_ADD) < 0)
         return false;
 
     if ((pn->pn_xflags & PNX_XMLROOT) && Emit1(cx, bce, pn->getOp()) < 0)
         return false;
 
     return true;
@@ -4608,17 +4564,17 @@ EmitXMLTag(JSContext *cx, BytecodeEmitte
 static bool
 EmitXMLProcessingInstruction(JSContext *cx, BytecodeEmitter *bce, XMLProcessingInstruction &pi)
 {
     JS_ASSERT(!bce->inStrictMode());
 
     jsatomid index;
     if (!bce->makeAtomIndex(pi.data(), &index))
         return false;
-    if (!EmitIndexOp(cx, JSOP_QNAMEPART, index, bce))
+    if (!EmitIndex32(cx, JSOP_QNAMEPART, index, bce))
         return false;
     if (!EmitAtomOp(cx, pi.target(), JSOP_XMLPI, bce))
         return false;
     return true;
 }
 #endif
 
 static bool
@@ -6037,37 +5993,36 @@ EmitObject(JSContext *cx, BytecodeEmitte
                                           JSPROP_ENUMERATE, 0, 0))
                 {
                     return false;
                 }
                 if (obj->inDictionaryMode())
                     obj = NULL;
             }
 
-            EMIT_INDEX_OP(op, index);
+            if (!EmitIndex32(cx, op, index, bce))
+                return false;
         }
     }
 
     if (Emit1(cx, bce, JSOP_ENDINIT) < 0)
         return false;
 
     if (obj) {
         /*
-         * The object survived and has a predictable shape.  Update the original bytecode,
-         * as long as we can do so without using a big index prefix/suffix.
+         * The object survived and has a predictable shape: update the original
+         * bytecode.
          */
         ObjectBox *objbox = bce->parser->newObjectBox(obj);
         if (!objbox)
             return false;
         uintN index = bce->objectList.index(objbox);
-        if (FitsWithoutBigIndex(index)) {
-            MOZ_STATIC_ASSERT(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
-                              "newinit and newobject must have equal length to edit in-place");
-            EMIT_UINT32_IN_PLACE(offset, JSOP_NEWOBJECT, uint32_t(index));
-        }
+        MOZ_STATIC_ASSERT(JSOP_NEWINIT_LENGTH == JSOP_NEWOBJECT_LENGTH,
+                          "newinit and newobject must have equal length to edit in-place");
+        EMIT_UINT32_IN_PLACE(offset, JSOP_NEWOBJECT, uint32_t(index));
     }
 
     return true;
 }
 
 static bool
 EmitArray(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
@@ -6639,17 +6594,18 @@ frontend::EmitTree(JSContext *cx, Byteco
 
         if (pn->pn_xflags & PNX_XMLROOT) {
             if (pn->pn_count == 0) {
                 JS_ASSERT(pn->isKind(PNK_XMLLIST));
                 JSAtom *atom = cx->runtime->atomState.emptyAtom;
                 jsatomid index;
                 if (!bce->makeAtomIndex(atom, &index))
                     return JS_FALSE;
-                EMIT_INDEX_OP(JSOP_STRING, index);
+                if (!EmitIndex32(cx, JSOP_STRING, index, bce))
+                    return false;
             }
             if (Emit1(cx, bce, pn->getOp()) < 0)
                 return JS_FALSE;
         }
 #ifdef DEBUG
         else
             JS_ASSERT(pn->pn_count != 0);
 #endif
--- a/js/src/frontend/FoldConstants.cpp
+++ b/js/src/frontend/FoldConstants.cpp
@@ -104,17 +104,17 @@ ContainsVarOrConst(ParseNode *pn)
  */
 static JSBool
 FoldType(JSContext *cx, ParseNode *pn, ParseNodeKind kind)
 {
     if (!pn->isKind(kind)) {
         switch (kind) {
           case PNK_NUMBER:
             if (pn->isKind(PNK_STRING)) {
-                jsdouble d;
+                double d;
                 if (!ToNumber(cx, StringValue(pn->pn_atom), &d))
                     return JS_FALSE;
                 pn->pn_dval = d;
                 pn->setKind(PNK_NUMBER);
                 pn->setOp(JSOP_DOUBLE);
             }
             break;
 
@@ -141,17 +141,17 @@ FoldType(JSContext *cx, ParseNode *pn, P
  * Fold two numeric constants.  Beware that pn1 and pn2 are recycled, unless
  * one of them aliases pn, so you can't safely fetch pn2->pn_next, e.g., after
  * a successful call to this function.
  */
 static JSBool
 FoldBinaryNumeric(JSContext *cx, JSOp op, ParseNode *pn1, ParseNode *pn2,
                   ParseNode *pn, TreeContext *tc)
 {
-    jsdouble d, d2;
+    double d, d2;
     int32_t i, j;
 
     JS_ASSERT(pn1->isKind(PNK_NUMBER) && pn2->isKind(PNK_NUMBER));
     d = pn1->pn_dval;
     d2 = pn2->pn_dval;
     switch (op) {
       case JSOP_LSH:
       case JSOP_RSH:
@@ -817,17 +817,17 @@ js::FoldConstants(JSContext *cx, ParseNo
 
       case PNK_TYPEOF:
       case PNK_VOID:
       case PNK_NOT:
       case PNK_BITNOT:
       case PNK_POS:
       case PNK_NEG:
         if (pn1->isKind(PNK_NUMBER)) {
-            jsdouble d;
+            double d;
 
             /* Operate on one numeric constant. */
             d = pn1->pn_dval;
             switch (pn->getOp()) {
               case JSOP_BITNOT:
                 d = ~js_DoubleToECMAInt32(d);
                 break;
 
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -614,17 +614,17 @@ struct ParseNode {
             uint32_t    dflags:12,      /* definition/use flags, see below */
                         blockid:20;     /* block number, for subset dominance
                                            computation */
         } name;
         struct {                        /* lexical dependencies + sub-tree */
             AtomDefnMapPtr   defnMap;
             ParseNode        *tree;     /* sub-tree containing name uses */
         } nameset;
-        jsdouble        dval;           /* aligned numeric literal value */
+        double        dval;             /* aligned numeric literal value */
         class {
             friend class LoopControlStatement;
             PropertyName     *label;    /* target of break/continue statement */
         } loopControl;
         class {                         /* E4X <?target data?> XML PI */
             friend class XMLProcessingInstruction;
             PropertyName     *target;   /* non-empty */
             JSAtom           *data;     /* may be empty, never null */
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -1727,17 +1727,17 @@ TokenStream::getTokenInternal()
             goto error;
         }
 
         /*
          * Unlike identifiers and strings, numbers cannot contain escaped
          * chars, so we don't need to use tokenbuf.  Instead we can just
          * convert the jschars in userbuf directly to the numeric value.
          */
-        jsdouble dval;
+        double dval;
         const jschar *dummy;
         if (!hasFracOrExp) {
             if (!GetPrefixInteger(cx, numStart, userbuf.addressOfNextRawChar(), 10, &dummy, &dval))
                 goto error;
         } else {
             if (!js_strtod(cx, numStart, userbuf.addressOfNextRawChar(), &dummy, &dval))
                 goto error;
         }
@@ -1818,17 +1818,17 @@ TokenStream::getTokenInternal()
         }
         ungetCharIgnoreEOL(c);
 
         if (c != EOF && IsIdentifierStart(c)) {
             ReportCompileErrorNumber(cx, this, NULL, JSREPORT_ERROR, JSMSG_IDSTART_AFTER_NUMBER);
             goto error;
         }
 
-        jsdouble dval;
+        double dval;
         const jschar *dummy;
         if (!GetPrefixInteger(cx, numStart, userbuf.addressOfNextRawChar(), radix, &dummy, &dval))
             goto error;
         tp->setNumber(dval);
         tt = TOK_NUMBER;
         goto out;
     }
 
--- a/js/src/frontend/TokenStream.h
+++ b/js/src/frontend/TokenStream.h
@@ -317,17 +317,17 @@ struct Token {
         } s;
 
       private:
         friend struct Token;
         struct {                        /* pair for <?target data?> XML PI */
             PropertyName *target;       /* non-empty */
             JSAtom       *data;         /* maybe empty, never null */
         } xmlpi;
-        jsdouble        number;         /* floating point number */
+        double          number;         /* floating point number */
         RegExpFlag      reflags;        /* regexp flags, use tokenbuf to access
                                            regexp chars */
     } u;
 
     /* Mutators */
 
     /*
      * FIXME: Init type early enough such that all mutators can assert
@@ -354,17 +354,17 @@ struct Token {
         u.xmlpi.data = data;
     }
 
     void setRegExpFlags(js::RegExpFlag flags) {
         JS_ASSERT((flags & AllFlags) == flags);
         u.reflags = flags;
     }
 
-    void setNumber(jsdouble n) {
+    void setNumber(double n) {
         u.number = n;
     }
 
     /* Type-safe accessors */
 
     PropertyName *name() const {
         JS_ASSERT(type == TOK_NAME);
         return u.s.n.name->asPropertyName(); /* poor-man's type verification */
@@ -391,17 +391,17 @@ struct Token {
     }
 
     js::RegExpFlag regExpFlags() const {
         JS_ASSERT(type == TOK_REGEXP);
         JS_ASSERT((u.reflags & AllFlags) == u.reflags);
         return u.reflags;
     }
 
-    jsdouble number() const {
+    double number() const {
         JS_ASSERT(type == TOK_NUMBER);
         return u.number;
     }
 };
 
 #define t_op            u.s.op
 
 enum TokenStreamFlags
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -143,16 +143,18 @@
  * newly allocated objects do not need a barrier as long as the GC is not
  * allowed to run in between the allocation and the write. In these cases, we
  * use the "obj->field.init(value)" method instead of "obj->field = value".
  * We use the init naming idiom in many places to signify that a field is being
  * assigned for the first time, and that no GCs have taken place between the
  * object allocation and the assignment.
  */
 
+struct JSXML;
+
 namespace js {
 
 /*
  * Ideally, we would like to make the argument to functions like MarkShape be a
  * HeapPtr<const js::Shape>. That would ensure that we don't forget to
  * barrier any fields that we mark through. However, that would prohibit us from
  * passing in a derived class like HeapPtr<js::EmptyShape>.
  *
@@ -264,16 +266,20 @@ BarrieredSetPair(JSCompartment *comp,
         v2.pre();
     }
     v1.unsafeSet(val1);
     v2.unsafeSet(val2);
     v1.post();
     v2.post();
 }
 
+struct Shape;
+class BaseShape;
+namespace types { struct TypeObject; }
+
 typedef HeapPtr<JSObject> HeapPtrObject;
 typedef HeapPtr<JSFunction> HeapPtrFunction;
 typedef HeapPtr<JSString> HeapPtrString;
 typedef HeapPtr<JSScript> HeapPtrScript;
 typedef HeapPtr<Shape> HeapPtrShape;
 typedef HeapPtr<BaseShape> HeapPtrBaseShape;
 typedef HeapPtr<types::TypeObject> HeapPtrTypeObject;
 typedef HeapPtr<JSXML> HeapPtrXML;
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap-newvar.js
@@ -1,10 +1,10 @@
 // |jit-test| mjitalways;debug
 setDebug(true);
 
 function nop(){}
 function caller(code, obj) {
   eval(code); // Make the compiler give up on binding analysis.
   return x;
 }
-trap(caller, 13, "var x = 'success'; nop()");
+trap(caller, 15, "var x = 'success'; nop()");
 assertEq(caller("var y = 'ignominy'", this), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-trap.js
@@ -2,10 +2,10 @@
 setDebug(true);
 
 function nop(){}
 function caller(obj) {
   assertJit();
   var x = "failure";
   return x;
 }
-trap(caller, 15, "x = 'success'; nop()");
+trap(caller, 19, "x = 'success'; nop()");
 assertEq(caller(this), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/simple-trap-2.js
@@ -1,11 +1,11 @@
 // |jit-test| debug
 setDebug(true);
 var x = "notset";
 function main() { x = "failure"; }
 function success() { x = "success"; }
 
 /* The JSOP_STOP in main. */
-trap(main, 10, "success()");
+trap(main, 16, "success()");
 main();
 
 assertEq(x, "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-force-return-1.js
@@ -1,8 +1,8 @@
 // |jit-test| debug
 setDebug(true);
 function main() {
   return "failure";
 }
 /* JSOP_RETURN in main. */
-trap(main, 3, "'success'");
+trap(main, 5, "'success'");
 assertEq(main(), "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-from-add-inline.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-from-add-inline.js
@@ -1,13 +1,13 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function main() {
   /* The JSOP_STOP in main. */
-  a = { valueOf: function () { trap(main, 39, "success()"); } };
+  a = { valueOf: function () { trap(main, 55, "success()"); } };
   a + "";
   x = "failure";
 }
 function success() { x = "success"; }
 
 main();
 assertEq(x, "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-from-add-ool.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-from-add-ool.js
@@ -1,14 +1,14 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function main() {
   /* The JSOP_STOP in main. */
-  a = { valueOf: function () { trap(main, 60, "success()"); } };
+  a = { valueOf: function () { trap(main, 84, "success()"); } };
   b = "";
   eval();
   a + b;
   x = "failure";
 }
 function success() { x = "success"; }
 
 main();
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-parent-from-trap.js
@@ -1,16 +1,16 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 
 function child() {
   x = "failure1";
   /* JSOP_STOP in parent. */
-  trap(parent, 10, "success()");
+  trap(parent, 16, "success()");
 }
 
 function parent() {
   x = "failure2";
 }
 /* First op in parent. */
 trap(parent, 0, "child()");
 
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-parent.js
@@ -1,14 +1,14 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function child() {
   /* JSOP_STOP in parent. */
-  trap(parent, 17, "success()");
+  trap(parent, 26, "success()");
 }
 function parent() {
   child();
   x = "failure";
 }
 function success() {
   x = "success";
 }
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-as-parent.js
@@ -1,16 +1,16 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 
 function myparent(nested) {
   if (nested) {
     /* noop call in myparent */
-    trap(myparent, 48, "success()");
+    trap(myparent, 68, "success()");
   } else {
     myparent(true);
     x = "failure";
     noop();
   }
 }
 function noop() { }
 function success() { x = "success"; }
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self-from-trap.js
@@ -2,23 +2,23 @@
 setDebug(true);
 x = "notset";
 
 function doNothing() { }
 
 function myparent(nested) {
   if (nested) {
     /* JSOP_CALL to doNothing in myparent with nested = true. */
-    trap(myparent, 28, "success()");
+    trap(myparent, 36, "success()");
     doNothing();
   } else {
     doNothing();
   }
 }
 /* JSOP_CALL to doNothing in myparent with nested = false. */
-trap(myparent, 41, "myparent(true)");
+trap(myparent, 51, "myparent(true)");
 
 function success() {
   x = "success";
 }
 
 myparent(false);
 assertEq(x, "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/trap-self.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/trap-self.js
@@ -1,12 +1,12 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function main() {
   /* The JSOP_STOP in main. */
-  trap(main, 25, "success()");
+  trap(main, 38, "success()");
   x = "failure";
 }
 function success() { x = "success"; }
 
 main();
 assertEq(x, "success");
--- a/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/untrap-own-trapsite.js
@@ -1,16 +1,16 @@
 // |jit-test| debug
 setDebug(true);
 x = "notset";
 function child() {
   /* JSOP_STOP in parent */
-  untrap(parent, 10);
+  untrap(parent, 16);
   x = "success";
 }
 function parent() {
   x = "failure";
 }
 /* JSOP_STOP in parent */
-trap(parent, 10, "child()");
+trap(parent, 16, "child()");
 
 parent();
 assertEq(x, "success");
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -118,17 +118,17 @@ ScriptAnalysis::checkAliasedName(JSConte
      */
 
     JSAtom *atom;
     if (JSOp(*pc) == JSOP_DEFFUN) {
         JSFunction *fun = script->getFunction(GET_UINT32_INDEX(pc));
         atom = fun->atom;
     } else {
         JS_ASSERT(JOF_TYPE(js_CodeSpec[*pc].format) == JOF_ATOM);
-        atom = script->getAtom(js_GetIndexFromBytecode(script, pc, 0));
+        atom = script->getAtom(GET_UINT32_INDEX(pc));
     }
 
     uintN index;
     BindingKind kind = script->bindings.lookup(cx, atom, &index);
 
     if (kind == ARGUMENT)
         escapedSlots[ArgSlot(index)] = true;
     else if (kind == VARIABLE)
@@ -417,17 +417,17 @@ ScriptAnalysis::analyzeBytecode(JSContex
             pc2 += UINT16_LEN;
 
             if (!addJump(cx, defaultOffset, &nextOffset, &forwardJump, stackDepth))
                 return;
             getCode(defaultOffset).switchTarget = true;
             getCode(defaultOffset).safePoint = true;
 
             while (npairs) {
-                pc2 += INDEX_LEN;
+                pc2 += UINT32_INDEX_LEN;
                 unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
                 if (!addJump(cx, targetOffset, &nextOffset, &forwardJump, stackDepth))
                     return;
                 getCode(targetOffset).switchTarget = true;
                 getCode(targetOffset).safePoint = true;
                 pc2 += JUMP_OFFSET_LEN;
                 npairs--;
             }
@@ -1545,17 +1545,17 @@ ScriptAnalysis::analyzeSSA(JSContext *cx
             jsbytecode *pc2 = pc + JUMP_OFFSET_LEN;
             unsigned npairs = GET_UINT16(pc2);
             pc2 += UINT16_LEN;
 
             Vector<SlotValue> *pending = NULL;
             uint32_t pendingOffset = 0;
 
             while (npairs) {
-                pc2 += INDEX_LEN;
+                pc2 += UINT32_INDEX_LEN;
                 unsigned targetOffset = offset + GET_JUMP_OFFSET(pc2);
                 checkBranchTarget(cx, targetOffset, branchTargets, values, stackDepth,
                                   &pending, &pendingOffset);
                 pc2 += JUMP_OFFSET_LEN;
                 npairs--;
             }
 
             checkBranchTarget(cx, defaultOffset, branchTargets, values, stackDepth,
--- a/js/src/jsapi-tests/testParseJSON.cpp
+++ b/js/src/jsapi-tests/testParseJSON.cpp
@@ -46,17 +46,17 @@ BEGIN_TEST(testParseJSON_success)
     CHECK(TryParse(cx, "false", JSVAL_FALSE));
     CHECK(TryParse(cx, "null", JSVAL_NULL));
     CHECK(TryParse(cx, "0", INT_TO_JSVAL(0)));
     CHECK(TryParse(cx, "1", INT_TO_JSVAL(1)));
     CHECK(TryParse(cx, "-1", INT_TO_JSVAL(-1)));
     CHECK(TryParse(cx, "1", DOUBLE_TO_JSVAL(1)));
     CHECK(TryParse(cx, "1.75", DOUBLE_TO_JSVAL(1.75)));
     CHECK(TryParse(cx, "9e9", DOUBLE_TO_JSVAL(9e9)));
-    CHECK(TryParse(cx, "9e99999", DOUBLE_TO_JSVAL(std::numeric_limits<jsdouble>::infinity())));
+    CHECK(TryParse(cx, "9e99999", DOUBLE_TO_JSVAL(std::numeric_limits<double>::infinity())));
 
     JSFlatString *str;
 
     const jschar emptystr[] = { '\0' };
     str = js_NewStringCopyN(cx, emptystr, 0);
     CHECK(str);
     CHECK(TryParse(cx, "\"\"", STRING_TO_JSVAL(str)));
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -280,17 +280,17 @@ JS_ConvertArguments(JSContext *cx, uintN
 
 JS_PUBLIC_API(JSBool)
 JS_ConvertArgumentsVA(JSContext *cx, uintN argc, jsval *argv, const char *format, va_list ap)
 {
     jsval *sp;
     JSBool required;
     char c;
     JSFunction *fun;
-    jsdouble d;
+    double d;
     JSString *str;
     JSObject *obj;
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, JSValueArray(argv - 2, argc + 2));
     sp = argv;
     required = JS_TRUE;
@@ -333,23 +333,23 @@ JS_ConvertArgumentsVA(JSContext *cx, uin
             if (!JS_ValueToECMAUint32(cx, *sp, va_arg(ap, uint32_t *)))
                 return JS_FALSE;
             break;
           case 'j':
             if (!JS_ValueToInt32(cx, *sp, va_arg(ap, int32_t *)))
                 return JS_FALSE;
             break;
           case 'd':
-            if (!JS_ValueToNumber(cx, *sp, va_arg(ap, jsdouble *)))
+            if (!JS_ValueToNumber(cx, *sp, va_arg(ap, double *)))
                 return JS_FALSE;
             break;
           case 'I':
             if (!JS_ValueToNumber(cx, *sp, &d))
                 return JS_FALSE;
-            *va_arg(ap, jsdouble *) = js_DoubleToInteger(d);
+            *va_arg(ap, double *) = js_DoubleToInteger(d);
             break;
           case 'S':
           case 'W':
             str = ToString(cx, *sp);
             if (!str)
                 return JS_FALSE;
             *sp = STRING_TO_JSVAL(str);
             if (c == 'W') {
@@ -440,17 +440,17 @@ JS_RemoveArgumentFormatter(JSContext *cx
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ConvertValue(JSContext *cx, jsval v, JSType type, jsval *vp)
 {
     JSBool ok;
     JSObject *obj;
     JSString *str;
-    jsdouble d;
+    double d;
 
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, v);
     switch (type) {
       case JSTYPE_VOID:
         *vp = JSVAL_VOID;
         ok = JS_TRUE;
@@ -531,40 +531,40 @@ JS_ValueToSource(JSContext *cx, jsval v)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, v);
     return js_ValueToSource(cx, v);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp)
+JS_ValueToNumber(JSContext *cx, jsval v, double *dp)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, v);
 
     AutoValueRooter tvr(cx, v);
     return ToNumber(cx, tvr.value(), dp);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_DoubleIsInt32(jsdouble d, jsint *ip)
+JS_DoubleIsInt32(double d, jsint *ip)
 {
     return JSDOUBLE_IS_INT32(d, (int32_t *)ip);
 }
 
 JS_PUBLIC_API(int32_t)
-JS_DoubleToInt32(jsdouble d)
+JS_DoubleToInt32(double d)
 {
     return js_DoubleToECMAInt32(d);
 }
 
 JS_PUBLIC_API(uint32_t)
-JS_DoubleToUint32(jsdouble d)
+JS_DoubleToUint32(double d)
 {
     return js_DoubleToECMAUint32(d);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ValueToECMAInt32(JSContext *cx, jsval v, int32_t *ip)
 {
     AssertNoGC(cx);
@@ -820,16 +820,20 @@ JSRuntime::init(uint32_t maxbytes)
 #endif
 
     if (!js_InitGC(this, maxbytes))
         return false;
 
     if (!gcMarker.init())
         return false;
 
+    const char *size = getenv("JSGC_MARK_STACK_LIMIT");
+    if (size)
+        SetMarkStackLimit(this, atoi(size));
+
     if (!(atomsCompartment = this->new_<JSCompartment>(this)) ||
         !atomsCompartment->init(NULL) ||
         !compartments.append(atomsCompartment)) {
         Foreground::delete_(atomsCompartment);
         return false;
     }
 
     atomsCompartment->isSystemCompartment = true;
@@ -2239,17 +2243,17 @@ JS_strdup(JSContext *cx, const char *s)
     size_t n = strlen(s) + 1;
     void *p = cx->malloc_(n);
     if (!p)
         return NULL;
     return (char *)js_memcpy(p, s, n);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval)
+JS_NewNumberValue(JSContext *cx, double d, jsval *rval)
 {
     AssertNoGC(cx);
     d = JS_CANONICALIZE_NAN(d);
     rval->setNumber(d);
     return JS_TRUE;
 }
 
 #undef JS_AddRoot
@@ -2902,16 +2906,19 @@ JS_SetGCParameter(JSRuntime *rt, JSGCPar
         break;
       }
       case JSGC_MAX_MALLOC_BYTES:
         rt->setGCMaxMallocBytes(value);
         break;
       case JSGC_SLICE_TIME_BUDGET:
         rt->gcSliceBudget = SliceBudget::TimeBudget(value);
         break;
+      case JSGC_MARK_STACK_LIMIT:
+        js::SetMarkStackLimit(rt, value);
+        break;
       default:
         JS_ASSERT(key == JSGC_MODE);
         rt->gcMode = JSGCMode(value);
         JS_ASSERT(rt->gcMode == JSGC_MODE_GLOBAL ||
                   rt->gcMode == JSGC_MODE_COMPARTMENT ||
                   rt->gcMode == JSGC_MODE_INCREMENTAL);
         return;
     }
@@ -2930,16 +2937,18 @@ JS_GetGCParameter(JSRuntime *rt, JSGCPar
       case JSGC_MODE:
         return uint32_t(rt->gcMode);
       case JSGC_UNUSED_CHUNKS:
         return uint32_t(rt->gcChunkPool.getEmptyCount());
       case JSGC_TOTAL_CHUNKS:
         return uint32_t(rt->gcChunkSet.count() + rt->gcChunkPool.getEmptyCount());
       case JSGC_SLICE_TIME_BUDGET:
         return uint32_t(rt->gcSliceBudget > 0 ? rt->gcSliceBudget / PRMJ_USEC_PER_MSEC : 0);
+      case JSGC_MARK_STACK_LIMIT:
+        return rt->gcMarker.sizeLimit();
       default:
         JS_ASSERT(key == JSGC_NUMBER);
         return uint32_t(rt->gcNumber);
     }
 }
 
 JS_PUBLIC_API(void)
 JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value)
@@ -6271,17 +6280,17 @@ JS_PUBLIC_API(JSObject *)
 JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     return js_NewDateObject(cx, year, mon, mday, hour, min, sec);
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_NewDateObjectMsec(JSContext *cx, jsdouble msec)
+JS_NewDateObjectMsec(JSContext *cx, double msec)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     return js_NewDateObjectMsec(cx, msec);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_ObjectIsDate(JSContext *cx, JSObject *obj)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1657,27 +1657,27 @@ INT_TO_JSVAL(int32_t i)
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_DOUBLE(jsval v)
 {
     return JSVAL_IS_DOUBLE_IMPL(JSVAL_TO_IMPL(v));
 }
 
-static JS_ALWAYS_INLINE jsdouble
+static JS_ALWAYS_INLINE double
 JSVAL_TO_DOUBLE(jsval v)
 {
     jsval_layout l;
     JS_ASSERT(JSVAL_IS_DOUBLE(v));
     l = JSVAL_TO_IMPL(v);
     return l.asDouble;
 }
 
 static JS_ALWAYS_INLINE jsval
-DOUBLE_TO_JSVAL(jsdouble d)
+DOUBLE_TO_JSVAL(double d)
 {
     /* This is a manually inlined version of:
      *    d = JS_CANONICALIZE_NAN(d);
      *    return IMPL_TO_JSVAL(DOUBLE_TO_JSVAL_IMPL(d));
      * because GCC from XCode 3.1.4 miscompiles the above code. */
     jsval_layout l;
     if (JS_UNLIKELY(d != d)) {
         l.asBits = 0x7FF8000000000000LL;
@@ -1687,17 +1687,17 @@ DOUBLE_TO_JSVAL(jsdouble d)
     return IMPL_TO_JSVAL(l);
 }
 
 static JS_ALWAYS_INLINE jsval
 UINT_TO_JSVAL(uint32_t i)
 {
     if (i <= JSVAL_INT_MAX)
         return INT_TO_JSVAL((int32_t)i);
-    return DOUBLE_TO_JSVAL((jsdouble)i);
+    return DOUBLE_TO_JSVAL((double)i);
 }
 
 static JS_ALWAYS_INLINE JSBool
 JSVAL_IS_NUMBER(jsval v)
 {
     return JSVAL_IS_NUMBER_IMPL(JSVAL_TO_IMPL(v));
 }
 
@@ -2126,18 +2126,18 @@ JS_GetEmptyString(JSRuntime *rt);
  * Format is a string of the following characters (spaces are insignificant),
  * specifying the tabulated type conversions:
  *
  *   b      JSBool          Boolean
  *   c      uint16_t/jschar ECMA uint16_t, Unicode char
  *   i      int32_t         ECMA int32_t
  *   u      uint32_t        ECMA uint32_t
  *   j      int32_t         Rounded int32_t (coordinate)
- *   d      jsdouble        IEEE double
- *   I      jsdouble        Integral IEEE double
+ *   d      double          IEEE double
+ *   I      double          Integral IEEE double
  *   S      JSString *      Unicode string, accessed by a JSString pointer
  *   W      jschar *        Unicode character vector, 0-terminated (W for wide)
  *   o      JSObject *      Object reference
  *   f      JSFunction *    Function private
  *   v      jsval           Argument value (no conversion)
  *   *      N/A             Skip this argument (no vararg)
  *   /      N/A             End of required arguments
  *
@@ -2228,26 +2228,26 @@ JS_ValueToConstructor(JSContext *cx, jsv
 
 extern JS_PUBLIC_API(JSString *)
 JS_ValueToString(JSContext *cx, jsval v);
 
 extern JS_PUBLIC_API(JSString *)
 JS_ValueToSource(JSContext *cx, jsval v);
 
 extern JS_PUBLIC_API(JSBool)
-JS_ValueToNumber(JSContext *cx, jsval v, jsdouble *dp);
+JS_ValueToNumber(JSContext *cx, jsval v, double *dp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_DoubleIsInt32(jsdouble d, jsint *ip);
+JS_DoubleIsInt32(double d, jsint *ip);
 
 extern JS_PUBLIC_API(int32_t)
-JS_DoubleToInt32(jsdouble d);
+JS_DoubleToInt32(double d);
 
 extern JS_PUBLIC_API(uint32_t)
-JS_DoubleToUint32(jsdouble d);
+JS_DoubleToUint32(double d);
 
 /*
  * Convert a value to a number, then to an int32_t, according to the ECMA rules
  * for ToInt32.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_ValueToECMAInt32(JSContext *cx, jsval v, int32_t *ip);
 
@@ -2889,17 +2889,17 @@ JS_free(JSContext *cx, void *p);
 
 extern JS_PUBLIC_API(void)
 JS_updateMallocCounter(JSContext *cx, size_t nbytes);
 
 extern JS_PUBLIC_API(char *)
 JS_strdup(JSContext *cx, const char *s);
 
 extern JS_PUBLIC_API(JSBool)
-JS_NewNumberValue(JSContext *cx, jsdouble d, jsval *rval);
+JS_NewNumberValue(JSContext *cx, double d, jsval *rval);
 
 /*
  * A GC root is a pointer to a jsval, JSObject * or JSString * that itself
  * points into the GC heap. JS_AddValueRoot takes a pointer to a jsval and
  * JS_AddGCThingRoot takes a pointer to a JSObject * or JString *.
  *
  * Note that, since JS_Add*Root stores the address of a variable (of type
  * jsval, JSString *, or JSObject *), that variable must live until
@@ -3303,17 +3303,20 @@ typedef enum JSGCParamKey {
 
     /* Number of cached empty GC chunks. */
     JSGC_UNUSED_CHUNKS = 7,
 
     /* Total number of allocated GC chunks. */
     JSGC_TOTAL_CHUNKS = 8,
 
     /* Max milliseconds to spend in an incremental GC slice. */
-    JSGC_SLICE_TIME_BUDGET = 9
+    JSGC_SLICE_TIME_BUDGET = 9,
+
+    /* Maximum size the GC mark stack can grow to. */
+    JSGC_MARK_STACK_LIMIT = 10
 } JSGCParamKey;
 
 typedef enum JSGCMode {
     /* Perform only global GCs. */
     JSGC_MODE_GLOBAL = 0,
 
     /* Perform per-compartment GCs until too much garbage has accumulated. */
     JSGC_MODE_COMPARTMENT = 1,
@@ -3588,17 +3591,17 @@ JS_ResolveStub(JSContext *cx, JSObject *
 
 extern JS_PUBLIC_API(JSBool)
 JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
 
 extern JS_PUBLIC_API(void)
 JS_FinalizeStub(JSContext *cx, JSObject *obj);
 
 struct JSConstDoubleSpec {
-    jsdouble        dval;
+    double          dval;
     const char      *name;
     uint8_t         flags;
     uint8_t         spare[3];
 };
 
 /*
  * To define an array element rather than a named property member, cast the
  * element's index to (const char *) and initialize name with it, and set the
@@ -5164,17 +5167,17 @@ JS_SetErrorReporter(JSContext *cx, JSErr
 /*
  * Dates.
  */
 
 extern JS_PUBLIC_API(JSObject *)
 JS_NewDateObject(JSContext *cx, int year, int mon, int mday, int hour, int min, int sec);
 
 extern JS_PUBLIC_API(JSObject *)
-JS_NewDateObjectMsec(JSContext *cx, jsdouble msec);
+JS_NewDateObjectMsec(JSContext *cx, double msec);
 
 /*
  * Infallible predicate to test whether obj is a date object.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_ObjectIsDate(JSContext *cx, JSObject *obj);
 
 /************************************************************************/
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -300,23 +300,23 @@ JSObject::willBeSparseDenseArray(uintN r
     for (uintN i = 0; i < len; i++) {
         if (!elems[i].isMagic(JS_ARRAY_HOLE) && !--minimalDenseCount)
             return false;
     }
     return true;
 }
 
 static bool
-ReallyBigIndexToId(JSContext* cx, jsdouble index, jsid* idp)
+ReallyBigIndexToId(JSContext* cx, double index, jsid* idp)
 {
     return js_ValueToStringId(cx, DoubleValue(index), idp);
 }
 
 static bool
-IndexToId(JSContext* cx, JSObject* obj, jsdouble index, JSBool* hole, jsid* idp,
+IndexToId(JSContext* cx, JSObject* obj, double index, JSBool* hole, jsid* idp,
           JSBool createAtom = JS_FALSE)
 {
     if (index <= JSID_INT_MAX) {
         *idp = INT_TO_JSID(int(index));
         return JS_TRUE;
     }
 
     if (index <= jsuint(-1)) {
@@ -358,17 +358,17 @@ JSObject::arrayGetOwnDataElement(JSConte
 
 /*
  * If the property at the given index exists, get its value into location
  * pointed by vp and set *hole to false. Otherwise set *hole to true and *vp
  * to JSVAL_VOID. This function assumes that the location pointed by vp is
  * properly rooted and can be used as GC-protected storage for temporaries.
  */
 static inline JSBool
-DoGetElement(JSContext *cx, JSObject *obj, jsdouble index, JSBool *hole, Value *vp)
+DoGetElement(JSContext *cx, JSObject *obj, double index, JSBool *hole, Value *vp)
 {
     AutoIdRooter idr(cx);
 
     *hole = JS_FALSE;
     if (!IndexToId(cx, obj, index, hole, idr.addr()))
         return JS_FALSE;
     if (*hole) {
         vp->setUndefined();
@@ -463,17 +463,17 @@ GetElements(JSContext *cx, JSObject *aob
 }
 
 }
 
 /*
  * Set the value of the property at the given index to v assuming v is rooted.
  */
 static JSBool
-SetArrayElement(JSContext *cx, JSObject *obj, jsdouble index, const Value &v)
+SetArrayElement(JSContext *cx, JSObject *obj, double index, const Value &v)
 {
     JS_ASSERT(index >= 0);
 
     if (obj->isDenseArray()) {
         /* Predicted/prefetched code should favor the remains-dense case. */
         JSObject::EnsureDenseResult result = JSObject::ED_SPARSE;
         do {
             if (index > jsuint(-1))
@@ -514,17 +514,17 @@ SetArrayElement(JSContext *cx, JSObject 
  *
  * - Return 0 if the deletion fails because the property is not
  *   configurable (that is, [[Delete]] would return false). Note that if
  *   |strict| is true we will throw, not return zero.
  *
  * - Return -1 if an exception occurs (that is, [[Delete]] would throw).
  */
 static int
-DeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index, bool strict)
+DeleteArrayElement(JSContext *cx, JSObject *obj, double index, bool strict)
 {
     JS_ASSERT(index >= 0);
     JS_ASSERT(floor(index) == index);
 
     if (obj->isDenseArray()) {
         if (index <= UINT32_MAX) {
             uint32_t idx = uint32_t(index);
             if (idx < obj->getDenseArrayInitializedLength()) {
@@ -549,28 +549,28 @@ DeleteArrayElement(JSContext *cx, JSObje
     return v.isTrue() ? 1 : 0;
 }
 
 /*
  * When hole is true, delete the property at the given index. Otherwise set
  * its value to v assuming v is rooted.
  */
 static JSBool
-SetOrDeleteArrayElement(JSContext *cx, JSObject *obj, jsdouble index,
+SetOrDeleteArrayElement(JSContext *cx, JSObject *obj, double index,
                         JSBool hole, const Value &v)
 {
     if (hole) {
         JS_ASSERT(v.isUndefined());
         return DeleteArrayElement(cx, obj, index, true) >= 0;
     }
     return SetArrayElement(cx, obj, index, v);
 }
 
 JSBool
-js_SetLengthProperty(JSContext *cx, JSObject *obj, jsdouble length)
+js_SetLengthProperty(JSContext *cx, JSObject *obj, double length)
 {
     Value v = NumberValue(length);
 
     /* We don't support read-only array length yet. */
     return obj->setProperty(cx, cx->runtime->atomState.lengthAtom, &v, false);
 }
 
 /*
@@ -599,17 +599,17 @@ array_length_setter(JSContext *cx, JSObj
         return obj->defineProperty(cx, cx->runtime->atomState.lengthAtom, *vp,
                                    NULL, NULL, JSPROP_ENUMERATE);
     }
 
     uint32_t newlen;
     if (!ToUint32(cx, *vp, &newlen))
         return false;
 
-    jsdouble d;
+    double d;
     if (!ToNumber(cx, *vp, &d))
         return false;
 
     if (d != newlen) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
         return false;
     }
 
@@ -2163,17 +2163,17 @@ SortComparatorFunction::operator()(const
     ag.setCallee(fval);
     ag.thisv() = UndefinedValue();
     ag[0] = a;
     ag[1] = b;
 
     if (!Invoke(cx, ag))
         return false;
 
-    jsdouble cmp;
+    double cmp;
     if (!ToNumber(cx, ag.rval(), &cmp))
         return false;
 
     /*
      * XXX eport some kind of error here if cmp is NaN? ECMA talks about
      * 'consistent compare functions' that don't return NaN, but is silent
      * about what the result should be. So we currently ignore it.
      */
@@ -2369,17 +2369,17 @@ array_push_slowly(JSContext *cx, JSObjec
     jsuint length;
 
     if (!js_GetLengthProperty(cx, obj, &length))
         return false;
     if (!InitArrayElements(cx, obj, length, args.length(), args.array(), UpdateTypes))
         return false;
 
     /* Per ECMA-262, return the new array length. */
-    jsdouble newlength = length + jsdouble(args.length());
+    double newlength = length + double(args.length());
     args.rval().setNumber(newlength);
     return js_SetLengthProperty(cx, obj, newlength);
 }
 
 static bool
 array_push1_dense(JSContext* cx, JSObject* obj, CallArgs &args)
 {
     JS_ASSERT(args.length() == 1);
@@ -2588,17 +2588,17 @@ array_unshift(JSContext *cx, uintN argc,
     JSObject *obj = ToObject(cx, &args.thisv());
     if (!obj)
         return false;
 
     jsuint length;
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
 
-    jsdouble newlen = length;
+    double newlen = length;
     if (args.length() > 0) {
         /* Slide up the array to make room for all args at the bottom. */
         if (length > 0) {
             bool optimized = false;
             do {
                 if (!obj->isDenseArray())
                     break;
                 if (js_PrototypeHasIndexedProperties(cx, obj))
@@ -2612,18 +2612,18 @@ array_unshift(JSContext *cx, uintN argc,
                 }
                 obj->moveDenseArrayElements(args.length(), 0, length);
                 for (uint32_t i = 0; i < args.length(); i++)
                     obj->setDenseArrayElement(i, MagicValue(JS_ARRAY_HOLE));
                 optimized = true;
             } while (false);
 
             if (!optimized) {
-                jsdouble last = length;
-                jsdouble upperIndex = last + args.length();
+                double last = length;
+                double upperIndex = last + args.length();
                 AutoValueRooter tvr(cx);
                 do {
                     --last, --upperIndex;
                     JSBool hole;
                     if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                         !GetElement(cx, obj, last, &hole, tvr.addr()) ||
                         !SetOrDeleteArrayElement(cx, obj, upperIndex, hole, tvr.value())) {
                         return JS_FALSE;
@@ -2726,17 +2726,17 @@ array_splice(JSContext *cx, uintN argc, 
     if (relativeStart < 0)
         actualStart = JS_MAX(len + relativeStart, 0);
     else
         actualStart = JS_MIN(relativeStart, len);
 
     /* Step 7. */
     uint32_t actualDeleteCount;
     if (argc != 1) {
-        jsdouble deleteCountDouble;
+        double deleteCountDouble;
         if (!ToInteger(cx, argc >= 2 ? args[1] : Int32Value(0), &deleteCountDouble))
             return false;
         actualDeleteCount = JS_MIN(JS_MAX(deleteCountDouble, 0), len - actualStart);
     } else {
         /*
          * Non-standard: if start was specified but deleteCount was omitted,
          * delete to the end of the array.  See bug 668024 for discussion.
          */
@@ -2848,19 +2848,19 @@ array_splice(JSContext *cx, uintN argc, 
         if (CanOptimizeForDenseStorage(obj, len, itemCount - actualDeleteCount, cx)) {
             obj->moveDenseArrayElements(actualStart + itemCount,
                                         actualStart + actualDeleteCount,
                                         len - (actualStart + actualDeleteCount));
 
             if (cx->typeInferenceEnabled())
                 obj->setDenseArrayInitializedLength(len + itemCount - actualDeleteCount);
         } else {
-            for (jsdouble k = len - actualDeleteCount; k > actualStart; k--) {
-                jsdouble from = k + actualDeleteCount - 1;
-                jsdouble to = k + itemCount - 1;
+            for (double k = len - actualDeleteCount; k > actualStart; k--) {
+                double from = k + actualDeleteCount - 1;
+                double to = k + itemCount - 1;
 
                 JSBool hole;
                 Value fromValue;
                 if (!JS_CHECK_OPERATION_LIMIT(cx) ||
                     !GetElement(cx, obj, from, &hole, &fromValue) ||
                     !SetOrDeleteArrayElement(cx, obj, to, hole, fromValue))
                 {
                     return false;
@@ -2874,17 +2874,17 @@ array_splice(JSContext *cx, uintN argc, 
 
     /* Steps 14-15. */
     for (uint32_t k = actualStart, i = 0; i < itemCount; i++, k++) {
         if (!SetArrayElement(cx, obj, k, items[i]))
             return false;
     }
 
     /* Step 16. */
-    jsdouble finalLength = jsdouble(len) - actualDeleteCount + itemCount;
+    double finalLength = double(len) - actualDeleteCount + itemCount;
     if (!js_SetLengthProperty(cx, obj, finalLength))
         return false;
 
     /* Step 17. */
     args.rval().setObject(*arr);
     return true;
 }
 
@@ -3009,17 +3009,17 @@ array_slice(JSContext *cx, uintN argc, V
         return false;
 
     if (!js_GetLengthProperty(cx, obj, &length))
         return JS_FALSE;
     begin = 0;
     end = length;
 
     if (args.length() > 0) {
-        jsdouble d;
+        double d;
         if (!ToInteger(cx, args[0], &d))
             return false;
         if (d < 0) {
             d += length;
             if (d < 0)
                 d = 0;
         } else if (d > length) {
             d = length;
@@ -3092,17 +3092,17 @@ array_indexOfHelper(JSContext *cx, Index
         return JS_FALSE;
     if (length == 0)
         goto not_found;
 
     if (args.length() <= 1) {
         i = (mode == LastIndexOf) ? length - 1 : 0;
         tosearch = (args.length() != 0) ? args[0] : UndefinedValue();
     } else {
-        jsdouble start;
+        double start;
 
         tosearch = args[0];
         if (!ToInteger(cx, args[1], &start))
             return false;
         if (start < 0) {
             start += length;
             if (start < 0) {
                 if (mode == LastIndexOf)
@@ -3658,19 +3658,19 @@ js_Array(JSContext *cx, uintN argc, Valu
     if (args[0].isInt32()) {
         int32_t i = args[0].toInt32();
         if (i < 0) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
             return false;
         }
         length = uint32_t(i);
     } else {
-        jsdouble d = args[0].toDouble();
+        double d = args[0].toDouble();
         length = js_DoubleToECMAUint32(d);
-        if (d != jsdouble(length)) {
+        if (d != double(length)) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
             return false;
         }
     }
 
     JSObject *obj = NewDenseUnallocatedArray(cx, length);
     if (!obj)
         return false;
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -136,17 +136,17 @@ extern JSObject *
 NewSlowEmptyArray(JSContext *cx);
 
 } /* namespace js */
 
 extern JSBool
 js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp);
 
 extern JSBool
-js_SetLengthProperty(JSContext *cx, JSObject *obj, jsdouble length);
+js_SetLengthProperty(JSContext *cx, JSObject *obj, double length);
 
 namespace js {
 
 extern JSBool
 array_defineElement(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
                     PropertyOp getter, StrictPropertyOp setter, uintN attrs);
 
 extern JSBool
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -227,16 +227,16 @@ js_ValueToBoolean(const Value &v)
         return v.toInt32() != 0;
     if (v.isString())
         return v.toString()->length() != 0;
     if (v.isObject())
         return JS_TRUE;
     if (v.isNullOrUndefined())
         return JS_FALSE;
     if (v.isDouble()) {
-        jsdouble d;
+        double d;
 
         d = v.toDouble();
         return !JSDOUBLE_IS_NaN(d) && d != 0;
     }
     JS_ASSERT(v.isBoolean());
     return v.toBoolean();
 }
--- a/js/src/jsclone.cpp
+++ b/js/src/jsclone.cpp
@@ -190,21 +190,21 @@ SCInput::readPair(uint32_t *tagp, uint32
  */
 static JS_NEVER_INLINE double
 CanonicalizeNan(double d)
 {
     return JS_CANONICALIZE_NAN(d);
 }
 
 bool
-SCInput::readDouble(jsdouble *p)
+SCInput::readDouble(double *p)
 {
     union {
         uint64_t u;
-        jsdouble d;
+        double d;
     } pun;
     if (!read(&pun.u))
         return false;
     *p = CanonicalizeNan(pun.d);
     return true;
 }
 
 template <class T>
@@ -260,56 +260,56 @@ PairToUInt64(uint32_t tag, uint32_t data
     return uint64_t(data) | (uint64_t(tag) << 32);
 }
 
 bool
 SCOutput::writePair(uint32_t tag, uint32_t data)
 {
     /*
      * As it happens, the tag word appears after the data word in the output.
-     * This is because exponents occupy the last 2 bytes of jsdoubles on the
+     * This is because exponents occupy the last 2 bytes of doubles on the
      * little-endian platforms we care most about.
      *
      * For example, JSVAL_TRUE is written using writePair(SCTAG_BOOLEAN, 1).
      * PairToUInt64 produces the number 0xFFFF000200000001.
      * That is written out as the bytes 01 00 00 00 02 00 FF FF.
      */
     return write(PairToUInt64(tag, data));
 }
 
 static inline uint64_t
-ReinterpretDoubleAsUInt64(jsdouble d)
+ReinterpretDoubleAsUInt64(double d)
 {
     union {
-        jsdouble d;
+        double d;
         uint64_t u;
     } pun;
     pun.d = d;
     return pun.u;
 }
 
-static inline jsdouble
+static inline double
 ReinterpretUInt64AsDouble(uint64_t u)
 {
     union {
         uint64_t u;
-        jsdouble d;
+        double d;
     } pun;
     pun.u = u;
     return pun.d;
 }
 
-static inline jsdouble
+static inline double
 ReinterpretPairAsDouble(uint32_t tag, uint32_t data)
 {
     return ReinterpretUInt64AsDouble(PairToUInt64(tag, data));
 }
 
 bool
-SCOutput::writeDouble(jsdouble d)
+SCOutput::writeDouble(double d)
 {
     return write(ReinterpretDoubleAsUInt64(CanonicalizeNan(d)));
 }
 
 template <class T>
 bool
 SCOutput::writeArray(const T *p, size_t nelems)
 {
@@ -525,17 +525,17 @@ JSStructuredCloneWriter::startWrite(cons
         return out.writePair(SCTAG_UNDEFINED, 0);
     } else if (v.isObject()) {
         JSObject *obj = &v.toObject();
         if (obj->isRegExp()) {
             RegExpObject &reobj = obj->asRegExp();
             return out.writePair(SCTAG_REGEXP_OBJECT, reobj.getFlags()) &&
                    writeString(SCTAG_STRING, reobj.getSource());
         } else if (obj->isDate()) {
-            jsdouble d = js_DateGetMsecSinceEpoch(context(), obj);
+            double d = js_DateGetMsecSinceEpoch(context(), obj);
             return out.writePair(SCTAG_DATE_OBJECT, 0) && out.writeDouble(d);
         } else if (obj->isObject() || obj->isArray()) {
             return startObject(obj);
         } else if (js_IsTypedArray(obj)) {
             return writeTypedArray(obj);
         } else if (js_IsArrayBuffer(obj)) {
             return writeArrayBuffer(obj);
         } else if (obj->isBoolean()) {
@@ -598,17 +598,17 @@ JSStructuredCloneWriter::write(const Val
     }
 
     memory.clear();
 
     return true;
 }
 
 bool
-JSStructuredCloneReader::checkDouble(jsdouble d)
+JSStructuredCloneReader::checkDouble(double d)
 {
     jsval_layout l;
     l.asDouble = d;
     if (!JSVAL_IS_DOUBLE_IMPL(l)) {
         JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL,
                              JSMSG_SC_BAD_SERIALIZED_DATA, "unrecognized NaN");
         return false;
     }
@@ -726,27 +726,27 @@ JSStructuredCloneReader::startRead(Value
             return false;
         vp->setString(str);
         if (tag == SCTAG_STRING_OBJECT && !js_PrimitiveToObject(context(), vp))
             return false;
         break;
       }
 
       case SCTAG_NUMBER_OBJECT: {
-        jsdouble d;
+        double d;
         if (!in.readDouble(&d) || !checkDouble(d))
             return false;
         vp->setDouble(d);
         if (!js_PrimitiveToObject(context(), vp))
             return false;
         break;
       }
 
       case SCTAG_DATE_OBJECT: {
-        jsdouble d;
+        double d;
         if (!in.readDouble(&d) || !checkDouble(d))
             return false;
         if (d == d && d != TIMECLIP(d)) {
             JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_BAD_SERIALIZED_DATA,
                                  "date");
             return false;
         }
         JSObject *obj = js_NewDateObjectMsec(context(), d);
@@ -803,17 +803,17 @@ JSStructuredCloneReader::startRead(Value
         break;
       }
 
       case SCTAG_ARRAY_BUFFER_OBJECT:
         return readArrayBuffer(data, vp);
 
       default: {
         if (tag <= SCTAG_FLOAT_MAX) {
-            jsdouble d = ReinterpretPairAsDouble(tag, data);
+            double d = ReinterpretPairAsDouble(tag, data);
             if (!checkDouble(d))
                 return false;
             vp->setNumber(d);
             break;
         }
 
         if (SCTAG_TYPED_ARRAY_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_MAX)
             return readTypedArray(tag, data, vp);
--- a/js/src/jsclone.h
+++ b/js/src/jsclone.h
@@ -58,17 +58,17 @@ ReadStructuredClone(JSContext *cx, const
 struct SCOutput {
   public:
     explicit SCOutput(JSContext *cx);
 
     JSContext *context() const { return cx; }
 
     bool write(uint64_t u);
     bool writePair(uint32_t tag, uint32_t data);
-    bool writeDouble(jsdouble d);
+    bool writeDouble(double d);
     bool writeBytes(const void *p, size_t nbytes);
     bool writeChars(const jschar *p, size_t nchars);
 
     template <class T>
     bool writeArray(const T *p, size_t nbytes);
 
     bool extractBuffer(uint64_t **datap, size_t *sizep);
 
@@ -82,30 +82,30 @@ struct SCOutput {
 struct SCInput {
   public:
     SCInput(JSContext *cx, const uint64_t *data, size_t nbytes);
 
     JSContext *context() const { return cx; }
 
     bool read(uint64_t *p);
     bool readPair(uint32_t *tagp, uint32_t *datap);
-    bool readDouble(jsdouble *p);
+    bool readDouble(double *p);
     bool readBytes(void *p, size_t nbytes);
     bool readChars(jschar *p, size_t nchars);
 
     template <class T>
     bool readArray(T *p, size_t nelems);
 
   private:
     bool eof();
 
     void staticAssertions() {
         JS_STATIC_ASSERT(sizeof(jschar) == 2);
         JS_STATIC_ASSERT(sizeof(uint32_t) == 4);
-        JS_STATIC_ASSERT(sizeof(jsdouble) == 8);
+        JS_STATIC_ASSERT(sizeof(double) == 8);
     }
 
     JSContext *cx;
     const uint64_t *point;
     const uint64_t *end;
 };
 
 }
@@ -118,17 +118,17 @@ struct JSStructuredCloneReader {
           callbacks(cb), closure(cbClosure) { }
 
     js::SCInput &input() { return in; }
     bool read(js::Value *vp);
 
   private:
     JSContext *context() { return in.context(); }
 
-    bool checkDouble(jsdouble d);
+    bool checkDouble(double d);
     JSString *readString(uint32_t nchars);
     bool readTypedArray(uint32_t tag, uint32_t nelems, js::Value *vp);
     bool readArrayBuffer(uint32_t nbytes, js::Value *vp);
     bool readId(jsid *idp);
     bool startRead(js::Value *vp);
 
     js::SCInput &in;
 
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -68,16 +68,17 @@
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 
 JSCompartment::JSCompartment(JSRuntime *rt)
   : rt(rt),
     principals(NULL),
     needsBarrier_(false),
+    barrierMarker_(rt->gcMarker.sizeLimit()),
     gcBytes(0),
     gcTriggerBytes(0),
     gcLastBytes(0),
     hold(false),
     typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
     data(NULL),
     active(false),
     hasDebugModeCodeToDrop(false),
--- a/js/src/jscompat.h
+++ b/js/src/jscompat.h
@@ -41,11 +41,11 @@
 #define jscompat_h___
 /*
  * Compatibility glue for various NSPR versions.  We must always define int8,
  * int16, jsword, and so on to minimize differences with js/ref, no matter what
  * the NSPR typedef names may be.
  */
 #include "jstypes.h"
 
-typedef JSIntn intN;
-typedef JSUintn uintN;
+typedef int intN;
+typedef unsigned uintN;
 #endif /* jscompat_h___ */
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -171,33 +171,33 @@ using namespace js::types;
 #define SecondsPerMinute 60.0
 
 #if defined(XP_WIN) || defined(XP_OS2)
 /* Work around msvc double optimization bug by making these runtime values; if
  * they're available at compile time, msvc optimizes division by them by
  * computing the reciprocal and multiplying instead of dividing - this loses
  * when the reciprocal isn't representable in a double.
  */
-static jsdouble msPerSecond = 1000.0;
-static jsdouble msPerDay = SecondsPerDay * 1000.0;
-static jsdouble msPerHour = SecondsPerHour * 1000.0;
-static jsdouble msPerMinute = SecondsPerMinute * 1000.0;
+static double msPerSecond = 1000.0;
+static double msPerDay = SecondsPerDay * 1000.0;
+static double msPerHour = SecondsPerHour * 1000.0;
+static double msPerMinute = SecondsPerMinute * 1000.0;
 #else
 #define msPerDay        (SecondsPerDay * msPerSecond)
 #define msPerHour       (SecondsPerHour * msPerSecond)
 #define msPerMinute     (SecondsPerMinute * msPerSecond)
 #define msPerSecond     1000.0
 #endif
 
 #define Day(t)          floor((t) / msPerDay)
 
-static jsdouble
-TimeWithinDay(jsdouble t)
+static double
+TimeWithinDay(double t)
 {
-    jsdouble result;
+    double result;
     result = fmod(t, msPerDay);
     if (result < 0)
         result += msPerDay;
     return result;
 }
 
 static inline bool
 IsLeapYear(jsint year)
@@ -220,20 +220,20 @@ DaysInFebruary(jsint year)
 /* math here has to be f.p, because we need
  *  floor((1968 - 1969) / 4) == -1
  */
 #define DayFromYear(y)  (365 * ((y)-1970) + floor(((y)-1969)/4.0)            \
                          - floor(((y)-1901)/100.0) + floor(((y)-1601)/400.0))
 #define TimeFromYear(y) (DayFromYear(y) * msPerDay)
 
 static jsint
-YearFromTime(jsdouble t)
+YearFromTime(double t)
 {
     jsint y = (jsint) floor(t /(msPerDay*365.2425)) + 1970;
-    jsdouble t2 = (jsdouble) TimeFromYear(y);
+    double t2 = (double) TimeFromYear(y);
 
     /*
      * Adjust the year if the approximation was wrong.  Since the year was
      * computed using the average number of ms per year, it will usually
      * be wrong for dates within several hours of a year transition.
      */
     if (t2 > t) {
         y--;
@@ -245,33 +245,33 @@ YearFromTime(jsdouble t)
 }
 
 #define DayWithinYear(t, year) ((intN) (Day(t) - DayFromYear(year)))
 
 /*
  * The following array contains the day of year for the first day of
  * each month, where index 0 is January, and day 0 is January 1.
  */
-static jsdouble firstDayOfMonth[2][13] = {
+static double firstDayOfMonth[2][13] = {
     {0.0, 31.0, 59.0, 90.0, 120.0, 151.0, 181.0, 212.0, 243.0, 273.0, 304.0, 334.0, 365.0},
     {0.0, 31.0, 60.0, 91.0, 121.0, 152.0, 182.0, 213.0, 244.0, 274.0, 305.0, 335.0, 366.0}
 };
 
 #define DayFromMonth(m, leap) firstDayOfMonth[leap][(intN)m]
 
 static intN
 DaysInMonth(jsint year, jsint month)
 {
     JSBool leap = IsLeapYear(year);
     intN result = intN(DayFromMonth(month, leap) - DayFromMonth(month-1, leap));
     return result;
 }
 
 static intN
-MonthFromTime(jsdouble t)
+MonthFromTime(double t)
 {
     intN d, step;
     jsint year = YearFromTime(t);
     d = DayWithinYear(t, year);
 
     if (d < (step = 31))
         return 0;
     if (d < (step += DaysInFebruary(year)))
@@ -293,17 +293,17 @@ MonthFromTime(jsdouble t)
     if (d < (step += 31))
         return 9;
     if (d < (step += 30))
         return 10;
     return 11;
 }
 
 static intN
-DateFromTime(jsdouble t)
+DateFromTime(double t)
 {
     intN d, step, next;
     jsint year = YearFromTime(t);
     d = DayWithinYear(t, year);
 
     if (d <= (next = 30))
         return d + 1;
     step = next;
@@ -336,35 +336,35 @@ DateFromTime(jsdouble t)
     step = next;
     if (d <= (next += 30))
         return d - step;
     step = next;
     return d - step;
 }
 
 static intN
-WeekDay(jsdouble t)
+WeekDay(double t)
 {
     jsint result;
     result = (jsint) Day(t) + 4;
     result = result % 7;
     if (result < 0)
         result += 7;
     return (intN) result;
 }
 
 #define MakeTime(hour, min, sec, ms) \
 ((((hour) * MinutesPerHour + (min)) * SecondsPerMinute + (sec)) * msPerSecond + (ms))
 
-static jsdouble
-MakeDay(jsdouble year, jsdouble month, jsdouble date)
+static double
+MakeDay(double year, double month, double date)
 {
     JSBool leap;
-    jsdouble yearday;
-    jsdouble monthday;
+    double yearday;
+    double monthday;
 
     year += floor(month / 12);
 
     month = fmod(month, 12.0);
     if (month < 0)
         month += 12;
 
     leap = IsLeapYear((jsint) year);
@@ -407,89 +407,89 @@ EquivalentYearForDST(jsint year)
     day = day % 7;
     if (day < 0)
         day += 7;
 
     return yearStartingWith[IsLeapYear(year)][day];
 }
 
 /* LocalTZA gets set by js_InitDateClass() */
-static jsdouble LocalTZA;
-
-static jsdouble
-DaylightSavingTA(jsdouble t, JSContext *cx)
+static double LocalTZA;
+
+static double
+DaylightSavingTA(double t, JSContext *cx)
 {
     /* abort if NaN */
     if (JSDOUBLE_IS_NaN(t))
         return t;
 
     /*
      * If earlier than 1970 or after 2038, potentially beyond the ken of
      * many OSes, map it to an equivalent year before asking.
      */
     if (t < 0.0 || t > 2145916800000.0) {
         jsint year = EquivalentYearForDST(YearFromTime(t));
-        jsdouble day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
+        double day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
         t = MakeDate(day, TimeWithinDay(t));
     }
 
     int64_t timeMilliseconds = static_cast<int64_t>(t);
     int64_t offsetMilliseconds = cx->dstOffsetCache.getDSTOffsetMilliseconds(timeMilliseconds, cx);
-    return static_cast<jsdouble>(offsetMilliseconds);
+    return static_cast<double>(offsetMilliseconds);
 }
 
-static jsdouble
-AdjustTime(jsdouble date, JSContext *cx)
+static double
+AdjustTime(double date, JSContext *cx)
 {
-    jsdouble t = DaylightSavingTA(date, cx) + LocalTZA;
+    double t = DaylightSavingTA(date, cx) + LocalTZA;
     t = (LocalTZA >= 0) ? fmod(t, msPerDay) : -fmod(msPerDay - t, msPerDay);
     return t;
 }
 
-static jsdouble
-LocalTime(jsdouble t, JSContext *cx)
+static double
+LocalTime(double t, JSContext *cx)
 {
     return t + AdjustTime(t, cx);
 }
 
-static jsdouble
-UTC(jsdouble t, JSContext *cx)
+static double
+UTC(double t, JSContext *cx)
 {
     return t - AdjustTime(t - LocalTZA, cx);
 }
 
 static intN
-HourFromTime(jsdouble t)
+HourFromTime(double t)
 {
     intN result = (intN) fmod(floor(t/msPerHour), HoursPerDay);
     if (result < 0)
         result += (intN)HoursPerDay;
     return result;
 }
 
 static intN
-MinFromTime(jsdouble t)
+MinFromTime(double t)
 {
     intN result = (intN) fmod(floor(t / msPerMinute), MinutesPerHour);
     if (result < 0)
         result += (intN)MinutesPerHour;
     return result;
 }
 
 static intN
-SecFromTime(jsdouble t)
+SecFromTime(double t)
 {
     intN result = (intN) fmod(floor(t / msPerSecond), SecondsPerMinute);
     if (result < 0)
         result += (intN)SecondsPerMinute;
     return result;
 }
 
 static intN
-msFromTime(jsdouble t)
+msFromTime(double t)
 {
     intN result = (intN) fmod(t, msPerSecond);
     if (result < 0)
         result += (intN)msPerSecond;
     return result;
 }
 
 /**
@@ -573,43 +573,43 @@ date_regionMatches(const char* s1, int s
     if (count == 0) {
         result = JS_TRUE;
     }
 
     return result;
 }
 
 /* find UTC time from given date... no 1900 correction! */
-static jsdouble
-date_msecFromDate(jsdouble year, jsdouble mon, jsdouble mday, jsdouble hour,
-                  jsdouble min, jsdouble sec, jsdouble msec)
+static double
+date_msecFromDate(double year, double mon, double mday, double hour,
+                  double min, double sec, double msec)
 {
-    jsdouble day;
-    jsdouble msec_time;
-    jsdouble result;
+    double day;
+    double msec_time;
+    double result;
 
     day = MakeDay(year, mon, mday);
     msec_time = MakeTime(hour, min, sec, msec);
     result = MakeDate(day, msec_time);
     return result;
 }
 
 /* compute the time in msec (unclipped) from the given args */
 #define MAXARGS        7
 
 static JSBool
 date_msecFromArgs(JSContext *cx, CallArgs args, double *rval)
 {
     uintN loop;
-    jsdouble array[MAXARGS];
-    jsdouble msec_time;
+    double array[MAXARGS];
+    double msec_time;
 
     for (loop = 0; loop < MAXARGS; loop++) {
         if (loop < args.length()) {
-            jsdouble d;
+            double d;
             if (!ToNumber(cx, args[loop], &d))
                 return JS_FALSE;
             /* return NaN if any arg is not finite */
             if (!JSDOUBLE_IS_FINITE(d)) {
                 *rval = js_NaN;
                 return JS_TRUE;
             }
             array[loop] = js_DoubleToInteger(d);
@@ -635,17 +635,17 @@ date_msecFromArgs(JSContext *cx, CallArg
 /*
  * See ECMA 15.9.4.[3-10];
  */
 static JSBool
 date_UTC(JSContext *cx, uintN argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
-    jsdouble msec_time;
+    double msec_time;
     if (!date_msecFromArgs(cx, args, &msec_time))
         return JS_FALSE;
 
     msec_time = TIMECLIP(msec_time);
 
     args.rval().setNumber(msec_time);
     return JS_TRUE;
 }
@@ -675,19 +675,19 @@ digits(size_t *result, const jschar *s, 
  * Read and convert decimal digits to the right of a decimal point,
  * representing a fractional integer, from s[*i] into *result
  * while *i < limit.
  *
  * Succeed if any digits are converted. Advance *i only
  * as digits are consumed.
  */
 static JSBool
-fractional(jsdouble *result, const jschar *s, size_t *i, size_t limit)
+fractional(double *result, const jschar *s, size_t *i, size_t limit)
 {
-    jsdouble factor = 0.1;
+    double factor = 0.1;
     size_t init = *i;
     *result = 0.0;
     while (*i < limit &&
            ('0' <= s[*i] && s[*i] <= '9')) {
         *result += (s[*i] - '0') * factor;
         factor *= 0.1;
         ++(*i);
     }
@@ -765,32 +765,32 @@ ndigits(size_t n, size_t *result, const 
  *   hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
  *   mm   = two digits of minute (00 through 59)
  *   ss   = two digits of second (00 through 59)
  *   s    = one or more digits representing a decimal fraction of a second
  *   TZD  = time zone designator (Z or +hh:mm or -hh:mm or missing for local)
  */
 
 static JSBool
-date_parseISOString(JSLinearString *str, jsdouble *result, JSContext *cx)
+date_parseISOString(JSLinearString *str, double *result, JSContext *cx)
 {
-    jsdouble msec;
+    double msec;
 
     const jschar *s;
     size_t limit;
     size_t i = 0;
     int tzMul = 1;
     int dateMul = 1;
     size_t year = 1970;
     size_t month = 1;
     size_t day = 1;
     size_t hour = 0;
     size_t min = 0;
     size_t sec = 0;
-    jsdouble frac = 0;
+    double frac = 0;
     bool isLocalTime = JS_FALSE;
     size_t tzHour = 0;
     size_t tzMin = 0;
 
 #define PEEK(ch) (i < limit && s[i] == ch)
 
 #define NEED(ch)                                                     \
     JS_BEGIN_MACRO                                                   \
@@ -874,17 +874,17 @@ date_parseISOString(JSLinearString *str,
         || tzMin > 59)
         goto syntax;
 
     if (i != limit)
         goto syntax;
 
     month -= 1; /* convert month to 0-based */
 
-    msec = date_msecFromDate(dateMul * (jsdouble)year, month, day,
+    msec = date_msecFromDate(dateMul * (double)year, month, day,
                              hour, min, sec,
                              frac * 1000.0);;
 
     if (isLocalTime) {
         msec = UTC(msec, cx);
     } else {
         msec -= ((tzMul) * ((tzHour * msPerHour)
                             + (tzMin * msPerMinute)));
@@ -904,19 +904,19 @@ date_parseISOString(JSLinearString *str,
 
 #undef PEEK
 #undef NEED
 #undef DONE_UNLESS
 #undef NEED_NDIGITS
 }
 
 static JSBool
-date_parseString(JSLinearString *str, jsdouble *result, JSContext *cx)
+date_parseString(JSLinearString *str, double *result, JSContext *cx)
 {
-    jsdouble msec;
+    double msec;
 
     const jschar *s;
     size_t limit;
     size_t i = 0;
     int year = -1;
     int mon = -1;
     int mday = -1;
     int hour = -1;
@@ -1179,17 +1179,17 @@ syntax:
     *result = 0;
     return JS_FALSE;
 }
 
 static JSBool
 date_parse(JSContext *cx, uintN argc, Value *vp)
 {
     JSString *str;
-    jsdouble result;
+    double result;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return true;
     }
     str = ToString(cx, vp[2]);
     if (!str)
         return JS_FALSE;
@@ -1203,34 +1203,34 @@ date_parse(JSContext *cx, uintN argc, Va
         return true;
     }
 
     result = TIMECLIP(result);
     vp->setNumber(result);
     return true;
 }
 
-static inline jsdouble
+static inline double
 NowAsMillis()
 {
-    return (jsdouble) (PRMJ_Now() / PRMJ_USEC_PER_MSEC);
+    return (double) (PRMJ_Now() / PRMJ_USEC_PER_MSEC);
 }
 
 static JSBool
 date_now(JSContext *cx, uintN argc, Value *vp)
 {
     vp->setDouble(NowAsMillis());
     return JS_TRUE;
 }
 
 /*
  * Set UTC time to a given time and invalidate cached local time.
  */
 static JSBool
-SetUTCTime(JSContext *cx, JSObject *obj, jsdouble t, Value *vp = NULL)
+SetUTCTime(JSContext *cx, JSObject *obj, double t, Value *vp = NULL)
 {
     JS_ASSERT(obj->isDate());
 
     for (size_t ind = JSObject::JSSLOT_DATE_COMPONENTS_START;
          ind < JSObject::DATE_CLASS_RESERVED_SLOTS;
          ind++) {
         obj->setSlot(ind, UndefinedValue());
     }
@@ -1239,57 +1239,57 @@ SetUTCTime(JSContext *cx, JSObject *obj,
     if (vp)
         vp->setDouble(t);
     return true;
 }
 
 static void
 SetDateToNaN(JSContext *cx, JSObject *obj, Value *vp = NULL)
 {
-    jsdouble NaN = cx->runtime->NaNValue.getDoubleRef();
+    double NaN = cx->runtime->NaNValue.getDoubleRef();
     SetUTCTime(cx, obj, NaN, vp);
 }
 
 /*
  * Cache the local time, year, month, and so forth of the object.
  * If UTC time is not finite (e.g., NaN), the local time
  * slots will be set to the UTC time without conversion.
  */
 static bool
 FillLocalTimes(JSContext *cx, JSObject *obj)
 {
     JS_ASSERT(obj->isDate());
 
-    jsdouble utcTime = obj->getDateUTCTime().toNumber();
+    double utcTime = obj->getDateUTCTime().toNumber();
 
     if (!JSDOUBLE_IS_FINITE(utcTime)) {
         for (size_t ind = JSObject::JSSLOT_DATE_COMPONENTS_START;
              ind < JSObject::DATE_CLASS_RESERVED_SLOTS;
              ind++) {
             obj->setSlot(ind, DoubleValue(utcTime));
         }
         return true;
     }
 
-    jsdouble localTime = LocalTime(utcTime, cx);
+    double localTime = LocalTime(utcTime, cx);
 
     obj->setSlot(JSObject::JSSLOT_DATE_LOCAL_TIME, DoubleValue(localTime));
 
     jsint year = (jsint) floor(localTime /(msPerDay*365.2425)) + 1970;
-    jsdouble yearStartTime = (jsdouble) TimeFromYear(year);
+    double yearStartTime = (double) TimeFromYear(year);
 
     /* Adjust the year in case the approximation was wrong, as in YearFromTime. */
     jsint yearDays;
     if (yearStartTime > localTime) {
         year--;
         yearStartTime -= (msPerDay * DaysInYear(year));
         yearDays = DaysInYear(year);
     } else {
         yearDays = DaysInYear(year);
-        jsdouble nextStart = yearStartTime + (msPerDay * yearDays);
+        double nextStart = yearStartTime + (msPerDay * yearDays);
         if (nextStart <= localTime) {
             year++;
             yearStartTime = nextStart;
             yearDays = DaysInYear(year);
         }
     }
 
     obj->setSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR, Int32Value(year));
@@ -1577,17 +1577,17 @@ date_getUTCDay(JSContext *cx, uintN argc
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     bool ok;
     JSObject *obj = NonGenericMethodGuard(cx, args, date_getUTCDay, &DateClass, &ok);
     if (!obj)
         return ok;
 
-    jsdouble result = obj->getDateUTCTime().toNumber();
+    double result = obj->getDateUTCTime().toNumber();
     if (JSDOUBLE_IS_FINITE(result))
         result = WeekDay(result);
 
     args.rval().setNumber(result);
     return true;
 }
 
 static JSBool
@@ -1735,17 +1735,17 @@ date_setTime(JSContext *cx, uintN argc, 
     if (!obj)
         return ok;
 
     if (args.length() == 0) {
         SetDateToNaN(cx, obj, &args.rval());
         return true;
     }
 
-    jsdouble result;
+    double result;
     if (!ToNumber(cx, args[0], &result))
         return false;
 
     return SetUTCTime(cx, obj, TIMECLIP(result), &args.rval());
 }
 
 static JSBool
 date_makeTime(JSContext *cx, Native native, uintN maxargs, JSBool local, uintN argc, Value *vp)
@@ -2039,44 +2039,44 @@ static const char* months[] =
 {
    "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 };
 
 
 // Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
 // requires a PRMJTime... which only has 16-bit years.  Sub-ECMA.
 static void
-print_gmt_string(char* buf, size_t size, jsdouble utctime)
+print_gmt_string(char* buf, size_t size, double utctime)
 {
     JS_snprintf(buf, size, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
                 days[WeekDay(utctime)],
                 DateFromTime(utctime),
                 months[MonthFromTime(utctime)],
                 YearFromTime(utctime),
                 HourFromTime(utctime),
                 MinFromTime(utctime),
                 SecFromTime(utctime));
 }
 
 static void
-print_iso_string(char* buf, size_t size, jsdouble utctime)
+print_iso_string(char* buf, size_t size, double utctime)
 {
     JS_snprintf(buf, size, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d.%.3dZ",
                 YearFromTime(utctime),
                 MonthFromTime(utctime) + 1,
                 DateFromTime(utctime),
                 HourFromTime(utctime),
                 MinFromTime(utctime),
                 SecFromTime(utctime),
                 msFromTime(utctime));
 }
 
 static JSBool
 date_utc_format(JSContext *cx, Native native, CallArgs args,
-                void (*printFunc)(char*, size_t, jsdouble))
+                void (*printFunc)(char*, size_t, double))
 {
     bool ok;
     JSObject *obj = NonGenericMethodGuard(cx, args, native, &DateClass, &ok);
     if (!obj)
         return ok;
 
     double utctime = obj->getDateUTCTime().toNumber();
 
@@ -2155,17 +2155,17 @@ date_toJSON(JSContext *cx, uintN argc, V
         return false;
     *vp = args.rval();
     return true;
 }
 
 /* for Date.toLocaleString; interface to PRMJTime date struct.
  */
 static void
-new_explode(jsdouble timeval, PRMJTime *split, JSContext *cx)
+new_explode(double timeval, PRMJTime *split, JSContext *cx)
 {
     jsint year = YearFromTime(timeval);
 
     split->tm_usec = int32_t(msFromTime(timeval)) * 1000;
     split->tm_sec = int8_t(SecFromTime(timeval));
     split->tm_min = int8_t(MinFromTime(timeval));
     split->tm_hour = int8_t(HourFromTime(timeval));
     split->tm_mday = int8_t(DateFromTime(timeval));
@@ -2180,29 +2180,29 @@ new_explode(jsdouble timeval, PRMJTime *
 }
 
 typedef enum formatspec {
     FORMATSPEC_FULL, FORMATSPEC_DATE, FORMATSPEC_TIME
 } formatspec;
 
 /* helper function */
 static JSBool
-date_format(JSContext *cx, jsdouble date, formatspec format, CallReceiver call)
+date_format(JSContext *cx, double date, formatspec format, CallReceiver call)
 {
     char buf[100];
     JSString *str;
     char tzbuf[100];
     JSBool usetz;
     size_t i, tzlen;
     PRMJTime split;
 
     if (!JSDOUBLE_IS_FINITE(date)) {
         JS_snprintf(buf, sizeof buf, js_NaN_date_str);
     } else {
-        jsdouble local = LocalTime(date, cx);
+        double local = LocalTime(date, cx);
 
         /* offset from GMT in minutes.  The offset includes daylight savings,
            if it applies. */
         jsint minutes = (jsint) floor(AdjustTime(date, cx) / msPerMinute);
 
         /* map 510 minutes to 0830 hours */
         intN offset = (minutes / 60) * 100 + minutes % 60;
 
@@ -2302,17 +2302,17 @@ ToLocaleHelper(JSContext *cx, CallReceiv
 {
     double utctime = obj->getDateUTCTime().toNumber();
 
     char buf[100];
     if (!JSDOUBLE_IS_FINITE(utctime)) {
         JS_snprintf(buf, sizeof buf, js_NaN_date_str);
     } else {
         intN result_len;
-        jsdouble local = LocalTime(utctime, cx);
+        double local = LocalTime(utctime, cx);
         PRMJTime split;
         new_explode(local, &split, cx);
 
         /* let PRMJTime format it.       */
         result_len = PRMJ_FormatTime(buf, sizeof buf, format, &split);
 
         /* If it failed, default to toString. */
         if (result_len == 0)
@@ -2590,17 +2590,17 @@ js_Date(JSContext *cx, uintN argc, Value
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Date called as function. */
     if (!IsConstructing(args))
         return date_format(cx, NowAsMillis(), FORMATSPEC_FULL, args);
 
     /* Date called as constructor. */
-    jsdouble d;
+    double d;
     if (args.length() == 0) {
         d = NowAsMillis();
     } else if (args.length() == 1) {
         if (!args[0].isString()) {
             /* the argument is a millisecond number */
             if (!ToNumber(cx, args[0], &d))
                 return false;
             d = TIMECLIP(d);
@@ -2615,17 +2615,17 @@ js_Date(JSContext *cx, uintN argc, Value
                 return false;
 
             if (!date_parseString(linearStr, &d, cx))
                 d = js_NaN;
             else
                 d = TIMECLIP(d);
         }
     } else {
-        jsdouble msec_time;
+        double msec_time;
         if (!date_msecFromArgs(cx, args, &msec_time))
             return false;
 
         if (JSDOUBLE_IS_FINITE(msec_time)) {
             msec_time = UTC(msec_time, cx);
             msec_time = TIMECLIP(msec_time);
         }
         d = msec_time;
@@ -2684,102 +2684,102 @@ js_InitDateClass(JSContext *cx, JSObject
 
     if (!DefineConstructorAndPrototype(cx, global, JSProto_Date, ctor, dateProto))
         return NULL;
 
     return dateProto;
 }
 
 JS_FRIEND_API(JSObject *)
-js_NewDateObjectMsec(JSContext *cx, jsdouble msec_time)
+js_NewDateObjectMsec(JSContext *cx, double msec_time)
 {
     JSObject *obj = NewBuiltinClassInstance(cx, &DateClass);
     if (!obj)
         return NULL;
     if (!SetUTCTime(cx, obj, msec_time))
         return NULL;
     return obj;
 }
 
 JS_FRIEND_API(JSObject *)
 js_NewDateObject(JSContext* cx, int year, int mon, int mday,
                  int hour, int min, int sec)
 {
     JSObject *obj;
-    jsdouble msec_time;
+    double msec_time;
 
     JS_ASSERT(mon < 12);
     msec_time = date_msecFromDate(year, mon, mday, hour, min, sec, 0);
     obj = js_NewDateObjectMsec(cx, UTC(msec_time, cx));
     return obj;
 }
 
 JS_FRIEND_API(JSBool)
 js_DateIsValid(JSContext *cx, JSObject* obj)
 {
     return obj->isDate() && !JSDOUBLE_IS_NaN(obj->getDateUTCTime().toNumber());
 }
 
 JS_FRIEND_API(int)
 js_DateGetYear(JSContext *cx, JSObject* obj)
 {
-    jsdouble localtime;
+    double localtime;
 
     /* Preserve legacy API behavior of returning 0 for invalid dates. */
     if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
         JSDOUBLE_IS_NaN(localtime)) {
         return 0;
     }
 
     return (int) YearFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetMonth(JSContext *cx, JSObject* obj)
 {
-    jsdouble localtime;
+    double localtime;
 
     if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
         JSDOUBLE_IS_NaN(localtime)) {
         return 0;
     }
 
     return (int) MonthFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetDate(JSContext *cx, JSObject* obj)
 {
-    jsdouble localtime;
+    double localtime;
 
     if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
         JSDOUBLE_IS_NaN(localtime)) {
         return 0;
     }
 
     return (int) DateFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetHours(JSContext *cx, JSObject* obj)
 {
-    jsdouble localtime;
+    double localtime;
 
     if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
         JSDOUBLE_IS_NaN(localtime)) {
         return 0;
     }
 
     return (int) HourFromTime(localtime);
 }
 
 JS_FRIEND_API(int)
 js_DateGetMinutes(JSContext *cx, JSObject* obj)
 {
-    jsdouble localtime;
+    double localtime;
 
     if (!GetAndCacheLocalTime(cx, obj, &localtime) ||
         JSDOUBLE_IS_NaN(localtime)) {
         return 0;
     }
 
     return (int) MinFromTime(localtime);
 }
@@ -2791,17 +2791,17 @@ js_DateGetSeconds(JSContext *cx, JSObjec
         return 0;
     
     double utctime = obj->getDateUTCTime().toNumber();
     if (JSDOUBLE_IS_NaN(utctime))
         return 0;
     return (int) SecFromTime(utctime);
 }
 
-JS_FRIEND_API(jsdouble)
+JS_FRIEND_API(double)
 js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj)
 {
     return obj->isDate() ? obj->getDateUTCTime().toNumber() : 0;
 }
 
 #ifdef JS_THREADSAFE
 #include "prinrval.h"
 
--- a/js/src/jsdate.h
+++ b/js/src/jsdate.h
@@ -59,17 +59,17 @@ js_InitDateClass(JSContext *cx, JSObject
  * These functions provide a C interface to the date/time object
  */
 
 /*
  * Construct a new Date Object from a time value given in milliseconds UTC
  * since the epoch.
  */
 extern JS_FRIEND_API(JSObject*)
-js_NewDateObjectMsec(JSContext* cx, jsdouble msec_time);
+js_NewDateObjectMsec(JSContext* cx, double msec_time);
 
 /*
  * Construct a new Date Object from an exploded local time value.
  *
  * Assert that mon < 12 to help catch off-by-one user errors, which are common
  * due to the 0-based month numbering copied into JS from Java (java.util.Date
  * in 1995).
  */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1870,18 +1870,19 @@ bool
 SliceBudget::checkOverBudget()
 {
     bool over = PRMJ_Now() > deadline;
     if (!over)
         counter = CounterReset;
     return over;
 }
 
-GCMarker::GCMarker()
-  : color(BLACK),
+GCMarker::GCMarker(size_t sizeLimit)
+  : stack(sizeLimit),
+    color(BLACK),
     started(false),
     unmarkedArenaStackTop(NULL),
     markLaterArenas(0),
     grayFailed(false)
 {
 }
 
 bool
@@ -2112,16 +2113,25 @@ GCMarker::appendGrayRoot(void *thing, JS
 
 void
 GCMarker::GrayCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind)
 {
     GCMarker *gcmarker = static_cast<GCMarker *>(trc);
     gcmarker->appendGrayRoot(*thingp, kind);
 }
 
+void
+SetMarkStackLimit(JSRuntime *rt, size_t limit)
+{
+    JS_ASSERT(!rt->gcRunning);
+    rt->gcMarker.setSizeLimit(limit);
+    for (CompartmentsIter c(rt); !c.done(); c.next())
+        c->barrierMarker_.setSizeLimit(limit);
+}
+
 } /* namespace js */
 
 #ifdef DEBUG
 static void
 EmptyMarkCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind)
 {
 }
 #endif
@@ -3054,57 +3064,66 @@ EndMarkPhase(JSContext *cx)
     }
 #endif
 }
 
 #ifdef DEBUG
 static void
 ValidateIncrementalMarking(JSContext *cx)
 {
+    typedef HashMap<Chunk *, uintptr_t *, GCChunkHasher, SystemAllocPolicy> BitmapMap;
+    BitmapMap map;
+    if (!map.init())
+        return;
+
     JSRuntime *rt = cx->runtime;
     FullGCMarker *gcmarker = &rt->gcMarker;
 
+    /* Save existing mark bits */
+    for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
+        ChunkBitmap *bitmap = &r.front()->bitmap;
+        uintptr_t *entry = (uintptr_t *)js_malloc(sizeof(bitmap->bitmap));
+        if (!entry)
+            return;
+
+        memcpy(entry, bitmap->bitmap, sizeof(bitmap->bitmap));
+        if (!map.putNew(r.front(), entry))
+            return;
+    }
+
+    /*
+     * After this point, the function should run to completion, so we shouldn't
+     * do anything fallible.
+     */
+
+    /* Re-do all the marking, but non-incrementally. */
     js::gc::State state = rt->gcIncrementalState;
     rt->gcIncrementalState = NO_INCREMENTAL;
 
     /* As we're re-doing marking, we need to reset the weak map list. */
     WeakMapBase::resetWeakMapList(rt);
 
     JS_ASSERT(gcmarker->isDrained());
     gcmarker->reset();
 
-    typedef HashMap<Chunk *, uintptr_t *> BitmapMap;
-    BitmapMap map(cx);
-    map.init();
-
-    for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
-        ChunkBitmap *bitmap = &r.front()->bitmap;
-        uintptr_t *entry = (uintptr_t *)js_malloc(sizeof(bitmap->bitmap));
-        if (entry)
-            memcpy(entry, bitmap->bitmap, sizeof(bitmap->bitmap));
-        map.putNew(r.front(), entry);
-    }
-
     for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
         r.front()->bitmap.clear();
 
     MarkRuntime(gcmarker, true);
     SliceBudget budget;
     rt->gcMarker.drainMarkStack(budget);
     MarkGrayAndWeak(cx);
 
+    /* Now verify that we have the same mark bits as before. */
     for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
         Chunk *chunk = r.front();
         ChunkBitmap *bitmap = &chunk->bitmap;
         uintptr_t *entry = map.lookup(r.front())->value;
         ChunkBitmap incBitmap;
 
-        if (!entry)
-            continue;
-
         memcpy(incBitmap.bitmap, entry, sizeof(incBitmap.bitmap));
         js_free(entry);
 
         for (size_t i = 0; i < ArenasPerChunk; i++) {
             Arena *arena = &chunk->arenas[i];
             if (!arena->aheader.allocated())
                 continue;
             if (rt->gcCurrentCompartment && arena->aheader.compartment != rt->gcCurrentCompartment)
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -1567,22 +1567,25 @@ template<class T>
 struct MarkStack {
     T *stack;
     T *tos;
     T *limit;
 
     T *ballast;
     T *ballastLimit;
 
-    MarkStack()
+    size_t sizeLimit;
+
+    MarkStack(size_t sizeLimit)
       : stack(NULL),
         tos(NULL),
         limit(NULL),
         ballast(NULL),
-        ballastLimit(NULL) { }
+        ballastLimit(NULL),
+        sizeLimit(sizeLimit) { }
 
     ~MarkStack() {
         if (stack != ballast)
             js_free(stack);
         js_free(ballast);
     }
 
     bool init(size_t ballastcap) {
@@ -1590,20 +1593,33 @@ struct MarkStack {
 
         if (ballastcap == 0)
             return true;
 
         ballast = (T *)js_malloc(sizeof(T) * ballastcap);
         if (!ballast)
             return false;
         ballastLimit = ballast + ballastcap;
+        initFromBallast();
+        return true;
+    }
+
+    void initFromBallast() {
         stack = ballast;
         limit = ballastLimit;
+        if (size_t(limit - stack) > sizeLimit)
+            limit = stack + sizeLimit;
         tos = stack;
-        return true;
+    }
+
+    void setSizeLimit(size_t size) {
+        JS_ASSERT(isEmpty());
+
+        sizeLimit = size;
+        reset();
     }
 
     bool push(T item) {
         if (tos == limit) {
             if (!enlarge())
                 return false;
         }
         JS_ASSERT(tos < limit);
@@ -1635,31 +1651,32 @@ struct MarkStack {
         return *--tos;
     }
 
     ptrdiff_t position() const {
         return tos - stack;
     }
 
     void reset() {
-        if (stack != ballast) {
+        if (stack != ballast)
             js_free(stack);
-            stack = ballast;
-            limit = ballastLimit;
-        }
-        tos = stack;
-        JS_ASSERT(limit == ballastLimit);
+        initFromBallast();
+        JS_ASSERT(stack == ballast);
     }
 
     bool enlarge() {
         size_t tosIndex = tos - stack;
         size_t cap = limit - stack;
+        if (cap == sizeLimit)
+            return false;
         size_t newcap = cap * 2;
         if (newcap == 0)
             newcap = 32;
+        if (newcap > sizeLimit)
+            newcap = sizeLimit;
 
         T *newStack;
         if (stack == ballast) {
             newStack = (T *)js_malloc(sizeof(T) * newcap);
             if (!newStack)
                 return false;
             for (T *src = stack, *dst = newStack; src < tos; )
                 *dst++ = *src++;
@@ -1736,19 +1753,22 @@ struct GCMarker : public JSTracer {
     static const uintptr_t StackTagMask = 7;
 
     static void staticAsserts() {
         JS_STATIC_ASSERT(StackTagMask >= uintptr_t(LastTag));
         JS_STATIC_ASSERT(StackTagMask <= gc::Cell::CellMask);
     }
 
   public:
-    explicit GCMarker();
+    explicit GCMarker(size_t sizeLimit);
     bool init(bool lazy);
 
+    void setSizeLimit(size_t size) { stack.setSizeLimit(size); }
+    size_t sizeLimit() const { return stack.sizeLimit; }
+
     void start(JSRuntime *rt, JSContext *cx);
     void stop();
     void reset();
 
     void pushObject(JSObject *obj) {
         pushTaggedPtr(ObjectTag, obj);
     }
 
@@ -1876,29 +1896,35 @@ struct GCMarker : public JSTracer {
           : thing(thing), kind(kind) {}
     };
 
     bool grayFailed;
     Vector<GrayRoot, 0, SystemAllocPolicy> grayRoots;
 };
 
 struct BarrierGCMarker : public GCMarker {
+    BarrierGCMarker(size_t sizeLimit) : GCMarker(sizeLimit) {}
+
     bool init() {
         return GCMarker::init(true);
     }
 };
 
+struct FullGCMarker : public GCMarker {
+    FullGCMarker() : GCMarker(size_t(-1)) {}
 
-struct FullGCMarker : public GCMarker {
     bool init() {
         return GCMarker::init(false);
     }
 };
 
 void
+SetMarkStackLimit(JSRuntime *rt, size_t limit);
+
+void
 MarkStackRangeConservatively(JSTracer *trc, Value *begin, Value *end);
 
 typedef void (*IterateChunkCallback)(JSContext *cx, void *data, gc::Chunk *chunk);
 typedef void (*IterateArenaCallback)(JSContext *cx, void *data, gc::Arena *arena,
                                      JSGCTraceKind traceKind, size_t thingSize);
 typedef void (*IterateCellCallback)(JSContext *cx, void *data, void *thing,
                                     JSGCTraceKind traceKind, size_t thingSize);
 
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -2038,25 +2038,18 @@ TypeCompartment::newAllocationSiteTypeOb
     }
 
     return res;
 }
 
 static inline jsid
 GetAtomId(JSContext *cx, JSScript *script, const jsbytecode *pc, unsigned offset)
 {
-    unsigned index = js_GetIndexFromBytecode(script, (jsbytecode*) pc, offset);
-    return MakeTypeId(cx, ATOM_TO_JSID(script->getAtom(index)));
-}
-
-static inline const Value &
-GetScriptConst(JSContext *cx, JSScript *script, const jsbytecode *pc)
-{
-    unsigned index = js_GetIndexFromBytecode(script, (jsbytecode*) pc, 0);
-    return script->getConst(index);
+    JSAtom *atom = script->getAtom(GET_UINT32_INDEX(pc + offset));
+    return MakeTypeId(cx, ATOM_TO_JSID(atom));
 }
 
 bool
 types::UseNewType(JSContext *cx, JSScript *script, jsbytecode *pc)
 {
     JS_ASSERT(cx->typeInferenceEnabled());
 
     /*
@@ -3438,22 +3431,16 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
       case JSOP_GOSUB:
       case JSOP_RETSUB:
       case JSOP_CONDSWITCH:
       case JSOP_DEFAULT:
       case JSOP_POPN:
       case JSOP_STARTXML:
       case JSOP_STARTXMLEXPR:
       case JSOP_DEFXMLNS:
-      case JSOP_INDEXBASE:
-      case JSOP_INDEXBASE1:
-      case JSOP_INDEXBASE2:
-      case JSOP_INDEXBASE3:
-      case JSOP_RESETBASE:
-      case JSOP_RESETBASE0:
       case JSOP_POPV:
       case JSOP_DEBUGGER:
       case JSOP_SETCALL:
       case JSOP_TABLESWITCH:
       case JSOP_LOOKUPSWITCH:
       case JSOP_TRY:
       case JSOP_LABEL:
         break;
@@ -4586,18 +4573,17 @@ AnalyzeNewScriptProperties(JSContext *cx
         JSObject *obj = *pbaseobj;
 
         if (op == JSOP_SETPROP && uses->u.which == 1) {
             /*
              * Don't use GetAtomId here, we need to watch for SETPROP on
              * integer properties and bail out. We can't mark the aggregate
              * JSID_VOID type property as being in a definite slot.
              */
-            unsigned index = js_GetIndexFromBytecode(script, pc, 0);
-            jsid id = ATOM_TO_JSID(script->getAtom(index));
+            jsid id = ATOM_TO_JSID(script->getAtom(GET_UINT32_INDEX(pc)));
             if (MakeTypeId(cx, id) != id)
                 return false;
             if (id == id_prototype(cx) || id == id___proto__(cx) || id == id_constructor(cx))
                 return false;
 
             /*
              * Ensure that if the properties named here could have a setter or
              * a permanent property in any transitive prototype, the definite
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1330,44 +1330,42 @@ js::Interpret(JSContext *cx, StackFrame 
  * To share the code for all len == 1 cases we use the specialized label with
  * code that falls through to advance_pc: .
  */
 # define END_CASE_LEN1      goto advance_pc_by_one;
 # define END_CASE_LEN2      len = 2; goto advance_pc;
 # define END_CASE_LEN3      len = 3; goto advance_pc;
 # define END_CASE_LEN4      len = 4; goto advance_pc;
 # define END_CASE_LEN5      len = 5; goto advance_pc;
+# define END_CASE_LEN6      len = 6; goto advance_pc;
 # define END_CASE_LEN7      len = 7; goto advance_pc;
 # define END_VARLEN_CASE    goto advance_pc;
 # define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
 # define END_EMPTY_CASES    goto advance_pc_by_one;
 
 #endif /* !JS_THREADED_INTERP */
 
 #define ENABLE_INTERRUPTS() (interruptEnabler.enableInterrupts())
 
 #define LOAD_ATOM(PCOFF, atom)                                                \
     JS_BEGIN_MACRO                                                            \
         JS_ASSERT((size_t)(atoms - script->atoms) <                           \
-                  (size_t)(script->natoms - GET_INDEX(regs.pc + PCOFF)));     \
-        atom = atoms[GET_INDEX(regs.pc + PCOFF)];                             \
+                  (size_t)(script->natoms - GET_UINT32_INDEX(regs.pc + PCOFF)));\
+        atom = atoms[GET_UINT32_INDEX(regs.pc + PCOFF)];                      \
     JS_END_MACRO
 
 #define LOAD_NAME(PCOFF, name)                                                \
     JS_BEGIN_MACRO                                                            \
         JSAtom *atom;                                                         \
         LOAD_ATOM((PCOFF), atom);                                             \
         name = atom->asPropertyName();                                        \
     JS_END_MACRO
 
-#define GET_FULL_INDEX(PCOFF)                                                 \
-    (atoms - script->atoms + GET_INDEX(regs.pc + (PCOFF)))
-
 #define LOAD_DOUBLE(PCOFF, dbl)                                               \
-    (dbl = script->getConst(GET_FULL_INDEX(PCOFF)).toDouble())
+    (dbl = script->getConst(GET_UINT32_INDEX(regs.pc + (PCOFF))).toDouble())
 
 #if defined(JS_METHODJIT)
     bool useMethodJIT = false;
 #endif
 
 #ifdef JS_METHODJIT
 
 #define RESET_USE_METHODJIT()                                                 \
@@ -1669,16 +1667,22 @@ ADD_EMPTY_CASE(JSOP_UNUSED9)
 ADD_EMPTY_CASE(JSOP_UNUSED10)
 ADD_EMPTY_CASE(JSOP_UNUSED11)
 ADD_EMPTY_CASE(JSOP_UNUSED12)
 ADD_EMPTY_CASE(JSOP_UNUSED13)
 ADD_EMPTY_CASE(JSOP_UNUSED14)
 ADD_EMPTY_CASE(JSOP_UNUSED15)
 ADD_EMPTY_CASE(JSOP_UNUSED16)
 ADD_EMPTY_CASE(JSOP_UNUSED17)
+ADD_EMPTY_CASE(JSOP_UNUSED18)
+ADD_EMPTY_CASE(JSOP_UNUSED19)
+ADD_EMPTY_CASE(JSOP_UNUSED20)
+ADD_EMPTY_CASE(JSOP_UNUSED21)
+ADD_EMPTY_CASE(JSOP_UNUSED22)
+ADD_EMPTY_CASE(JSOP_UNUSED23)
 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_LOOPHEAD)
 ADD_EMPTY_CASE(JSOP_LOOPENTRY)
@@ -2362,17 +2366,17 @@ BEGIN_CASE(JSOP_BITNOT)
 }
 END_CASE(JSOP_BITNOT)
 
 BEGIN_CASE(JSOP_NEG)
 {
     /*
      * When the operand is int jsval, INT32_FITS_IN_JSVAL(i) implies
      * INT32_FITS_IN_JSVAL(-i) unless i is 0 or INT32_MIN when the
-     * results, -0.0 or INT32_MAX + 1, are jsdouble values.
+     * results, -0.0 or INT32_MAX + 1, are double values.
      */
     Value ref = regs.sp[-1];
     int32_t i;
     if (ref.isInt32() && (i = ref.toInt32()) != 0 && i != INT32_MIN) {
         i = -i;
         regs.sp[-1].setInt32(i);
     } else {
         double d;
@@ -2819,35 +2823,16 @@ END_CASE(JSOP_UINT24)
 BEGIN_CASE(JSOP_INT8)
     PUSH_INT32(GET_INT8(regs.pc));
 END_CASE(JSOP_INT8)
 
 BEGIN_CASE(JSOP_INT32)
     PUSH_INT32(GET_INT32(regs.pc));
 END_CASE(JSOP_INT32)
 
-BEGIN_CASE(JSOP_INDEXBASE)
-    /*
-     * Here atoms can exceed script->natoms as we use atoms as a
-     * segment register for object literals as well.
-     */
-    atoms += GET_INDEXBASE(regs.pc);
-END_CASE(JSOP_INDEXBASE)
-
-BEGIN_CASE(JSOP_INDEXBASE1)
-BEGIN_CASE(JSOP_INDEXBASE2)
-BEGIN_CASE(JSOP_INDEXBASE3)
-    atoms += (op - JSOP_INDEXBASE1 + 1) << 16;
-END_CASE(JSOP_INDEXBASE3)
-
-BEGIN_CASE(JSOP_RESETBASE0)
-BEGIN_CASE(JSOP_RESETBASE)
-    atoms = script->atoms;
-END_CASE(JSOP_RESETBASE)
-
 BEGIN_CASE(JSOP_DOUBLE)
 {
     double dbl;
     LOAD_DOUBLE(0, dbl);
     PUSH_DOUBLE(dbl);
 }
 END_CASE(JSOP_DOUBLE)
 
@@ -2963,19 +2948,19 @@ BEGIN_CASE(JSOP_LOOKUPSWITCH)
     jsint npairs;
     npairs = (jsint) GET_UINT16(pc2);
     pc2 += UINT16_LEN;
     JS_ASSERT(npairs);  /* empty switch uses JSOP_TABLESWITCH */
 
     bool match;
 #define SEARCH_PAIRS(MATCH_CODE)                                              \
     for (;;) {                                                                \
-        Value rval = script->getConst(GET_INDEX(pc2));                        \
+        Value rval = script->getConst(GET_UINT32_INDEX(pc2));                 \
         MATCH_CODE                                                            \
-        pc2 += INDEX_LEN;                                                     \
+        pc2 += UINT32_INDEX_LEN;                                              \
         if (match)                                                            \
             break;                                                            \
         pc2 += off;                                                           \
         if (--npairs == 0) {                                                  \
             pc2 = regs.pc;                                                    \
             break;                                                            \
         }                                                                     \
     }
@@ -3065,17 +3050,17 @@ BEGIN_CASE(JSOP_CALLFCSLOT)
     PUSH_COPY(obj->toFunction()->getFlatClosureUpvar(index));
     TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
 }
 END_CASE(JSOP_GETFCSLOT)
 
 BEGIN_CASE(JSOP_DEFCONST)
 BEGIN_CASE(JSOP_DEFVAR)
 {
-    PropertyName *dn = atoms[GET_INDEX(regs.pc)]->asPropertyName();
+    PropertyName *dn = atoms[GET_UINT32_INDEX(regs.pc)]->asPropertyName();
 
     /* ES5 10.5 step 8 (with subsequent errata). */
     uintN attrs = JSPROP_ENUMERATE;
     if (!regs.fp()->isEvalFrame())
         attrs |= JSPROP_PERMANENT;
     if (op == JSOP_DEFCONST)
         attrs |= JSPROP_READONLY;
 
@@ -3268,28 +3253,30 @@ BEGIN_CASE(JSOP_LAMBDA)
                  */
                 if (op2 == JSOP_INITMETHOD) {
 #ifdef DEBUG
                     const Value &lref = regs.sp[-1];
                     JS_ASSERT(lref.isObject());
                     JSObject *obj2 = &lref.toObject();
                     JS_ASSERT(obj2->isObject());
 #endif
-                    JS_ASSERT(fun->methodAtom() == script->getAtom(GET_FULL_INDEX(JSOP_LAMBDA_LENGTH)));
+                    JS_ASSERT(fun->methodAtom() ==
+                              script->getAtom(GET_UINT32_INDEX(regs.pc + JSOP_LAMBDA_LENGTH)));
                     break;
                 }
 
                 if (op2 == JSOP_SETMETHOD) {
 #ifdef DEBUG
                     op2 = JSOp(pc2[JSOP_SETMETHOD_LENGTH]);
                     JS_ASSERT(op2 == JSOP_POP || op2 == JSOP_POPV);
 #endif
                     const Value &lref = regs.sp[-1];
                     if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) {
-                        JS_ASSERT(fun->methodAtom() == script->getAtom(GET_FULL_INDEX(JSOP_LAMBDA_LENGTH)));
+                        JS_ASSERT(fun->methodAtom() ==
+                                  script->getAtom(GET_UINT32_INDEX(regs.pc + JSOP_LAMBDA_LENGTH)));
                         break;
                     }
                 } else if (op2 == JSOP_CALL) {
                     /*
                      * Array.prototype.sort and String.prototype.replace are
                      * optimized as if they are special form. We know that they
                      * won't leak the joined function object in obj, therefore
                      * we don't need to clone that compiler-created function
@@ -3355,33 +3342,22 @@ END_CASE(JSOP_LAMBDA_FC)
 BEGIN_CASE(JSOP_CALLEE)
     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
     PUSH_COPY(argv[-2]);
 END_CASE(JSOP_CALLEE)
 
 BEGIN_CASE(JSOP_GETTER)
 BEGIN_CASE(JSOP_SETTER)
 {
-  do_getter_setter:
     JSOp op2 = JSOp(*++regs.pc);
     jsid id;
     Value rval;
     jsint i;
     JSObject *obj;
     switch (op2) {
-      case JSOP_INDEXBASE:
-        atoms += GET_INDEXBASE(regs.pc);
-        regs.pc += JSOP_INDEXBASE_LENGTH - 1;
-        goto do_getter_setter;
-      case JSOP_INDEXBASE1:
-      case JSOP_INDEXBASE2:
-      case JSOP_INDEXBASE3:
-        atoms += (op2 - JSOP_INDEXBASE1 + 1) << 16;
-        goto do_getter_setter;
-
       case JSOP_SETNAME:
       case JSOP_SETPROP:
       {
         PropertyName *name;
         LOAD_NAME(0, name);
         id = ATOM_TO_JSID(name);
         rval = regs.sp[-1];
         i = -1;
@@ -3995,50 +3971,44 @@ BEGIN_CASE(JSOP_XMLELTEXPR)
     regs.sp[-1].setString(str);
 }
 END_CASE(JSOP_XMLELTEXPR)
 
 BEGIN_CASE(JSOP_XMLCDATA)
 {
     JS_ASSERT(!script->strictModeCode);
 
-    JSAtom *atom;
-    LOAD_ATOM(0, atom);
-    JSString *str = atom;
-    JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, str);
+    JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
+    JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_TEXT, NULL, atom);
     if (!obj)
         goto error;
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_XMLCDATA)
 
 BEGIN_CASE(JSOP_XMLCOMMENT)
 {
     JS_ASSERT(!script->strictModeCode);
 
-    JSAtom *atom;
-    LOAD_ATOM(0, atom);
-    JSString *str = atom;
-    JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, str);
+    JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
+    JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_COMMENT, NULL, atom);
     if (!obj)
         goto error;
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_XMLCOMMENT)
 
 BEGIN_CASE(JSOP_XMLPI)
 {
     JS_ASSERT(!script->strictModeCode);
 
-    JSAtom *atom;
-    LOAD_ATOM(0, atom);
-    JSString *str = atom;
+    JSAtom *atom = script->getAtom(GET_UINT32_INDEX(regs.pc));
     Value rval = regs.sp[-1];
     JSString *str2 = rval.toString();
-    JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, str, str2);
+    JSObject *obj = js_NewXMLSpecialObject(cx, JSXML_CLASS_PROCESSING_INSTRUCTION, atom, str2);
     if (!obj)
         goto error;
     regs.sp[-1].setObject(*obj);
 }
 END_CASE(JSOP_XMLPI)
 
 BEGIN_CASE(JSOP_GETFUNNS)
 {
--- a/js/src/jsmath.cpp
+++ b/js/src/jsmath.cpp
@@ -114,33 +114,33 @@ Class js::MathClass = {
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
 JSBool
 js_math_abs(JSContext *cx, uintN argc, Value *vp)
 {
-    jsdouble x, z;
+    double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = fabs(x);
     vp->setNumber(z);
     return JS_TRUE;
 }
 
 static JSBool
 math_acos(JSContext *cx, uintN argc, Value *vp)
 {
-    jsdouble x, z;
+    double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
 #if defined(SOLARIS) && defined(__GNUC__)
@@ -155,17 +155,17 @@ math_acos(JSContext *cx, uintN argc, Val
     z = mathCache->lookup(acos, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 static JSBool
 math_asin(JSContext *cx, uintN argc, Value *vp)
 {
-    jsdouble x, z;
+    double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
 #if defined(SOLARIS) && defined(__GNUC__)
@@ -180,45 +180,45 @@ math_asin(JSContext *cx, uintN argc, Val
     z = mathCache->lookup(asin, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
 static JSBool
 math_atan(JSContext *cx, uintN argc, Value *vp)
 {
-    jsdouble x, z;
+    double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
     MathCache *mathCache = GetMathCache(cx);
     if (!mathCache)
         return JS_FALSE;
     z = mathCache->lookup(atan, x);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
-static inline jsdouble JS_FASTCALL
-math_atan2_kernel(jsdouble x, jsdouble y)
+static inline double JS_FASTCALL
+math_atan2_kernel(double x, double y)
 {
 #if defined(_MSC_VER)
     /*
      * MSVC's atan2 does not yield the result demanded by ECMA when both x
      * and y are infinite.
      * - The result is a multiple of pi/4.
      * - The sign of x determines the sign of the result.
      * - The sign of y determines the multiplicator, 1 or 3.
      */
     if (JSDOUBLE_IS_INFINITE(x) && JSDOUBLE_IS_INFINITE(y)) {
-        jsdouble z = js_copysign(M_PI / 4, x);
+        double z = js_copysign(M_PI / 4, x);
         if (y < 0)
             z *= 3;
         return z;
     }
 #endif
 
 #if defined(SOLARIS) && defined(__GNUC__)
     if (x == 0) {
@@ -229,59 +229,59 @@ math_atan2_kernel(jsdouble x, jsdouble y
     }
 #endif
     return atan2(x, y);
 }
 
 static JSBool
 math_atan2(JSContext *cx, uintN argc, Value *vp)
 {
-    jsdouble x, y, z;
+    double x, y, z;
 
     if (argc <= 1) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x) || !ToNumber(cx, vp[3], &y))
         return JS_FALSE;
     z = math_atan2_kernel(x, y);
     vp->setDouble(z);
     return JS_TRUE;
 }
 
-jsdouble
-js_math_ceil_impl(jsdouble x)
+double
+js_math_ceil_impl(double x)
 {
 #ifdef __APPLE__
     if (x < 0 && x > -1.0)
         return js_copysign(0, -1);
 #endif
     return ceil(x);
 }
 
 JSBool
 js_math_ceil(JSContext *cx, uintN argc, Value *vp)
 {
-    jsdouble x, z;
+    double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
     z = js_math_ceil_impl(x);
     vp->setNumber(z);
     return JS_TRUE;
 }
 
 static JSBool
 math_cos(JSContext *cx, uintN argc, Value *vp)
 {
-    jsdouble x, z;
+    double x, z;
 
     if (argc == 0) {
         vp->setDouble(js_NaN);
         return JS_TRUE;
     }
     if (!ToNumber(cx, vp[2], &x))
         return JS_FALSE;
     MathCache *mathCache = GetMathCache(cx);
@@ -304,58 +304,58 @@ math_exp_body(double d)
     }
 #endif
     return exp(d);
 }
 
 static JSBool
 math_exp(JSContext *cx, uintN argc, Value *vp)
 {
-    jsdouble x, z;
+    double x, z;