Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 18 May 2012 20:40:16 -0400
changeset 94417 642d1a36702f7fb3f34dd3a4220adf6a5a257fa9
parent 94360 9dab33fa5ff4aecbc36dfd6c09027fee897cf05e (current diff)
parent 94416 47c8f2d06763c0f3aa48790243ffe307f5edfed9 (diff)
child 94418 d55df2c9c037168968cdf072b68b524e14e7ce4d
push id22712
push userryanvm@gmail.com
push dateSat, 19 May 2012 00:52:01 +0000
treeherdermozilla-central@642d1a36702f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone15.0a1
first release with
nightly linux32
642d1a36702f / 15.0a1 / 20120519030527 / files
nightly linux64
642d1a36702f / 15.0a1 / 20120519030527 / files
nightly mac
642d1a36702f / 15.0a1 / 20120519030527 / files
nightly win32
642d1a36702f / 15.0a1 / 20120519030527 / files
nightly win64
642d1a36702f / 15.0a1 / 20120519030527 / 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 the last PGO-green inbound changeset to m-c.
browser/app/profile/extensions/uriloader@pdf.js/LICENSE
browser/app/profile/extensions/uriloader@pdf.js/README.mozilla
browser/app/profile/extensions/uriloader@pdf.js/components/PdfStreamConverter.js
browser/app/profile/extensions/uriloader@pdf.js/content/web/viewer-snippet-firefox-extension.html
browser/app/profile/extensions/uriloader@pdf.js/content/web/viewer.css
browser/app/profile/extensions/uriloader@pdf.js/content/web/viewer.html
browser/app/profile/extensions/uriloader@pdf.js/content/web/viewer.js
browser/app/profile/extensions/uriloader@pdf.js/install.rdf.in
browser/app/profile/extensions/uriloader@pdf.js/test/browser_pdfjs_main.js
testing/marionette/client/marionette/tests/unit/unit-tests.ini
testing/marionette/marionette-actors.js
tools/profiler/thread_helper.h
--- a/accessible/src/base/nsAccDocManager.cpp
+++ b/accessible/src/base/nsAccDocManager.cpp
@@ -390,18 +390,17 @@ nsAccDocManager::CreateDocOrRootAccessib
 
   // We only create root accessibles for the true root, otherwise create a
   // doc accessible.
   nsRefPtr<nsDocAccessible> docAcc = isRootDoc ?
     new RootAccessibleWrap(aDocument, rootElm, presShell) :
     new nsDocAccessibleWrap(aDocument, rootElm, presShell);
 
   // Cache the document accessible into document cache.
-  if (!docAcc || !mDocAccessibleCache.Put(aDocument, docAcc))
-    return nsnull;
+  mDocAccessibleCache.Put(aDocument, docAcc);
 
   // Initialize the document accessible.
   if (!docAcc->Init()) {
     docAcc->Shutdown();
     return nsnull;
   }
   docAcc->SetRoleMapEntry(aria::GetRoleMap(aDocument));
 
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1364,27 +1364,21 @@ nsDocAccessible::GetAccessibleOrContaine
 bool
 nsDocAccessible::BindToDocument(nsAccessible* aAccessible,
                                 nsRoleMapEntry* aRoleMapEntry)
 {
   if (!aAccessible)
     return false;
 
   // Put into DOM node cache.
-  if (aAccessible->IsPrimaryForNode() &&
-      !mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible))
-    return false;
+  if (aAccessible->IsPrimaryForNode())
+    mNodeToAccessibleMap.Put(aAccessible->GetNode(), aAccessible);
 
   // Put into unique ID cache.
-  if (!mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible)) {
-    if (aAccessible->IsPrimaryForNode())
-      mNodeToAccessibleMap.Remove(aAccessible->GetNode());
-
-    return false;
-  }
+  mAccessibleCache.Put(aAccessible->UniqueID(), aAccessible);
 
   // Initialize the accessible.
   if (!aAccessible->Init()) {
     NS_ERROR("Failed to initialize an accessible!");
 
     UnbindFromDocument(aAccessible);
     return false;
   }
@@ -1616,20 +1610,17 @@ nsDocAccessible::AddDependentIDsFor(nsAc
       const nsDependentSubstring id = iter.NextID();
       if (id.IsEmpty())
         break;
 
       AttrRelProviderArray* providers = mDependentIDsHash.Get(id);
       if (!providers) {
         providers = new AttrRelProviderArray();
         if (providers) {
-          if (!mDependentIDsHash.Put(id, providers)) {
-            delete providers;
-            providers = nsnull;
-          }
+          mDependentIDsHash.Put(id, providers);
         }
       }
 
       if (providers) {
         AttrRelProvider* provider =
           new AttrRelProvider(relAttr, aRelProvider->GetContent());
         if (provider) {
           providers->AppendElement(provider);
--- a/accessible/src/jsat/AccessFu.jsm
+++ b/accessible/src/jsat/AccessFu.jsm
@@ -34,22 +34,22 @@ var AccessFu = {
       // XXX: only supports attaching to one window now.
       throw new Error('Only one window could be attached to AccessFu');
 
     dump('AccessFu attach!! ' + Services.appinfo.OS + '\n');
     this.chromeWin = aWindow;
     this.presenters = [];
 
     this.prefsBranch = Cc['@mozilla.org/preferences-service;1']
-      .getService(Ci.nsIPrefService).getBranch('accessibility.');
-    this.prefsBranch.addObserver('accessfu', this, false);
+      .getService(Ci.nsIPrefService).getBranch('accessibility.accessfu.');
+    this.prefsBranch.addObserver('activate', this, false);
 
     let accessPref = ACCESSFU_DISABLE;
     try {
-      accessPref = this.prefsBranch.getIntPref('accessfu');
+      accessPref = this.prefsBranch.getIntPref('activate');
     } catch (x) {
     }
 
     this._processPreferences(accessPref);
   },
 
   /**
    * Start AccessFu mode, this primarily means controlling the virtual cursor
@@ -171,18 +171,18 @@ var AccessFu = {
     switch (aTopic) {
       case 'Accessibility:Settings':
         if (JSON.parse(aData).enabled)
           this._enable();
         else
           this._disable();
         break;
       case 'nsPref:changed':
-        if (aData == 'accessfu')
-          this._processPreferences(this.prefsBranch.getIntPref('accessfu'));
+        if (aData == 'activate')
+          this._processPreferences(this.prefsBranch.getIntPref('activate'));
         break;
       case 'accessible-event':
         let event;
         try {
           event = aSubject.QueryInterface(Ci.nsIAccessibleEvent);
           this._handleAccEvent(event);
         } catch (ex) {
           dump(ex);
@@ -210,22 +210,20 @@ var AccessFu = {
             // focus.
             let sel = doc.getSelection();
             sel.collapse(position.DOMNode, 0);
             Cc["@mozilla.org/focus-manager;1"]
               .getService(Ci.nsIFocusManager).moveFocus(
                 doc.defaultView, null, Ci.nsIFocusManager.MOVEFOCUS_CARET, 0);
           }
 
-          let newContext = this.getNewContext(event.oldAccessible,
-                                              pivot.position);
+          let presenterContext = new PresenterContext(pivot.position,
+                                                      event.oldAccessible);
           this.presenters.forEach(
-            function(p) {
-              p.pivotChanged(pivot.position, newContext);
-            });
+            function(p) { p.pivotChanged(presenterContext); });
           break;
         }
       case Ci.nsIAccessibleEvent.EVENT_STATE_CHANGE:
         {
           let event = aEvent.QueryInterface(Ci.nsIAccessibleStateChangeEvent);
           if (event.state == Ci.nsIAccessibleStates.STATE_CHECKED &&
               !(event.isExtraState())) {
             this.presenters.forEach(
@@ -308,18 +306,23 @@ var AccessFu = {
             }
           );
           break;
         }
       case Ci.nsIAccessibleEvent.EVENT_FOCUS:
         {
           if (this._isBrowserDoc(aEvent.accessible)) {
             // The document recieved focus, call tabSelected to present current tab.
+            let docContext = new PresenterContext(aEvent.accessible, null);
+            let cursorable = aEvent.accessible.
+              QueryInterface(Ci.nsIAccessibleCursorable);
+            let vcContext = new PresenterContext(
+              (cursorable) ? cursorable.virtualCursor.position : null, null);
             this.presenters.forEach(
-              function(p) { p.tabSelected(aEvent.accessible); });
+              function(p) { p.tabSelected(docContext, vcContext); });
           }
           break;
         }
       case Ci.nsIAccessibleEvent.EVENT_TEXT_INSERTED:
       case Ci.nsIAccessibleEvent.EVENT_TEXT_REMOVED:
       {
         if (aEvent.isFromUserInput) {
           // XXX support live regions as well.
@@ -378,51 +381,16 @@ var AccessFu = {
   _isNotChromeDoc: function _isNotChromeDoc(aDocument) {
     let location = aDocument.DOMNode.location;
     if (!location)
       return false;
 
     return location.protocol != "about:";
   },
 
-  getNewContext: function getNewContext(aOldObject, aNewObject) {
-    let newLineage = [];
-    let oldLineage = [];
-
-    let parent = aNewObject;
-    while ((parent = parent.parent))
-      newLineage.push(parent);
-
-    if (aOldObject) {
-      parent = aOldObject;
-      while ((parent = parent.parent))
-        oldLineage.push(parent);
-    }
-
-//    newLineage.reverse();
-//    oldLineage.reverse();
-
-    let i = 0;
-    let newContext = [];
-
-    while (true) {
-      let newAncestor = newLineage.pop();
-      let oldAncestor = oldLineage.pop();
-
-      if (newAncestor == undefined)
-        break;
-
-      if (newAncestor != oldAncestor)
-        newContext.push(newAncestor);
-      i++;
-    }
-
-    return newContext;
-  },
-
   // A hash of documents that don't yet have an accessible tree.
   _pendingDocuments: {},
 
   // So we don't enable/disable twice
   _enabled: false,
 
   // Observing accessibility settings
   _observingSystemSettings: false
--- a/accessible/src/jsat/Presenters.jsm
+++ b/accessible/src/jsat/Presenters.jsm
@@ -9,17 +9,18 @@ const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import('resource://gre/modules/accessibility/UtteranceGenerator.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 
 var EXPORTED_SYMBOLS = ['VisualPresenter',
                         'AndroidPresenter',
-                        'DummyAndroidPresenter'];
+                        'DummyAndroidPresenter',
+                        'PresenterContext'];
 
 /**
  * The interface for all presenter classes. A presenter could be, for example,
  * a speech output module, or a visual cursor indicator.
  */
 function Presenter() {}
 
 Presenter.prototype = {
@@ -31,21 +32,20 @@ Presenter.prototype = {
 
   /**
    * Detach function.
    */
   detach: function detach() {},
 
   /**
    * The virtual cursor's position changed.
-   * @param {nsIAccessible} aObject the new position.
-   * @param {nsIAccessible[]} aNewContext the ancestry of the new position that
-   *    is different from the old virtual cursor position.
+   * @param {PresenterContext} aContext the context object for the new pivot
+   *   position.
    */
-  pivotChanged: function pivotChanged(aObject, aNewContext) {},
+  pivotChanged: function pivotChanged(aContext) {},
 
   /**
    * An object's action has been invoked.
    * @param {nsIAccessible} aObject the object that has been invoked.
    * @param {string} aActionName the name of the action.
    */
   actionInvoked: function actionInvoked(aObject, aActionName) {},
 
@@ -73,21 +73,22 @@ Presenter.prototype = {
    *    state changed, or null if the tab has no associated document yet.
    * @param {string} aPageState the state name for the tab, valid states are:
    *    'newtab', 'loading', 'newdoc', 'loaded', 'stopped', and 'reload'.
    */
   tabStateChanged: function tabStateChanged(aDocObj, aPageState) {},
 
   /**
    * The current tab has changed.
-   * @param {nsIAccessible} aObject the document contained by the tab
-   *    accessible, or null if it is a new tab with no attached
-   *    document yet.
+   * @param {PresenterContext} aDocContext context object for tab's
+   *   document.
+   * @param {PresenterContext} aVCContext context object for tab's current
+   *   virtual cursor position.
    */
-  tabSelected: function tabSelected(aDocObj) {},
+  tabSelected: function tabSelected(aDocContext, aVCContext) {},
 
   /**
    * The viewport has changed, either a scroll, pan, zoom, or
    *    landscape/portrait toggle.
    */
   viewportChanged: function viewportChanged() {}
 };
 
@@ -134,44 +135,42 @@ VisualPresenter.prototype = {
     this.highlightBox = this.stylesheet = null;
   },
 
   viewportChanged: function VisualPresenter_viewportChanged() {
     if (this._currentObject)
       this._highlight(this._currentObject);
   },
 
-  pivotChanged: function VisualPresenter_pivotChanged(aObject, aNewContext) {
-    this._currentObject = aObject;
+  pivotChanged: function VisualPresenter_pivotChanged(aContext) {
+    this._currentObject = aContext.accessible;
 
-    if (!aObject) {
+    if (!aContext.accessible) {
       this._hide();
       return;
     }
 
     try {
-      aObject.scrollTo(Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
-      this._highlight(aObject);
+      aContext.accessible.scrollTo(
+        Ci.nsIAccessibleScrollType.SCROLL_TYPE_ANYWHERE);
+      this._highlight(aContext.accessible);
     } catch (e) {
       dump('Error getting bounds: ' + e);
       return;
     }
   },
 
-  tabSelected: function VisualPresenter_tabSelected(aDocObj) {
-    let vcPos = aDocObj ? aDocObj.QueryInterface(Ci.nsIAccessibleCursorable).
-      virtualCursor.position : null;
-
-    this.pivotChanged(vcPos);
+  tabSelected: function VisualPresenter_tabSelected(aDocContext, aVCContext) {
+    this.pivotChanged(aVCContext);
   },
 
   tabStateChanged: function VisualPresenter_tabStateChanged(aDocObj,
                                                             aPageState) {
     if (aPageState == 'newdoc')
-      this.pivotChanged(null);
+      this._hide();
   },
 
   // Internals
 
   _hide: function _hide() {
     this.highlightBox.style.display = 'none';
   },
 
@@ -229,24 +228,25 @@ AndroidPresenter.prototype = {
   // Android AccessibilityEvent type constants.
   ANDROID_VIEW_CLICKED: 0x01,
   ANDROID_VIEW_LONG_CLICKED: 0x02,
   ANDROID_VIEW_SELECTED: 0x04,
   ANDROID_VIEW_FOCUSED: 0x08,
   ANDROID_VIEW_TEXT_CHANGED: 0x10,
   ANDROID_WINDOW_STATE_CHANGED: 0x20,
 
-  pivotChanged: function AndroidPresenter_pivotChanged(aObject, aNewContext) {
+  pivotChanged: function AndroidPresenter_pivotChanged(aContext) {
     let output = [];
-    for (let i in aNewContext)
-      output.push.apply(output,
-                        UtteranceGenerator.genForObject(aNewContext[i]));
+    for (let i in aContext.newAncestry)
+      output.push.apply(
+        output, UtteranceGenerator.genForObject(aContext.newAncestry[i]));
 
     output.push.apply(output,
-                      UtteranceGenerator.genForObject(aObject, true));
+                      UtteranceGenerator.genForObject(aContext.accessible,
+                                                      true));
 
     this.sendMessageToJava({
       gecko: {
         type: 'Accessibility:Event',
         eventType: this.ANDROID_VIEW_FOCUSED,
         text: output
       }
     });
@@ -257,31 +257,19 @@ AndroidPresenter.prototype = {
       gecko: {
         type: 'Accessibility:Event',
         eventType: this.ANDROID_VIEW_CLICKED,
         text: UtteranceGenerator.genForAction(aObject, aActionName)
       }
     });
   },
 
-  tabSelected: function AndroidPresenter_tabSelected(aDocObj) {
+  tabSelected: function AndroidPresenter_tabSelected(aDocContext, aVCContext) {
     // Send a pivot change message with the full context utterance for this doc.
-    let vcDoc = aDocObj.QueryInterface(Ci.nsIAccessibleCursorable);
-    let context = [];
-
-    let parent = vcDoc.virtualCursor.position || aDocObj;
-    while ((parent = parent.parent)) {
-      context.push(parent);
-      if (parent == aDocObj)
-        break;
-    }
-
-    context.reverse();
-
-    this.pivotChanged(vcDoc.virtualCursor.position || aDocObj, context);
+    this.pivotChanged(aVCContext);
   },
 
   tabStateChanged: function AndroidPresenter_tabStateChanged(aDocObj,
                                                              aPageState) {
     let stateUtterance = UtteranceGenerator.
       genForTabStateChange(aDocObj, aPageState);
 
     if (!stateUtterance.length)
@@ -337,8 +325,67 @@ function DummyAndroidPresenter() {}
 
 DummyAndroidPresenter.prototype = {
   __proto__: AndroidPresenter.prototype,
 
   sendMessageToJava: function DummyAndroidPresenter_sendMessageToJava(aMsg) {
     dump(JSON.stringify(aMsg, null, 2) + '\n');
   }
 };
+
+/**
+ * PresenterContext: An object that generates and caches context information
+ * for a given accessible and its relationship with another accessible.
+ */
+function PresenterContext(aAccessible, aOldAccessible) {
+  this._accessible = aAccessible;
+  this._oldAccessible = aOldAccessible;
+}
+
+PresenterContext.prototype = {
+  get accessible() {
+    return this._accessible;
+  },
+
+  get oldAccessible() {
+    return this._oldAccessible;
+  },
+
+  /*
+   * This is a list of the accessible's ancestry up to the common ancestor
+   * of the accessible and the old accessible. It is useful for giving the
+   * user context as to where they are in the heirarchy.
+   */
+  get newAncestry() {
+    if (!this._newAncestry) {
+      let newLineage = [];
+      let oldLineage = [];
+
+      let parent = this._accessible;
+      while ((parent = parent.parent))
+        newLineage.push(parent);
+
+      if (this._oldAccessible) {
+        parent = this._oldAccessible;
+        while ((parent = parent.parent))
+          oldLineage.push(parent);
+      }
+
+      let i = 0;
+      this._newAncestry = [];
+
+      while (true) {
+        let newAncestor = newLineage.pop();
+        let oldAncestor = oldLineage.pop();
+
+        if (newAncestor == undefined)
+          break;
+
+        if (newAncestor != oldAncestor)
+          this._newAncestry.push(newAncestor);
+        i++;
+      }
+
+    }
+
+    return this._newAncestry;
+  }
+};
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -569,22 +569,21 @@ nsXULTreeAccessible::GetTreeItemAccessib
 
   void *key = reinterpret_cast<void*>(aRow);
   nsAccessible* cachedTreeItem = mAccessibleCache.GetWeak(key);
   if (cachedTreeItem)
     return cachedTreeItem;
 
   nsRefPtr<nsAccessible> treeItem = CreateTreeItemAccessible(aRow);
   if (treeItem) {
-    if (mAccessibleCache.Put(key, treeItem)) {
-      if (Document()->BindToDocument(treeItem, nsnull))
-        return treeItem;
+    mAccessibleCache.Put(key, treeItem);
+    if (Document()->BindToDocument(treeItem, nsnull))
+      return treeItem;
 
-      mAccessibleCache.Remove(key);
-    }
+    mAccessibleCache.Remove(key);
   }
 
   return nsnull;
 }
 
 void
 nsXULTreeAccessible::InvalidateCache(PRInt32 aRow, PRInt32 aCount)
 {
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -727,22 +727,21 @@ nsXULTreeGridRowAccessible::GetCellAcces
   nsAccessible* cachedCell = mAccessibleCache.GetWeak(key);
   if (cachedCell)
     return cachedCell;
 
   nsRefPtr<nsAccessible> cell =
     new nsXULTreeGridCellAccessibleWrap(mContent, mDoc, this, mTree,
                                         mTreeView, mRow, aColumn);
   if (cell) {
-    if (mAccessibleCache.Put(key, cell)) {
-      if (Document()->BindToDocument(cell, nsnull))
-        return cell;
+    mAccessibleCache.Put(key, cell);
+    if (Document()->BindToDocument(cell, nsnull))
+      return cell;
 
-      mAccessibleCache.Remove(key);
-    }
+    mAccessibleCache.Remove(key);
   }
 
   return nsnull;
 }
 
 void
 nsXULTreeGridRowAccessible::RowInvalidated(PRInt32 aStartColIdx,
                                            PRInt32 aEndColIdx)
--- a/browser/base/content/browser-thumbnails.js
+++ b/browser/base/content/browser-thumbnails.js
@@ -117,18 +117,18 @@ let gBrowserThumbnails = {
     this._timeouts.set(aBrowser, timeout);
   },
 
   _shouldCapture: function Thumbnails_shouldCapture(aBrowser) {
     // Capture only if it's the currently selected tab.
     if (aBrowser != gBrowser.selectedBrowser)
       return false;
 
-    // Don't capture in private browsing mode.
-    if (gPrivateBrowsingUI.privateBrowsingEnabled)
+    // Don't capture in per-window private browsing mode.
+    if (gPrivateBrowsingUI.privateWindow)
       return false;
 
     let doc = aBrowser.contentDocument;
 
     // FIXME Bug 720575 - Don't capture thumbnails for SVG or XML documents as
     //       that currently regresses Talos SVG tests.
     if (doc instanceof SVGDocument || doc instanceof XMLDocument)
       return false;
--- a/browser/config/mozconfigs/win32/nightly
+++ b/browser/config/mozconfigs/win32/nightly
@@ -19,8 +19,14 @@ mk_add_options MOZ_MAKE_FLAGS=-j1
 if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
   . $topsrcdir/build/win32/mozconfig.vs2010-win64
 else
   . $topsrcdir/build/win32/mozconfig.vs2010
 fi
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+# For known full-clobber builds on Windows (like nightlies/try), 
+# this speeds things up. IS_NIGHTLY is set by the build automation.
+if test "$IS_NIGHTLY" != ""; then 
+  ac_add_options --disable-auto-deps
+fi
--- a/browser/config/mozconfigs/win64/nightly
+++ b/browser/config/mozconfigs/win64/nightly
@@ -17,9 +17,15 @@ export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
 
+# For known full-clobber builds on Windows (like nightlies/try), 
+# this speeds things up. IS_NIGHTLY is set by the build automation.
+if test "$IS_NIGHTLY" != ""; then 
+  ac_add_options --disable-auto-deps
+fi
+
 . $topsrcdir/build/win64/mozconfig.vs2010
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-07.js
@@ -71,27 +71,28 @@ function testFrameParameters()
         "Should have the right property value for 'dArg'.");
 
       is(localNodes[5].querySelector(".info").textContent, "null",
         "Should have the right property value for 'eArg'.");
 
       is(localNodes[6].querySelector(".info").textContent, "undefined",
         "Should have the right property value for 'fArg'.");
 
-      is(localNodes[7].querySelector(".info").textContent, "1",
-        "Should have the right property value for 'a'.");
-
-      is(localNodes[8].querySelector(".info").textContent, "[object Object]",
-        "Should have the right property value for 'b'.");
+      // FIXME bug TODO: reenable
+      //is(localNodes[7].querySelector(".info").textContent, "1",
+      //  "Should have the right property value for 'a'.");
 
-      is(localNodes[9].querySelector(".info").textContent, "[object Object]",
-        "Should have the right property value for 'c'.");
+      //is(localNodes[8].querySelector(".info").textContent, "[object Object]",
+      //  "Should have the right property value for 'b'.");
 
-      is(localNodes[10].querySelector(".info").textContent, "[object Arguments]",
-        "Should have the right property value for 'arguments'.");
+      //is(localNodes[9].querySelector(".info").textContent, "[object Object]",
+      //  "Should have the right property value for 'c'.");
+
+      //is(localNodes[10].querySelector(".info").textContent, "[object Arguments]",
+      //  "Should have the right property value for 'arguments'.");
 
       resumeAndFinish();
     }}, 0);
   }, false);
 
   EventUtils.sendMouseEvent({ type: "click" },
     content.document.querySelector("button"),
     content.window);
--- a/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
+++ b/browser/devtools/debugger/test/browser_dbg_propertyview-08.js
@@ -91,27 +91,27 @@ function testFrameParameters()
         is(localNodes[9].querySelectorAll(".property > .title > .key")[1]
                         .textContent, "a",
           "Should have the right property name for 'a'.");
 
         is(localNodes[9].querySelectorAll(".property > .title > .value")[1]
                         .textContent, 1,
           "Should have the right value for 'c.a'.");
 
-        is(localNodes[10].querySelector(".info").textContent,
-          "[object Arguments]",
-          "Should have the right property value for 'arguments'.");
+        //is(localNodes[10].querySelector(".info").textContent,
+        //  "[object Arguments]",
+        //  "Should have the right property value for 'arguments'.");
 
-        is(localNodes[10].querySelector(".property > .title > .key")
-                        .textContent, "length",
-          "Should have the right property name for 'length'.");
+        //is(localNodes[10].querySelector(".property > .title > .key")
+        //                .textContent, "length",
+        //  "Should have the right property name for 'length'.");
 
-        is(localNodes[10].querySelector(".property > .title > .value")
-                        .textContent, 5,
-          "Should have the right argument length.");
+        //is(localNodes[10].querySelector(".property > .title > .value")
+        //                .textContent, 5,
+        //  "Should have the right argument length.");
 
         resumeAndFinish();
       }, 100);
     }}, 0);
   }, false);
 
   EventUtils.sendMouseEvent({ type: "click" },
     content.document.querySelector("button"),
--- a/chrome/src/nsChromeRegistry.cpp
+++ b/chrome/src/nsChromeRegistry.cpp
@@ -170,18 +170,17 @@ nsChromeRegistry::GetService()
   }
   NS_ADDREF(gChromeRegistry);
   return gChromeRegistry;
 }
 
 nsresult
 nsChromeRegistry::Init()
 {
-  if (!mOverrideTable.Init())
-    return NS_ERROR_FAILURE;
+  mOverrideTable.Init();
 
   // This initialization process is fairly complicated and may cause reentrant
   // getservice calls to resolve chrome URIs (especially locale files). We
   // don't want that, so we inform the protocol handler about our existence
   // before we are actually fully initialized.
   gChromeRegistry = this;
 
   mInitialized = true;
--- a/chrome/src/nsChromeRegistryChrome.cpp
+++ b/chrome/src/nsChromeRegistryChrome.cpp
@@ -150,19 +150,18 @@ nsChromeRegistryChrome::~nsChromeRegistr
 
 nsresult
 nsChromeRegistryChrome::Init()
 {
   nsresult rv = nsChromeRegistry::Init();
   if (NS_FAILED(rv))
     return rv;
 
-  if (!mOverlayHash.Init() ||
-      !mStyleHash.Init())
-    return NS_ERROR_FAILURE;
+  mOverlayHash.Init();
+  mStyleHash.Init();
   
   mSelectedLocale = NS_LITERAL_CSTRING("en-US");
   mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0");
 
   if (!PL_DHashTableInit(&mPackagesHash, &kTableOps,
                          nsnull, sizeof(PackageEntry), 16))
     return NS_ERROR_FAILURE;
 
--- a/chrome/src/nsChromeRegistryChrome.h
+++ b/chrome/src/nsChromeRegistryChrome.h
@@ -166,17 +166,17 @@ class nsChromeRegistryChrome : public ns
   };
 
   class OverlayListHash
   {
    public:
     OverlayListHash() { }
     ~OverlayListHash() { }
 
-    bool Init() { return mTable.Init(); }
+    void Init() { mTable.Init(); }
     void Add(nsIURI* aBase, nsIURI* aOverlay);
     void Clear() { mTable.Clear(); }
     const nsCOMArray<nsIURI>* GetArray(nsIURI* aBase);
 
    private:
     nsTHashtable<OverlayListEntry> mTable;
   };
 
--- a/chrome/src/nsChromeRegistryContent.cpp
+++ b/chrome/src/nsChromeRegistryContent.cpp
@@ -112,19 +112,17 @@ nsChromeRegistryContent::RegisterPackage
   }
 
   PackageEntry* entry = new PackageEntry;
   entry->flags = aPackage.flags;
   entry->contentBaseURI = content;
   entry->localeBaseURI = locale;
   entry->skinBaseURI = skin;
 
-  nsresult rv = mPackagesHash.Put(aPackage.package, entry);
-  if (NS_FAILED(rv))
-    return;
+  mPackagesHash.Put(aPackage.package, entry);
 }
 
 void
 nsChromeRegistryContent::RegisterResource(const ResourceMapping& aResource)
 {
   nsCOMPtr<nsIIOService> io (do_GetIOService());
   if (!io)
     return;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -543,40 +543,24 @@ nsContentUtils::InitializeEventTable() {
 #undef WINDOW_ONLY_EVENT
 #undef EVENT
     { nsnull }
   };
 
   sAtomEventTable = new nsDataHashtable<nsISupportsHashKey, EventNameMapping>;
   sStringEventTable = new nsDataHashtable<nsStringHashKey, EventNameMapping>;
   sUserDefinedEvents = new nsCOMArray<nsIAtom>(64);
-
-  if (!sAtomEventTable || !sStringEventTable || !sUserDefinedEvents ||
-      !sAtomEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1) ||
-      !sStringEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1)) {
-    delete sAtomEventTable;
-    sAtomEventTable = nsnull;
-    delete sStringEventTable;
-    sStringEventTable = nsnull;
-    delete sUserDefinedEvents;
-    sUserDefinedEvents = nsnull;
-    return false;
-  }
+  sAtomEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1);
+  sStringEventTable->Init(int(ArrayLength(eventArray) / 0.75) + 1);
 
   // Subtract one from the length because of the trailing null
   for (PRUint32 i = 0; i < ArrayLength(eventArray) - 1; ++i) {
-    if (!sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]) ||
-        !sStringEventTable->Put(Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
-                                eventArray[i])) {
-      delete sAtomEventTable;
-      sAtomEventTable = nsnull;
-      delete sStringEventTable;
-      sStringEventTable = nsnull;
-      return false;
-    }
+    sAtomEventTable->Put(eventArray[i].mAtom, eventArray[i]);
+    sStringEventTable->Put(Substring(nsDependentAtomString(eventArray[i].mAtom), 2),
+                           eventArray[i]);
   }
 
   return true;
 }
 
 void
 nsContentUtils::InitializeTouchEventTable()
 {
@@ -589,25 +573,19 @@ nsContentUtils::InitializeTouchEventTabl
       { nsGkAtoms::on##name_, _id, _type, _struct },
 #include "nsEventNameList.h"
 #undef TOUCH_EVENT
 #undef EVENT
       { nsnull }
     };
     // Subtract one from the length because of the trailing null
     for (PRUint32 i = 0; i < ArrayLength(touchEventArray) - 1; ++i) {
-      if (!sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]) ||
-          !sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
-                                  touchEventArray[i])) {
-        delete sAtomEventTable;
-        sAtomEventTable = nsnull;
-        delete sStringEventTable;
-        sStringEventTable = nsnull;
-        return;
-      }
+      sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]);
+      sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
+                             touchEventArray[i]);
     }
   }
 }
 
 static bool
 Is8bit(const nsAString& aString)
 {
   static const PRUnichar EIGHT_BIT = PRUnichar(~0x00FF);
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -108,17 +108,18 @@ public:
   ~nsPreflightCache()
   {
     Clear();
     MOZ_COUNT_DTOR(nsPreflightCache);
   }
 
   bool Initialize()
   {
-    return mTable.Init();
+    mTable.Init();
+    return true;
   }
 
   CacheEntry* GetEntry(nsIURI* aURI, nsIPrincipal* aPrincipal,
                        bool aWithCredentials, bool aCreate);
   void RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal);
 
   void Clear();
 
@@ -255,24 +256,17 @@ nsPreflightCache::GetEntry(nsIURI* aURI,
       // This will delete 'lruEntry'.
       mTable.Remove(lruEntry->mKey);
 
       NS_ASSERTION(mTable.Count() == PREFLIGHT_CACHE_SIZE - 1,
                    "Somehow tried to remove an entry that was never added!");
     }
   }
   
-  if (!mTable.Put(key, entry)) {
-    // Failed, clean up the new entry.
-    delete entry;
-
-    NS_WARNING("Failed to add entry to the CORS preflight cache!");
-    return nsnull;
-  }
-
+  mTable.Put(key, entry);
   PR_INSERT_LINK(entry, &mList);
 
   return entry;
 }
 
 void
 nsPreflightCache::RemoveEntries(nsIURI* aURI, nsIPrincipal* aPrincipal)
 {
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -60,17 +60,18 @@ nsDOMAttributeMap::nsDOMAttributeMap(Ele
 {
   // We don't add a reference to our content. If it goes away,
   // we'll be told to drop our reference
 }
 
 bool
 nsDOMAttributeMap::Init()
 {
-  return mAttributeCache.Init();
+  mAttributeCache.Init();
+  return true;
 }
 
 /**
  * Clear map pointer for attributes.
  */
 PLDHashOperator
 RemoveMapRef(nsAttrHashKey::KeyType aKey, nsRefPtr<nsDOMAttribute>& aData,
              void* aUserArg)
@@ -207,19 +208,18 @@ nsDOMAttributeMap::GetAttribute(nsINodeI
 
   nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
 
   nsDOMAttribute* node = mAttributeCache.GetWeak(attr);
   if (!node) {
     nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
     nsRefPtr<nsDOMAttribute> newAttr =
       new nsDOMAttribute(this, ni.forget(), EmptyString(), aNsAware);
-    if (newAttr && mAttributeCache.Put(attr, newAttr)) {
-      node = newAttr;
-    }
+    mAttributeCache.Put(attr, newAttr);
+    node = newAttr;
   }
 
   return node;
 }
 
 nsDOMAttribute*
 nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName, nsresult *aResult)
 {
@@ -347,18 +347,17 @@ nsDOMAttributeMap::SetNamedItemInternal(
     }
 
     nsAutoString value;
     attribute->GetValue(value);
 
     // Add the new attribute to the attribute map before updating
     // its value in the element. @see bug 364413.
     nsAttrKey attrkey(ni->NamespaceID(), ni->NameAtom());
-    rv = mAttributeCache.Put(attrkey, attribute);
-    NS_ENSURE_SUCCESS(rv, rv);
+    mAttributeCache.Put(attrkey, attribute);
     iAttribute->SetMap(this);
 
     rv = mContent->SetAttr(ni->NamespaceID(), ni->NameAtom(),
                            ni->GetPrefixAtom(), value, true);
     if (NS_FAILED(rv)) {
       DropAttribute(ni->NamespaceID(), ni->NameAtom());
     }
   }
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -345,17 +345,17 @@ nsDOMFileReader::DoOnDataAvailable(nsIRe
                                    PRUint32 aCount)
 {
   if (mDataFormat == FILE_AS_BINARY) {
     //Continuously update our binary string as data comes in
     NS_ASSERTION(mResult.Length() == aOffset,
                  "unexpected mResult length");
     PRUint32 oldLen = mResult.Length();
     PRUnichar *buf = nsnull;
-    mResult.GetMutableData(&buf, oldLen + aCount);
+    mResult.GetMutableData(&buf, oldLen + aCount, fallible_t());
     NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
 
     PRUint32 bytesRead = 0;
     aInputStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount,
                                &bytesRead);
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
   }
   else if (mDataFormat == FILE_AS_ARRAYBUFFER) {
@@ -558,18 +558,18 @@ nsDOMFileReader::ConvertStream(const cha
   nsCOMPtr<nsIUnicodeDecoder> unicodeDecoder;
   rv = charsetConverter->GetUnicodeDecoder(aCharset, getter_AddRefs(unicodeDecoder));
   NS_ENSURE_SUCCESS(rv, rv);
 
   PRInt32 destLength;
   rv = unicodeDecoder->GetMaxLength(aFileData, aDataLen, &destLength);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  aResult.SetLength(destLength);  //Make sure we have enough space for the conversion
-  destLength = aResult.Length();
+  if (!aResult.SetLength(destLength, fallible_t()))
+    return NS_ERROR_OUT_OF_MEMORY;
 
   PRInt32 srcLength = aDataLen;
   rv = unicodeDecoder->Convert(aFileData, &srcLength, aResult.BeginWriting(), &destLength);
   aResult.SetLength(destLength); //Trim down to the correct size
 
   return rv;
 }
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -721,19 +721,17 @@ nsExternalResourceMap::RequestResource(n
   mPendingLoads.Get(clone, getter_AddRefs(load));
   if (load) {
     load.forget(aPendingLoad);
     return nsnull;
   }
 
   load = new PendingLoad(aDisplayDocument);
 
-  if (!mPendingLoads.Put(clone, load)) {
-    return nsnull;
-  }
+  mPendingLoads.Put(clone, load);
 
   if (NS_FAILED(load->StartLoad(clone, aRequestingNode))) {
     // Make sure we don't thrash things by trying this load again, since
     // chances are it failed for good reasons (security check, etc).
     AddExternalResource(clone, nsnull, nsnull, aDisplayDocument);
   } else {
     load.forget(aPendingLoad);
   }
@@ -915,32 +913,24 @@ nsExternalResourceMap::AddExternalResour
     if (NS_FAILED(rv)) {
       doc = nsnull;
       aViewer = nsnull;
       aLoadGroup = nsnull;
     }
   }
 
   ExternalResource* newResource = new ExternalResource();
-  if (newResource && !mMap.Put(aURI, newResource)) {
-    delete newResource;
-    newResource = nsnull;
-    if (NS_SUCCEEDED(rv)) {
-      rv = NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-
-  if (newResource) {
-    newResource->mDocument = doc;
-    newResource->mViewer = aViewer;
-    newResource->mLoadGroup = aLoadGroup;
-    if (doc) {
-      TransferZoomLevels(aDisplayDocument, doc);
-      TransferShowingState(aDisplayDocument, doc);
-    }
+  mMap.Put(aURI, newResource);
+
+  newResource->mDocument = doc;
+  newResource->mViewer = aViewer;
+  newResource->mLoadGroup = aLoadGroup;
+  if (doc) {
+    TransferZoomLevels(aDisplayDocument, doc);
+    TransferShowingState(aDisplayDocument, doc);
   }
 
   const nsTArray< nsCOMPtr<nsIObserver> > & obs = load->Observers();
   for (PRUint32 i = 0; i < obs.Length(); ++i) {
     obs[i]->Observe(doc, "external-resource-document-created", nsnull);
   }
 
   return rv;
@@ -1995,17 +1985,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 nsresult
 nsDocument::Init()
 {
   if (mCSSLoader || mNodeInfoManager || mScriptLoader) {
     return NS_ERROR_ALREADY_INITIALIZED;
   }
 
   mIdentifierMap.Init();
-  (void)mStyledLinks.Init();
+  mStyledLinks.Init();
   mRadioGroups.Init();
 
   // Force initialization.
   nsINode::nsSlots* slots = GetSlots();
   NS_ENSURE_TRUE(slots,NS_ERROR_OUT_OF_MEMORY);
 
   // Prepend self as mutation-observer whether we need it or not (some
   // subclasses currently do, other don't). This is because the code in
@@ -2036,20 +2026,18 @@ nsDocument::Init()
   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
                     "Bad NodeType in aNodeInfo");
 
   NS_ASSERTION(OwnerDoc() == this, "Our nodeinfo is busted!");
 
   mScriptLoader = new nsScriptLoader(this);
   NS_ENSURE_TRUE(mScriptLoader, NS_ERROR_OUT_OF_MEMORY);
 
-  if (!mImageTracker.Init() ||
-      !mPlugins.Init()) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
+  mImageTracker.Init();
+  mPlugins.Init();
 
   return NS_OK;
 }
 
 void 
 nsIDocument::DeleteAllProperties()
 {
   for (PRUint32 i = 0; i < GetPropertyTableCount(); ++i) {
@@ -5350,19 +5338,17 @@ nsDocument::GetBoxObjectFor(nsIDOMElemen
                                     nsContentUtils::eDOM_PROPERTIES,
                                     "UseOfGetBoxObjectForWarning");
   }
 
   *aResult = nsnull;
 
   if (!mBoxObjectTable) {
     mBoxObjectTable = new nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject>;
-    if (mBoxObjectTable && !mBoxObjectTable->Init(12)) {
-      mBoxObjectTable = nsnull;
-    }
+    mBoxObjectTable->Init(12);
   } else {
     // Want to use Get(content, aResult); but it's the wrong type
     *aResult = mBoxObjectTable->GetWeak(content);
     if (*aResult) {
       NS_ADDREF(*aResult);
       return NS_OK;
     }
   }
@@ -6497,17 +6483,17 @@ nsDocument::GetRadioGroup(const nsAStrin
   }
 
   nsRadioGroupStruct* radioGroup;
   if (mRadioGroups.Get(tmKey, &radioGroup)) {
     return radioGroup;
   }
 
   nsAutoPtr<nsRadioGroupStruct> newRadioGroup(new nsRadioGroupStruct());
-  NS_ENSURE_TRUE(mRadioGroups.Put(tmKey, newRadioGroup), nsnull);
+  mRadioGroups.Put(tmKey, newRadioGroup);
 
   return newRadioGroup.forget();
 }
 
 NS_IMETHODIMP
 nsDocument::SetCurrentRadioButton(const nsAString& aName,
                                   nsIDOMHTMLInputElement* aRadio)
 {
@@ -8280,19 +8266,17 @@ nsDocument::AddImage(imgIRequest* aImage
 {
   NS_ENSURE_ARG_POINTER(aImage);
 
   // See if the image is already in the hashtable. If it is, get the old count.
   PRUint32 oldCount = 0;
   mImageTracker.Get(aImage, &oldCount);
 
   // Put the image in the hashtable, with the proper count.
-  bool success = mImageTracker.Put(aImage, oldCount + 1);
-  if (!success)
-    return NS_ERROR_OUT_OF_MEMORY;
+  mImageTracker.Put(aImage, oldCount + 1);
 
   nsresult rv = NS_OK;
 
   // If this is the first insertion and we're locking images, lock this image
   // too.
   if (oldCount == 0 && mLockingImages) {
     rv = aImage->LockImage();
     if (NS_SUCCEEDED(rv))
--- a/content/base/src/nsNameSpaceManager.cpp
+++ b/content/base/src/nsNameSpaceManager.cpp
@@ -135,19 +135,19 @@ private:
 };
 
 static NameSpaceManagerImpl* sNameSpaceManager = nsnull;
 
 NS_IMPL_ISUPPORTS1(NameSpaceManagerImpl, nsINameSpaceManager)
 
 nsresult NameSpaceManagerImpl::Init()
 {
-  nsresult rv = mURIToIDTable.Init(32);
-  NS_ENSURE_SUCCESS(rv, rv);
+  mURIToIDTable.Init(32);
 
+  nsresult rv;
 #define REGISTER_NAMESPACE(uri, id) \
   rv = AddNameSpace(NS_LITERAL_STRING(uri), id); \
   NS_ENSURE_SUCCESS(rv, rv)
 
   // Need to be ordered according to ID.
   REGISTER_NAMESPACE(kXMLNSNameSpaceURI, kNameSpaceID_XMLNS);
   REGISTER_NAMESPACE(kXMLNameSpaceURI, kNameSpaceID_XML);
   REGISTER_NAMESPACE(kXHTMLNameSpaceURI, kNameSpaceID_XHTML);
@@ -283,21 +283,17 @@ nsresult NameSpaceManagerImpl::AddNameSp
                "BAD! AddNameSpace not called in right order!");
 
   nsString* uri = new nsString(aURI);
   if (!uri || !mURIArray.AppendElement(uri)) {
     delete uri;
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  if (!mURIToIDTable.Put(uri, aNameSpaceID)) {
-    mURIArray.RemoveElementAt(aNameSpaceID - 1);
-
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
+  mURIToIDTable.Put(uri, aNameSpaceID);
 
   return NS_OK;
 }
 
 nsresult
 NS_GetNameSpaceManager(nsINameSpaceManager** aInstancePtrResult)
 {
   NS_ENSURE_ARG_POINTER(aInstancePtrResult);
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -574,16 +574,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug650386_redirect_303.html \
 		test_bug650386_redirect_307.html \
 		file_bug650386_content.sjs \
 		file_bug650386_report.sjs \
 		test_bug719533.html \
 		test_bug737087.html \
 		test_bug433662.html \
 		test_bug749367.html \
+		test_bug753278.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug753278.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=753278
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 753278</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="runTest();">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=753278">Mozilla Bug 753278</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe></iframe>  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 753278 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var f = document.getElementsByTagName("iframe")[0];
+
+function runTest() {
+  f.contentDocument.open();
+  f.contentDocument.write('<script>window.location = "data:text/html;charset=utf-8,\\u003Cscript>parent.pass();\\u003C/script>"; document.close(); document.open(); document.write("\\u003Cscript>parent.fail();\\u003C/script>"); document.close();\u003c/script>');
+  f.contentDocument.close();
+}
+
+function pass() {
+  ok(true, "window.location took precedence");
+  SimpleTest.finish();
+}
+
+function fail() {
+  ok(false, "window.location should have taken precedence");
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/events/src/nsDOMDataContainerEvent.cpp
+++ b/content/events/src/nsDOMDataContainerEvent.cpp
@@ -84,17 +84,18 @@ nsDOMDataContainerEvent::GetData(const n
 NS_IMETHODIMP
 nsDOMDataContainerEvent::SetData(const nsAString& aKey, nsIVariant *aData)
 {
   NS_ENSURE_ARG(aData);
 
   // Make sure this event isn't already being dispatched.
   NS_ENSURE_STATE(!(NS_IS_EVENT_IN_DISPATCH(mEvent)));
   NS_ENSURE_STATE(mData.IsInitialized());
-  return mData.Put(aKey, aData) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+  mData.Put(aKey, aData);
+  return NS_OK;
 }
 
 nsresult
 NS_NewDOMDataContainerEvent(nsIDOMEvent** aInstancePtrResult,
                    nsPresContext* aPresContext,
                    nsEvent* aEvent)
 {
   nsDOMDataContainerEvent* it =
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -284,22 +284,19 @@ nsHTMLFormElement::Init()
   nsresult rv = mControls->Init();
   
   if (NS_FAILED(rv))
   {
     mControls = nsnull;
     return rv;
   }
   
-  NS_ENSURE_TRUE(mSelectedRadioButtons.Init(4),
-                 NS_ERROR_OUT_OF_MEMORY);
-  NS_ENSURE_TRUE(mRequiredRadioButtonCounts.Init(4),
-                 NS_ERROR_OUT_OF_MEMORY);
-  NS_ENSURE_TRUE(mValueMissingRadioGroups.Init(4),
-                 NS_ERROR_OUT_OF_MEMORY);
+  mSelectedRadioButtons.Init(4);
+  mRequiredRadioButtonCounts.Init(4);
+  mValueMissingRadioGroups.Init(4);
 
   return NS_OK;
 }
 
 
 // nsISupports
 
 static PLDHashOperator
@@ -1889,18 +1886,17 @@ nsHTMLFormElement::IndexOfControl(nsIFor
   PRInt32 index = nsnull;
   return mControls->IndexOfControl(aControl, &index) == NS_OK ? index : nsnull;
 }
 
 NS_IMETHODIMP
 nsHTMLFormElement::SetCurrentRadioButton(const nsAString& aName,
                                          nsIDOMHTMLInputElement* aRadio)
 {
-  NS_ENSURE_TRUE(mSelectedRadioButtons.Put(aName, aRadio),
-                 NS_ERROR_OUT_OF_MEMORY);
+  mSelectedRadioButtons.Put(aName, aRadio);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLFormElement::GetCurrentRadioButton(const nsAString& aName,
                                          nsIDOMHTMLInputElement** aRadio)
 {
@@ -2139,20 +2135,17 @@ nsFormControlList::nsFormControlList(nsH
 nsFormControlList::~nsFormControlList()
 {
   mForm = nsnull;
   Clear();
 }
 
 nsresult nsFormControlList::Init()
 {
-  NS_ENSURE_TRUE(
-    mNameLookupTable.Init(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE),
-    NS_ERROR_OUT_OF_MEMORY);
-
+  mNameLookupTable.Init(NS_FORM_CONTROL_LIST_HASHTABLE_SIZE);
   return NS_OK;
 }
 
 void
 nsFormControlList::DropFormReference()
 {
   mForm = nsnull;
   Clear();
@@ -2305,19 +2298,17 @@ nsFormControlList::AddElementToTable(nsG
     return NS_OK;
   }
 
   nsCOMPtr<nsISupports> supports;
   mNameLookupTable.Get(aName, getter_AddRefs(supports));
 
   if (!supports) {
     // No entry found, add the form control
-    NS_ENSURE_TRUE(mNameLookupTable.Put(aName,
-                                        NS_ISUPPORTS_CAST(nsIContent*, aChild)),
-                   NS_ERROR_FAILURE);
+    mNameLookupTable.Put(aName, NS_ISUPPORTS_CAST(nsIContent*, aChild));
   } else {
     // Found something in the hash, check its type
     nsCOMPtr<nsIContent> content = do_QueryInterface(supports);
 
     if (content) {
       // Check if the new content is the same as the one we found in the
       // hash, if it is then we leave it in the hash as it is, this will
       // happen if a form control has both a name and an id with the same
@@ -2340,18 +2331,17 @@ nsFormControlList::AddElementToTable(nsG
 
       list->AppendElement(newFirst ? aChild : content);
       list->AppendElement(newFirst ? content : aChild);
 
 
       nsCOMPtr<nsISupports> listSupports = do_QueryObject(list);
 
       // Replace the element with the list.
-      NS_ENSURE_TRUE(mNameLookupTable.Put(aName, listSupports),
-                     NS_ERROR_FAILURE);
+      mNameLookupTable.Put(aName, listSupports);
     } else {
       // There's already a list in the hash, add the child to the list
       nsCOMPtr<nsIDOMNodeList> nodeList = do_QueryInterface(supports);
       NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
 
       // Upcast, uggly, but it works!
       nsSimpleContentList *list =
         static_cast<nsSimpleContentList*>(nodeList.get());
@@ -2450,17 +2440,17 @@ nsFormControlList::RemoveElementFromTabl
     // If the list is empty we remove if from our hash, this shouldn't
     // happen tho
     mNameLookupTable.Remove(aName);
   } else if (length == 1) {
     // Only one element left, replace the list in the hash with the
     // single element.
     nsIContent* node = list->GetNodeAt(0);
     if (node) {
-      NS_ENSURE_TRUE(mNameLookupTable.Put(aName, node),NS_ERROR_FAILURE);
+      mNameLookupTable.Put(aName, node);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
 nsFormControlList::GetSortedControls(nsTArray<nsGenericHTMLFormElement*>& aControls) const
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1349,17 +1349,26 @@ nsHTMLDocument::Open(const nsAString& aC
     NS_ParseContentType(NS_ConvertUTF16toUTF8(type), actualType, dummy);
     if (!actualType.EqualsLiteral("text/html") &&
         !type.EqualsLiteral("replace")) {
       contentType.AssignLiteral("text/plain");
     }
   }
 
   // If we already have a parser we ignore the document.open call.
-  if (mParser) {
+  if (mParser || mParserAborted) {
+    // The WHATWG spec says: "If the document has an active parser that isn't
+    // a script-created parser, and the insertion point associated with that
+    // parser's input stream is not undefined (that is, it does point to
+    // somewhere in the input stream), then the method does nothing. Abort
+    // these steps and return the Document object on which the method was
+    // invoked."
+    // Note that aborting a parser leaves the parser "active" with its
+    // insertion point "not undefined". We track this using mParserAborted,
+    // because aborting a parser nulls out mParser.
     return NS_OK;
   }
 
   // No calling document.open() without a script global object
   if (!mScriptGlobalObject) {
     return NS_OK;
   }
 
--- a/content/media/gstreamer/nsGStreamerReader.h
+++ b/content/media/gstreamer/nsGStreamerReader.h
@@ -29,16 +29,20 @@ public:
                                 PRInt64 aTimeThreshold);
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime,
                         PRInt64 aStartTime,
                         PRInt64 aEndTime,
                         PRInt64 aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
 
+  virtual bool IsSeekableInBufferedRanges() {
+    return true;
+  }
+
   virtual bool HasAudio() {
     return mInfo.mHasAudio;
   }
 
   virtual bool HasVideo() {
     return mInfo.mHasVideo;
   }
 
--- a/content/media/nsBuiltinDecoder.cpp
+++ b/content/media/nsBuiltinDecoder.cpp
@@ -980,17 +980,23 @@ nsresult nsBuiltinDecoder::GetSeekable(n
 
   if (IsSeekable()) {
     double end = IsInfinite() ? std::numeric_limits<double>::infinity()
                               : initialTime + GetDuration();
     aSeekable->Add(initialTime, end);
     return NS_OK;
   }
 
-  return GetBuffered(aSeekable);
+  if (mDecoderStateMachine->IsSeekableInBufferedRanges()) {
+    return GetBuffered(aSeekable);
+  } else {
+    // The stream is not seekable using only buffered ranges, and is not
+    // seekable. Don't allow seeking (return no ranges in |seekable|).
+    return NS_OK;
+  }
 }
 
 void nsBuiltinDecoder::SetEndTime(double aTime)
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (mDecoderStateMachine) {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     mDecoderStateMachine->SetFragmentEndTime(static_cast<PRInt64>(aTime * USECS_PER_S));
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -326,16 +326,19 @@ public:
   // and an invalidate of the frame being dispatched asynchronously if
   // there is no such event currently queued.
   // Only called on the decoder thread. Must be called with
   // the decode monitor held.
   virtual void UpdatePlaybackPosition(PRInt64 aTime) = 0;
 
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered) = 0;
 
+  // Return true if the media is seekable using only buffered ranges.
+  virtual bool IsSeekableInBufferedRanges() = 0;
+
   virtual PRInt64 VideoQueueMemoryInUse() = 0;
   virtual PRInt64 AudioQueueMemoryInUse() = 0;
 
   virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset) = 0;
 
   // Causes the state machine to switch to buffering state, and to
   // immediately stop playback and buffer downloaded data. Must be called
   // with the decode monitor held. Called on the state machine thread and
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -475,16 +475,19 @@ public:
 
   // Populates aBuffered with the time ranges which are buffered. aStartTime
   // must be the presentation time of the first frame in the media, e.g.
   // the media time corresponding to playback time/position 0. This function
   // should only be called on the main thread.
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered,
                                PRInt64 aStartTime) = 0;
 
+  // True if we can seek using only buffered ranges. This is backend dependant.
+  virtual bool IsSeekableInBufferedRanges() = 0;
+
   class VideoQueueMemoryFunctor : public nsDequeFunctor {
   public:
     VideoQueueMemoryFunctor() : mResult(0) {}
 
     virtual void* operator()(void* anObject) {
       const VideoData* v = static_cast<const VideoData*>(anObject);
       if (!v->mImage) {
         return nsnull;
--- a/content/media/nsBuiltinDecoderStateMachine.h
+++ b/content/media/nsBuiltinDecoderStateMachine.h
@@ -238,16 +238,23 @@ public:
     return mEndTime;
   }
 
   bool IsSeekable() {
     mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
     return mSeekable;
   }
 
+  bool IsSeekableInBufferedRanges() {
+    if (mReader) {
+      return mReader->IsSeekableInBufferedRanges();
+    }
+    return false;
+  }
+
   // Sets the current frame buffer length for the MozAudioAvailable event.
   // Accessed on the main and state machine threads.
   virtual void SetFrameBufferLength(PRUint32 aLength);
 
   // Returns the shared state machine thread.
   static nsIThread* GetStateMachineThread();
 
   // Schedules the shared state machine thread to run the state machine.
--- a/content/media/ogg/nsOggCodecState.cpp
+++ b/content/media/ogg/nsOggCodecState.cpp
@@ -1258,22 +1258,17 @@ bool nsSkeletonState::DecodeHeader(ogg_p
     }
 
     // Extract the segment length.
     mLength = LEInt64(aPacket->packet + SKELETON_FILE_LENGTH_OFFSET);
 
     LOG(PR_LOG_DEBUG, ("Skeleton segment length: %lld", mLength));
 
     // Initialize the serianlno-to-index map.
-    bool init = mIndex.Init();
-    if (!init) {
-      NS_WARNING("Failed to initialize Ogg skeleton serialno-to-index map");
-      mActive = false;
-      return mDoneReadingHeaders = true;
-    }
+    mIndex.Init();
     mActive = true;
   } else if (IsSkeletonIndex(aPacket) && mVersion >= SKELETON_VERSION(4,0)) {
     if (!DecodeIndex(aPacket)) {
       // Failed to parse index, or invalid/hostile index. DecodeIndex() will
       // have deactivated the track.
       return mDoneReadingHeaders = true;
     }
 
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -121,21 +121,17 @@ nsOggReader::nsOggReader(nsBuiltinDecode
 
 nsOggReader::~nsOggReader()
 {
   ogg_sync_clear(&mOggState);
   MOZ_COUNT_DTOR(nsOggReader);
 }
 
 nsresult nsOggReader::Init(nsBuiltinDecoderReader* aCloneDonor) {
-  bool init = mCodecStates.Init();
-  NS_ASSERTION(init, "Failed to initialize mCodecStates");
-  if (!init) {
-    return NS_ERROR_FAILURE;
-  }
+  mCodecStates.Init();
   int ret = ogg_sync_init(&mOggState);
   NS_ENSURE_TRUE(ret == 0, NS_ERROR_FAILURE);
   return NS_OK;
 }
 
 nsresult nsOggReader::ResetDecode()
 {
   NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
@@ -200,18 +196,17 @@ nsresult nsOggReader::ReadMetadata(nsVid
       // can follow in this Ogg segment, so there will be no other bitstreams
       // in the Ogg (unless it's invalid).
       readAllBOS = true;
     } else if (!mCodecStates.Get(serial, nsnull)) {
       // We've not encountered a stream with this serial number before. Create
       // an nsOggCodecState to demux it, and map that to the nsOggCodecState
       // in mCodecStates.
       codecState = nsOggCodecState::Create(&page);
-      DebugOnly<bool> r = mCodecStates.Put(serial, codecState);
-      NS_ASSERTION(r, "Failed to insert into mCodecStates");
+      mCodecStates.Put(serial, codecState);
       bitstreams.AppendElement(codecState);
       mKnownStreams.AppendElement(serial);
       if (codecState &&
           codecState->GetType() == nsOggCodecState::TYPE_VORBIS &&
           !mVorbisState)
       {
         // First Vorbis bitstream, we'll play this one. Subsequent Vorbis
         // bitstreams will be ignored.
--- a/content/media/ogg/nsOggReader.h
+++ b/content/media/ogg/nsOggReader.h
@@ -79,16 +79,21 @@ public:
   virtual bool HasVideo() {
     return mTheoraState != 0 && mTheoraState->mActive;
   }
 
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
 
+  // We use bisection to seek in buffered range.
+  virtual bool IsSeekableInBufferedRanges() {
+    return true;
+  }
+
 private:
 
   bool HasSkeleton() {
     return mSkeletonState != 0 && mSkeletonState->mActive;
   }
 
   // Seeks to the keyframe preceeding the target time using available
   // keyframe indexes.
--- a/content/media/raw/nsRawReader.h
+++ b/content/media/raw/nsRawReader.h
@@ -65,16 +65,21 @@ public:
   {
     return true;
   }
 
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
 
+  // By seeking in the media resource, it is possible to seek.
+  bool IsSeekableInBufferedRanges() {
+    return true;
+  }
+
 private:
   bool ReadFromResource(MediaResource *aResource, PRUint8 *aBuf, PRUint32 aLength);
 
   nsRawVideoHeader mMetadata;
   PRUint32 mCurrentFrame;
   double mFrameRate;
   PRUint32 mFrameSize;
   nsIntRect mPicture;
--- a/content/media/wave/nsWaveReader.h
+++ b/content/media/wave/nsWaveReader.h
@@ -63,16 +63,21 @@ public:
   {
     return false;
   }
 
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
 
+  // To seek in a buffered range, we just have to seek the stream.
+  virtual bool IsSeekableInBufferedRanges() {
+    return true;
+  }
+
 private:
   bool ReadAll(char* aBuf, PRInt64 aSize, PRInt64* aBytesRead = nsnull);
   bool LoadRIFFChunk();
   bool ScanForwardUntil(PRUint32 aWantedChunk, PRUint32* aChunkSize);
   bool LoadFormatChunk();
   bool FindDataOffset();
 
   // Returns the number of seconds that aBytes represents based on the
--- a/content/media/webm/nsWebMReader.h
+++ b/content/media/webm/nsWebMReader.h
@@ -151,16 +151,21 @@ public:
   }
 
   virtual bool HasVideo()
   {
     NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread.");
     return mHasVideo;
   }
 
+  // Bug 575140, cannot seek in webm if no cue is present.
+  bool IsSeekableInBufferedRanges() {
+    return false;
+  }
+
   virtual nsresult ReadMetadata(nsVideoInfo* aInfo);
   virtual nsresult Seek(PRInt64 aTime, PRInt64 aStartTime, PRInt64 aEndTime, PRInt64 aCurrentTime);
   virtual nsresult GetBuffered(nsTimeRanges* aBuffered, PRInt64 aStartTime);
   virtual void NotifyDataArrived(const char* aBuffer, PRUint32 aLength, PRInt64 aOffset);
 
 private:
   // Value passed to NextPacket to determine if we are reading a video or an
   // audio packet.
--- a/content/svg/content/src/nsSVGAttrTearoffTable.h
+++ b/content/svg/content/src/nsSVGAttrTearoffTable.h
@@ -99,21 +99,17 @@ nsSVGAttrTearoffTable<SimpleType, Tearof
 
   // We shouldn't be adding a tear-off if there already is one. If that happens,
   // something is wrong.
   if (mTable.Get(aSimple, nsnull)) {
     NS_ABORT_IF_FALSE(false, "There is already a tear-off for this object.");
     return;
   }
 
-#ifdef DEBUG
-  bool result =
-#endif
-    mTable.Put(aSimple, aTearoff);
-  NS_ABORT_IF_FALSE(result, "Out of memory.");
+  mTable.Put(aSimple, aTearoff);
 }
 
 template<class SimpleType, class TearoffType>
 void
 nsSVGAttrTearoffTable<SimpleType, TearoffType>::RemoveTearoff(
     SimpleType* aSimple)
 {
   if (!mTable.IsInitialized()) {
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -549,18 +549,17 @@ nsBindingManager::GetBinding(nsIContent*
 
   return nsnull;
 }
 
 nsresult
 nsBindingManager::SetBinding(nsIContent* aContent, nsXBLBinding* aBinding)
 {
   if (!mBindingTable.IsInitialized()) {
-    if (!mBindingTable.Init())
-      return NS_ERROR_OUT_OF_MEMORY;
+    mBindingTable.Init();
   }
 
   // After this point, aBinding will be the most-derived binding for aContent.
   // If we already have a binding for aContent in our table, make sure to
   // remove it from the attached stack.  Otherwise we might end up firing its
   // constructor twice (if aBinding inherits from it) or firing its constructor
   // after aContent has been deleted (if aBinding is null and the content node
   // dies before we process mAttachedStack).
@@ -579,36 +578,34 @@ nsBindingManager::SetBinding(nsIContent*
     // Don't remove items here as that could mess up an executing
     // ProcessAttachedQueue
     PRUint32 index = mAttachedStack.IndexOf(oldBinding);
     if (index != mAttachedStack.NoIndex) {
       mAttachedStack[index] = nsnull;
     }
   }
   
-  bool result = true;
-
   if (aBinding) {
     aContent->SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
-    result = mBindingTable.Put(aContent, aBinding);
+    mBindingTable.Put(aContent, aBinding);
   } else {
     mBindingTable.Remove(aContent);
 
     // The death of the bindings means the death of the JS wrapper,
     // and the flushing of our explicit and anonymous insertion point
     // lists.
     SetWrappedJS(aContent, nsnull);
     SetContentListFor(aContent, nsnull);
     SetAnonymousNodesFor(aContent, nsnull);
     if (oldBinding) {
       oldBinding->SetBoundElement(nsnull);
     }
   }
 
-  return result ? NS_OK : NS_ERROR_FAILURE;
+  return NS_OK;
 }
 
 nsIContent*
 nsBindingManager::GetInsertionParent(nsIContent* aContent)
 { 
   if (mInsertionParentTable.ops) {
     return static_cast<nsIContent*>
                       (LookupObject(mInsertionParentTable, aContent));
@@ -1096,22 +1093,21 @@ nsBindingManager::ExecuteDetachedHandler
   }
 }
 
 nsresult
 nsBindingManager::PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo)
 {
   NS_PRECONDITION(aDocumentInfo, "Must have a non-null documentinfo!");
   
-  NS_ENSURE_TRUE(mDocumentTable.IsInitialized() || mDocumentTable.Init(16),
-                 NS_ERROR_OUT_OF_MEMORY);
+  if (!mDocumentTable.IsInitialized())
+    mDocumentTable.Init(16);
 
-  NS_ENSURE_TRUE(mDocumentTable.Put(aDocumentInfo->DocumentURI(),
-                                    aDocumentInfo),
-                 NS_ERROR_OUT_OF_MEMORY);
+  mDocumentTable.Put(aDocumentInfo->DocumentURI(),
+                     aDocumentInfo);
 
   return NS_OK;
 }
 
 void
 nsBindingManager::RemoveXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo)
 {
   if (mDocumentTable.IsInitialized()) {
@@ -1128,21 +1124,20 @@ nsBindingManager::GetXBLDocumentInfo(nsI
   return mDocumentTable.GetWeak(aURL);
 }
 
 nsresult
 nsBindingManager::PutLoadingDocListener(nsIURI* aURL, nsIStreamListener* aListener)
 {
   NS_PRECONDITION(aListener, "Must have a non-null listener!");
   
-  NS_ENSURE_TRUE(mLoadingDocTable.IsInitialized() || mLoadingDocTable.Init(16),
-                 NS_ERROR_OUT_OF_MEMORY);
+  if (!mLoadingDocTable.IsInitialized())
+    mLoadingDocTable.Init(16);
   
-  NS_ENSURE_TRUE(mLoadingDocTable.Put(aURL, aListener),
-                 NS_ERROR_OUT_OF_MEMORY);
+  mLoadingDocTable.Put(aURL, aListener);
 
   return NS_OK;
 }
 
 nsIStreamListener*
 nsBindingManager::GetLoadingDocListener(nsIURI* aURL)
 {
   if (!mLoadingDocTable.IsInitialized())
@@ -1350,18 +1345,19 @@ static PLDHashOperator
 EnumRuleProcessors(nsISupports *aKey, nsXBLBinding *aBinding, void* aClosure)
 {
   RuleProcessorSet *set = static_cast<RuleProcessorSet*>(aClosure);
   for (nsXBLBinding *binding = aBinding; binding;
        binding = binding->GetBaseBinding()) {
     nsIStyleRuleProcessor *ruleProc =
       binding->PrototypeBinding()->GetRuleProcessor();
     if (ruleProc) {
-      if (!set->IsInitialized() && !set->Init(16))
-        return PL_DHASH_STOP;
+      if (!set->IsInitialized()) {
+        set->Init(16);
+      }
       set->PutEntry(ruleProc);
     }
   }
   return PL_DHASH_NEXT;
 }
 
 struct WalkAllRulesData {
   nsIStyleRuleProcessor::EnumFunc mFunc;
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -1433,32 +1433,24 @@ nsXBLBinding::HasInsertionParent(nsICont
 
 nsresult
 nsXBLBinding::GetInsertionPointsFor(nsIContent* aParent,
                                     nsInsertionPointList** aResult)
 {
   if (!mInsertionPointTable) {
     mInsertionPointTable =
       new nsClassHashtable<nsISupportsHashKey, nsInsertionPointList>;
-    if (!mInsertionPointTable || !mInsertionPointTable->Init(4)) {
-      delete mInsertionPointTable;
-      mInsertionPointTable = nsnull;
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
+    mInsertionPointTable->Init(4);
   }
 
   mInsertionPointTable->Get(aParent, aResult);
 
   if (!*aResult) {
     *aResult = new nsInsertionPointList;
-    if (!*aResult || !mInsertionPointTable->Put(aParent, *aResult)) {
-      delete *aResult;
-      *aResult = nsnull;
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
+    mInsertionPointTable->Put(aParent, *aResult);
     if (aParent) {
       aParent->SetFlags(NODE_IS_INSERTION_PARENT);
     }
   }
 
   return NS_OK;
 }
 
--- a/content/xslt/src/xslt/txEXSLTFunctions.cpp
+++ b/content/xslt/src/xslt/txEXSLTFunctions.cpp
@@ -402,29 +402,25 @@ txEXSLTFunctionCall::evaluate(txIEvalCon
                                    getter_AddRefs(nodes));
             NS_ENSURE_SUCCESS(rv, rv);
 
             nsRefPtr<txNodeSet> resultSet;
             rv = aContext->recycler()->getNodeSet(getter_AddRefs(resultSet));
             NS_ENSURE_SUCCESS(rv, rv);
 
             nsTHashtable<nsStringHashKey> hash;
-            if (!hash.Init()) {
-                return NS_ERROR_OUT_OF_MEMORY;
-            }
+            hash.Init();
 
             PRInt32 i, len = nodes->size();
             for (i = 0; i < len; ++i) {
                 nsAutoString str;
                 const txXPathNode& node = nodes->get(i);
                 txXPathNodeUtils::appendNodeValue(node, str);
                 if (!hash.GetEntry(str)) {
-                    if (!hash.PutEntry(str)) {
-                        return NS_ERROR_OUT_OF_MEMORY;
-                    }
+                    hash.PutEntry(str);
                     rv = resultSet->append(node);
                     NS_ENSURE_SUCCESS(rv, rv);
                 }
             }
 
             NS_ADDREF(*aResult = resultSet);
 
             return NS_OK;
--- a/content/xslt/src/xslt/txExecutionState.cpp
+++ b/content/xslt/src/xslt/txExecutionState.cpp
@@ -46,18 +46,17 @@
 #include "txLog.h"
 #include "txURIUtils.h"
 #include "txXMLParser.h"
 
 const PRInt32 txExecutionState::kMaxRecursionDepth = 20000;
 
 nsresult txLoadedDocumentsHash::init(txXPathNode* aSourceDocument)
 {
-    nsresult rv = Init(8);
-    NS_ENSURE_SUCCESS(rv, rv);
+    Init(8);
 
     mSourceDocument = aSourceDocument;
     
     nsAutoString baseURI;
     txXPathNodeUtils::getBaseURI(*mSourceDocument, baseURI);
 
     txLoadedDocumentEntry* entry = PutEntry(baseURI);
     if (!entry) {
--- a/content/xslt/src/xslt/txKeyFunctionCall.cpp
+++ b/content/xslt/src/xslt/txKeyFunctionCall.cpp
@@ -267,25 +267,20 @@ txKeyHash::getKeyNodes(const txExpandedN
     }
 
     return NS_OK;
 }
 
 nsresult
 txKeyHash::init()
 {
-    nsresult rv = mKeyValues.Init(8);
-    NS_ENSURE_SUCCESS(rv, rv);
+    mKeyValues.Init(8);
+    mIndexedKeys.Init(1);
+    mEmptyNodeSet = new txNodeSet(nsnull);
 
-    rv = mIndexedKeys.Init(1);
-    NS_ENSURE_SUCCESS(rv, rv);
-    
-    mEmptyNodeSet = new txNodeSet(nsnull);
-    NS_ENSURE_TRUE(mEmptyNodeSet, NS_ERROR_OUT_OF_MEMORY);
-    
     return NS_OK;
 }
 
 
 /**
  * Adds a match/use pair.
  * @param aMatch  match-pattern
  * @param aUse    use-expression
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -1868,20 +1868,17 @@ NS_IMETHODIMP
 nsXULDocument::SetTemplateBuilderFor(nsIContent* aContent,
                                      nsIXULTemplateBuilder* aBuilder)
 {
     if (! mTemplateBuilderTable) {
         if (!aBuilder) {
             return NS_OK;
         }
         mTemplateBuilderTable = new BuilderTable;
-        if (! mTemplateBuilderTable || !mTemplateBuilderTable->Init()) {
-            mTemplateBuilderTable = nsnull;
-            return NS_ERROR_OUT_OF_MEMORY;
-        }
+        mTemplateBuilderTable->Init();
     }
 
     if (aBuilder) {
         mTemplateBuilderTable->Put(aContent, aBuilder);
     }
     else {
         mTemplateBuilderTable->Remove(aContent);
     }
@@ -2644,19 +2641,19 @@ nsXULDocument::LoadOverlay(const nsAStri
     nsresult rv;
 
     nsCOMPtr<nsIURI> uri;
     rv = NS_NewURI(getter_AddRefs(uri), aURL, nsnull);
     if (NS_FAILED(rv)) return rv;
 
     if (aObserver) {
         nsIObserver* obs = nsnull;
-        NS_ENSURE_TRUE(mOverlayLoadObservers.IsInitialized() || mOverlayLoadObservers.Init(), 
-                       NS_ERROR_OUT_OF_MEMORY);
-        
+        if (!mOverlayLoadObservers.IsInitialized()) {
+            mOverlayLoadObservers.Init();
+        }
         obs = mOverlayLoadObservers.GetWeak(uri);
 
         if (obs) {
             // We don't support loading the same overlay twice into the same
             // document - that doesn't make sense anyway.
             return NS_ERROR_FAILURE;
         }
         mOverlayLoadObservers.Put(uri, aObserver);
@@ -3243,18 +3240,19 @@ nsXULDocument::DoneWalking()
                 // yet been attached. This can be a race condition because dynamic
                 // overlay loading can take varying amounts of time depending on
                 // whether or not the overlay prototype is in the XUL cache. The
                 // most likely effect of this bug is odd UI initialization due to
                 // methods and properties that do not work.
                 // XXXbz really, we shouldn't be firing binding constructors
                 // until after StartLayout returns!
 
-                NS_ENSURE_TRUE(mPendingOverlayLoadNotifications.IsInitialized() || mPendingOverlayLoadNotifications.Init(), 
-                               NS_ERROR_OUT_OF_MEMORY);
+                if (!mPendingOverlayLoadNotifications.IsInitialized()) {
+                    mPendingOverlayLoadNotifications.Init();
+                }
                 
                 mPendingOverlayLoadNotifications.Get(overlayURI, getter_AddRefs(obs));
                 if (!obs) {
                     mOverlayLoadObservers.Get(overlayURI, getter_AddRefs(obs));
                     NS_ASSERTION(obs, "null overlay load observer?");
                     mPendingOverlayLoadNotifications.Put(overlayURI, obs);
                 }
             }
--- a/content/xul/document/src/nsXULPrototypeCache.cpp
+++ b/content/xul/document/src/nsXULPrototypeCache.cpp
@@ -204,28 +204,27 @@ nsXULPrototypeCache::GetPrototype(nsIURI
     return newProto;
 }
 
 nsresult
 nsXULPrototypeCache::PutPrototype(nsXULPrototypeDocument* aDocument)
 {
     nsCOMPtr<nsIURI> uri = aDocument->GetURI();
     // Put() releases any old value and addrefs the new one
-    NS_ENSURE_TRUE(mPrototypeTable.Put(uri, aDocument), NS_ERROR_OUT_OF_MEMORY);
+    mPrototypeTable.Put(uri, aDocument);
 
     return NS_OK;
 }
 
 nsresult
 nsXULPrototypeCache::PutStyleSheet(nsCSSStyleSheet* aStyleSheet)
 {
     nsIURI* uri = aStyleSheet->GetSheetURI();
 
-    NS_ENSURE_TRUE(mStyleSheetTable.Put(uri, aStyleSheet),
-                   NS_ERROR_OUT_OF_MEMORY);
+    mStyleSheetTable.Put(uri, aStyleSheet);
 
     return NS_OK;
 }
 
 
 JSScript*
 nsXULPrototypeCache::GetScript(nsIURI* aURI)
 {
@@ -261,17 +260,17 @@ nsXULPrototypeCache::PutScript(nsIURI* a
         NS_WARNING(message.get());
 #endif
         // Reuse the callback used for enumeration in FlushScripts
         ReleaseScriptObjectCallback(aURI, existingEntry, nsnull);
     }
 
     CacheScriptEntry entry = {aScriptObject};
 
-    NS_ENSURE_TRUE(mScriptTable.Put(aURI, entry), NS_ERROR_OUT_OF_MEMORY);
+    mScriptTable.Put(aURI, entry);
 
     // Lock the object from being gc'd until it is removed from the cache
     nsCOMPtr<nsIScriptRuntime> rt;
     nsresult rv = NS_GetJSRuntime(getter_AddRefs(rt));
     if (NS_SUCCEEDED(rv))
         rv = rt->HoldScriptObject(aScriptObject);
     NS_ASSERTION(NS_SUCCEEDED(rv), "Failed to GC lock the object");
 
@@ -291,18 +290,17 @@ nsXULPrototypeCache::FlushScripts()
 nsresult
 nsXULPrototypeCache::PutXBLDocumentInfo(nsXBLDocumentInfo* aDocumentInfo)
 {
     nsIURI* uri = aDocumentInfo->DocumentURI();
 
     nsRefPtr<nsXBLDocumentInfo> info;
     mXBLDocTable.Get(uri, getter_AddRefs(info));
     if (!info) {
-        NS_ENSURE_TRUE(mXBLDocTable.Put(uri, aDocumentInfo),
-                       NS_ERROR_OUT_OF_MEMORY);
+        mXBLDocTable.Put(uri, aDocumentInfo);
     }
     return NS_OK;
 }
 
 static PLDHashOperator
 FlushSkinXBL(nsIURI* aKey, nsRefPtr<nsXBLDocumentInfo>& aDocInfo, void* aClosure)
 {
   nsCAutoString str;
--- a/content/xul/templates/src/nsXULContentBuilder.cpp
+++ b/content/xul/templates/src/nsXULContentBuilder.cpp
@@ -1236,19 +1236,18 @@ nsXULContentBuilder::CreateContainerCont
         }
 
         if (mFlags & eLoggingEnabled)
             OutputMatchToLog(resultid, newmatch, true);
 
         if (prevmatch) {
             prevmatch->mNext = newmatch;
         }
-        else if (!mMatchMap.Put(resultid, newmatch)) {
-            nsTemplateMatch::Destroy(mPool, newmatch, true);
-            return NS_ERROR_OUT_OF_MEMORY;
+        else {
+            mMatchMap.Put(resultid, newmatch);
         }
 
         if (removematch) {
             newmatch->mNext = removematch->mNext;
             nsTemplateMatch::Destroy(mPool, removematch, true);
         }
         else {
             newmatch->mNext = existingmatch;
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -206,18 +206,18 @@ nsXULTemplateBuilder::InitGlobals()
             return rv;
     }
 
 #ifdef PR_LOGGING
     if (! gXULTemplateLog)
         gXULTemplateLog = PR_NewLogModule("nsXULTemplateBuilder");
 #endif
 
-    if (!mMatchMap.IsInitialized() && !mMatchMap.Init())
-        return NS_ERROR_OUT_OF_MEMORY;
+    if (!mMatchMap.IsInitialized())
+        mMatchMap.Init();
 
     const size_t bucketsizes[] = { sizeof(nsTemplateMatch) };
     return mPool.Init("nsXULTemplateBuilder", bucketsizes, 1, 256);
 }
 
 void
 nsXULTemplateBuilder::CleanUp(bool aIsFinal)
 {
@@ -786,18 +786,17 @@ nsXULTemplateBuilder::UpdateResultInCont
 
                         findmatch = findmatch->mNext;
                     }
                 }
 
                 if (oldmatch == firstmatch) {
                     // the match to remove is at the beginning
                     if (oldmatch->mNext) {
-                        if (!mMatchMap.Put(aOldId, oldmatch->mNext))
-                            return NS_ERROR_OUT_OF_MEMORY;
+                        mMatchMap.Put(aOldId, oldmatch->mNext);
                     }
                     else {
                         mMatchMap.Remove(aOldId);
                     }
                 }
 
                 if (prevmatch)
                     prevmatch->mNext = nextmatch;
@@ -960,23 +959,17 @@ nsXULTemplateBuilder::UpdateResultInCont
                         }
 
                         newmatch = newmatch->mNext;
                     }
                 }
 
                 // put the match in the map if there isn't a previous match
                 if (! prevmatch) {
-                    if (!mMatchMap.Put(aNewId, newmatch)) {
-                        // The match may have already matched a rule above, so
-                        // HasBeenRemoved should be called to indicate that it
-                        // is being removed again.
-                        nsTemplateMatch::Destroy(mPool, newmatch, true);
-                        return rv;
-                    }
+                    mMatchMap.Put(aNewId, newmatch);
                 }
             }
 
             // hook up the match last in case an error occurs
             if (prevmatch)
                 prevmatch->mNext = newmatch;
         }
         else {
@@ -995,20 +988,17 @@ nsXULTemplateBuilder::UpdateResultInCont
                 if (NS_FAILED(rv)) {
                     nsTemplateMatch::Destroy(mPool, newmatch, false);
                     return rv;
                 }
 
                 acceptedmatch = newmatch;
             }
 
-            if (!mMatchMap.Put(aNewId, newmatch)) {
-                nsTemplateMatch::Destroy(mPool, newmatch, true);
-                return NS_ERROR_OUT_OF_MEMORY;
-            }
+            mMatchMap.Put(aNewId, newmatch);
         }
     }
 
     // The ReplaceMatch method is builder specific and removes the generated
     // content for a match.
 
     // Remove the content for a match that was active and needs to be replaced.
     if (replacedmatch) {
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorRDF.cpp
@@ -337,25 +337,22 @@ nsXULTemplateQueryProcessorRDF::Initiali
                                                       nsIXULTemplateBuilder* aBuilder,
                                                       nsIDOMNode* aRootNode)
 {
     if (!mQueryProcessorRDFInited) {
         nsresult rv = InitGlobals();
         if (NS_FAILED(rv))
             return rv;
 
-        if (!mMemoryElementToResultMap.IsInitialized() &&
-            !mMemoryElementToResultMap.Init())
-            return NS_ERROR_OUT_OF_MEMORY;
-        if (!mBindingDependencies.IsInitialized() &&
-            !mBindingDependencies.Init())
-            return NS_ERROR_OUT_OF_MEMORY;
-        if (!mRuleToBindingsMap.IsInitialized() &&
-            !mRuleToBindingsMap.Init())
-            return NS_ERROR_OUT_OF_MEMORY;
+        if (!mMemoryElementToResultMap.IsInitialized())
+            mMemoryElementToResultMap.Init();
+        if (!mBindingDependencies.IsInitialized())
+            mBindingDependencies.Init();
+        if (!mRuleToBindingsMap.IsInitialized())
+            mRuleToBindingsMap.Init();
 
         mQueryProcessorRDFInited = true;
     }
 
     // don't do anything if generation has already been done
     if (mGenerationStarted)
         return NS_ERROR_UNEXPECTED;
 
@@ -615,18 +612,17 @@ nsXULTemplateQueryProcessorRDF::AddBindi
     nsCOMPtr<nsIRDFResource> property;
     nsresult rv = gRDFService->GetUnicodeResource(aExpr, getter_AddRefs(property));
     if (NS_FAILED(rv))
         return rv;
 
     nsRefPtr<RDFBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode);
     if (!bindings) {
         bindings = new RDFBindingSet();
-        if (!bindings || !mRuleToBindingsMap.Put(aRuleNode, bindings))
-            return NS_ERROR_OUT_OF_MEMORY;
+        mRuleToBindingsMap.Put(aRuleNode, bindings);
     }
 
     return bindings->AddBinding(aVar, aRef, property);
 }
 
 NS_IMETHODIMP
 nsXULTemplateQueryProcessorRDF::TranslateRef(nsISupports* aDatasource,
                                                            const nsAString& aRefString,
@@ -1761,20 +1757,17 @@ nsXULTemplateQueryProcessorRDF::AddBindi
                                                      nsIRDFResource* aResource)
 {
     nsCOMArray<nsXULTemplateResultRDF>* arr;
     if (!mBindingDependencies.Get(aResource, &arr)) {
         arr = new nsCOMArray<nsXULTemplateResultRDF>();
         if (!arr)
             return NS_ERROR_OUT_OF_MEMORY;
 
-        if (!mBindingDependencies.Put(aResource, arr)) {
-            delete arr;
-            return NS_ERROR_OUT_OF_MEMORY;
-        }
+        mBindingDependencies.Put(aResource, arr);
     }
 
     PRInt32 index = arr->IndexOf(aResult);
     if (index == -1)
         return arr->AppendObject(aResult);
 
     return NS_OK;
 }
@@ -1806,20 +1799,17 @@ nsXULTemplateQueryProcessorRDF::AddMemor
         PLHashNumber hash = (element.operator->())->Hash();
 
         nsCOMArray<nsXULTemplateResultRDF>* arr;
         if (!mMemoryElementToResultMap.Get(hash, &arr)) {
             arr = new nsCOMArray<nsXULTemplateResultRDF>();
             if (!arr)
                 return NS_ERROR_OUT_OF_MEMORY;
 
-            if (!mMemoryElementToResultMap.Put(hash, arr)) {
-                delete arr;
-                return NS_ERROR_OUT_OF_MEMORY;
-            }
+            mMemoryElementToResultMap.Put(hash, arr);
         }
 
         // results may be added more than once so they will all get deleted properly
         arr->AppendObject(aResult);
     }
 
     return NS_OK;
 }
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
@@ -250,19 +250,18 @@ nsXULTemplateQueryProcessorXML::Initiali
         doc->GetDocumentElement(getter_AddRefs(mRoot));
     else
       mRoot = do_QueryInterface(aDatasource);
     NS_ENSURE_STATE(mRoot);
 
     mEvaluator = do_CreateInstance("@mozilla.org/dom/xpath-evaluator;1");
     NS_ENSURE_TRUE(mEvaluator, NS_ERROR_OUT_OF_MEMORY);
 
-    if (!mRuleToBindingsMap.IsInitialized() &&
-        !mRuleToBindingsMap.Init())
-        return NS_ERROR_OUT_OF_MEMORY;
+    if (!mRuleToBindingsMap.IsInitialized())
+        mRuleToBindingsMap.Init();
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateQueryProcessorXML::Done()
 {
     mGenerationStarted = false;
@@ -395,18 +394,17 @@ nsXULTemplateQueryProcessorXML::AddBindi
                                            const nsAString& aExpr)
 {
     if (mGenerationStarted)
         return NS_ERROR_FAILURE;
 
     nsRefPtr<nsXMLBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode);
     if (!bindings) {
         bindings = new nsXMLBindingSet();
-        if (!bindings || !mRuleToBindingsMap.Put(aRuleNode, bindings))
-            return NS_ERROR_OUT_OF_MEMORY;
+        mRuleToBindingsMap.Put(aRuleNode, bindings);
     }
 
     nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
     nsresult rv =
         CreateExpression(aExpr, aRuleNode, getter_AddRefs(compiledexpr));
     if (NS_FAILED(rv)) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_BINDING_XPATH);
         return NS_OK;
--- a/content/xul/templates/src/nsXULTreeBuilder.cpp
+++ b/content/xul/templates/src/nsXULTreeBuilder.cpp
@@ -1738,19 +1738,18 @@ nsXULTreeBuilder::OpenSubtreeForQuerySet
             if (mFlags & eLoggingEnabled)
                 OutputMatchToLog(resultid, newmatch, true);
 
         }
 
         if (prevmatch) {
             prevmatch->mNext = newmatch;
         }
-        else if (!mMatchMap.Put(resultid, newmatch)) {
-            nsTemplateMatch::Destroy(mPool, newmatch, true);
-            return NS_ERROR_OUT_OF_MEMORY;
+        else {
+            mMatchMap.Put(resultid, newmatch);
         }
     }
 
     *aDelta = count;
     return rv;
 }
 
 nsresult
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -872,18 +872,17 @@ nsDocShell::Init()
     NS_ASSERTION(mLoadGroup, "Something went wrong!");
 
     mContentListener = new nsDSURIContentListener(this);
     NS_ENSURE_TRUE(mContentListener, NS_ERROR_OUT_OF_MEMORY);
 
     rv = mContentListener->Init();
     NS_ENSURE_SUCCESS(rv, rv);
 
-    if (!mStorages.Init())
-        return NS_ERROR_OUT_OF_MEMORY;
+    mStorages.Init();
 
     // We want to hold a strong ref to the loadgroup, so it better hold a weak
     // ref to us...  use an InterfaceRequestorProxy to do this.
     nsCOMPtr<InterfaceRequestorProxy> proxy =
         new InterfaceRequestorProxy(static_cast<nsIInterfaceRequestor*>
                                                (this));
     NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
     mLoadGroup->SetNotificationCallbacks(proxy);
@@ -2437,18 +2436,17 @@ nsDocShell::GetSessionStorageForPrincipa
         nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(newstorage);
         if (!pistorage)
             return NS_ERROR_FAILURE;
 
         rv = pistorage->InitAsSessionStorage(aPrincipal, aDocumentURI);
         if (NS_FAILED(rv))
             return rv;
 
-        if (!mStorages.Put(origin, newstorage))
-            return NS_ERROR_OUT_OF_MEMORY;
+        mStorages.Put(origin, newstorage);
 
         newstorage.swap(*aStorage);
 #if defined(PR_LOGGING) && defined(DEBUG)
         PR_LOG(gDocShellLog, PR_LOG_DEBUG,
                ("nsDocShell[%p]: created a new sessionStorage %p",
                 this, *aStorage));
 #endif
     }
@@ -2575,18 +2573,17 @@ nsDocShell::AddSessionStorage(nsIPrincip
             if (mStorages.GetWeak(origin))
                 return NS_ERROR_NOT_AVAILABLE;
 
 #if defined(PR_LOGGING) && defined(DEBUG)
             PR_LOG(gDocShellLog, PR_LOG_DEBUG,
                    ("nsDocShell[%p]: was added a sessionStorage %p",
                     this, aStorage));
 #endif
-            if (!mStorages.Put(origin, aStorage))
-                return NS_ERROR_OUT_OF_MEMORY;
+            mStorages.Put(origin, aStorage);
         }
         else {
             return topDocShell->AddSessionStorage(aPrincipal, aStorage);
         }
     }
 
     return NS_OK;
 }
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -811,24 +811,17 @@ nsGlobalWindow::Init()
                "gEntropyCollector should have been initialized!");
 
 #ifdef PR_LOGGING
   gDOMLeakPRLog = PR_NewLogModule("DOMLeak");
   NS_ASSERTION(gDOMLeakPRLog, "gDOMLeakPRLog should have been initialized!");
 #endif
 
   sWindowsById = new WindowByIdTable();
-  // There are two reasons to have Init() failing: if we were not able to
-  // alloc the memory or if the size we want to init is too high. None of them
-  // should happen.
-#ifdef DEBUG
-  NS_ASSERTION(sWindowsById->Init(), "Init() should not fail!");
-#else
   sWindowsById->Init();
-#endif
 }
 
 static PLDHashOperator
 DisconnectEventTargetObjects(nsPtrHashKey<nsDOMEventTargetHelper>* aKey,
                              void* aClosure)
 {
   nsRefPtr<nsDOMEventTargetHelper> target = aKey->GetKey();
   target->DisconnectFromOwner();
@@ -6740,20 +6733,18 @@ nsGlobalWindow::GetCachedXBLPrototypeHan
   }
   return handler;
 }
 
 void
 nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
                                          nsScriptObjectHolder<JSObject>& aHandler)
 {
-  if (!mCachedXBLPrototypeHandlers.IsInitialized() &&
-      !mCachedXBLPrototypeHandlers.Init()) {
-    NS_ERROR("Failed to initiailize hashtable!");
-    return;
+  if (!mCachedXBLPrototypeHandlers.IsInitialized()) {
+    mCachedXBLPrototypeHandlers.Init();
   }
 
   if (!mCachedXBLPrototypeHandlers.Count()) {
     // Can't use macros to get the participant because nsGlobalChromeWindow also
     // runs through this code. Use QueryInterface to get the correct objects.
     nsXPCOMCycleCollectionParticipant* participant;
     CallQueryInterface(this, &participant);
     NS_ASSERTION(participant,
--- a/dom/indexedDB/DatabaseInfo.cpp
+++ b/dom/indexedDB/DatabaseInfo.cpp
@@ -68,20 +68,17 @@ PLDHashOperator
 CloneObjectStoreInfo(const nsAString& aKey,
                      ObjectStoreInfo* aData,
                      void* aUserArg)
 {
   ObjectStoreInfoHash* hash = static_cast<ObjectStoreInfoHash*>(aUserArg);
 
   nsRefPtr<ObjectStoreInfo> newInfo(new ObjectStoreInfo(*aData));
 
-  if (!hash->Put(aKey, newInfo)) {
-    NS_WARNING("Out of memory?");
-    return PL_DHASH_STOP;
-  }
+  hash->Put(aKey, newInfo);
 
   return PL_DHASH_NEXT;
 }
 
 }
 
 DatabaseInfo::~DatabaseInfo()
 {
@@ -173,33 +170,26 @@ DatabaseInfo::Get(nsIAtom* aId,
 bool
 DatabaseInfo::Put(DatabaseInfo* aInfo)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aInfo, "Null pointer!");
 
   if (!gDatabaseHash) {
     nsAutoPtr<DatabaseHash> databaseHash(new DatabaseHash());
-    if (!databaseHash->Init()) {
-      NS_ERROR("Failed to initialize hashtable!");
-      return false;
-    }
-
+    databaseHash->Init();
     gDatabaseHash = databaseHash.forget();
   }
 
   if (gDatabaseHash->Get(aInfo->id, nsnull)) {
     NS_ERROR("Already know about this database!");
     return false;
   }
 
-  if (!gDatabaseHash->Put(aInfo->id, aInfo)) {
-    NS_ERROR("Put failed!");
-    return false;
-  }
+  gDatabaseHash->Put(aInfo->id, aInfo);
 
   return true;
 }
 
 // static
 void
 DatabaseInfo::Remove(nsIAtom* aId)
 {
@@ -275,29 +265,27 @@ DatabaseInfo::GetObjectStore(const nsASt
 bool
 DatabaseInfo::PutObjectStore(ObjectStoreInfo* aInfo)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(aInfo, "Null pointer!");
 
   if (!objectStoreHash) {
     nsAutoPtr<ObjectStoreInfoHash> hash(new ObjectStoreInfoHash());
-    if (!hash->Init()) {
-      NS_ERROR("Failed to initialize hashtable!");
-      return false;
-    }
+    hash->Init();
     objectStoreHash = hash.forget();
   }
 
   if (objectStoreHash->Get(aInfo->name, nsnull)) {
     NS_ERROR("Already have an entry for this objectstore!");
     return false;
   }
 
-  return objectStoreHash->Put(aInfo->name, aInfo);
+  objectStoreHash->Put(aInfo->name, aInfo);
+  return true;
 }
 
 void
 DatabaseInfo::RemoveObjectStore(const nsAString& aName)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(GetObjectStore(aName), "Don't know about this one!");
 
@@ -318,18 +306,15 @@ DatabaseInfo::Clone()
   dbInfo->version = version;
   dbInfo->id = id;
   dbInfo->filePath = filePath;
   dbInfo->nextObjectStoreId = nextObjectStoreId;
   dbInfo->nextIndexId = nextIndexId;
 
   if (objectStoreHash) {
     dbInfo->objectStoreHash = new ObjectStoreInfoHash();
-    if (!dbInfo->objectStoreHash->Init()) {
-      return nsnull;
-    }
-
+    dbInfo->objectStoreHash->Init();
     objectStoreHash->EnumerateRead(CloneObjectStoreInfo,
                                    dbInfo->objectStoreHash);
   }
 
   return dbInfo.forget();
 }
--- a/dom/indexedDB/FileManager.cpp
+++ b/dom/indexedDB/FileManager.cpp
@@ -73,17 +73,17 @@ EnumerateToTArray(const PRUint64& aKey,
 } // anonymous namespace
 
 nsresult
 FileManager::Init(nsIFile* aDirectory,
                   mozIStorageConnection* aConnection)
 {
   NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
 
-  NS_ENSURE_TRUE(mFileInfos.Init(), NS_ERROR_OUT_OF_MEMORY);
+  mFileInfos.Init();
 
   bool exists;
   nsresult rv = aDirectory->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (exists) {
     bool isDirectory;
     rv = aDirectory->IsDirectory(&isDirectory);
@@ -181,20 +181,17 @@ FileManager::Load(mozIStorageConnection*
     rv = stmt->GetInt32(1, &refcount);
     NS_ENSURE_SUCCESS(rv, rv);
 
     NS_ASSERTION(refcount, "This shouldn't happen!");
 
     nsRefPtr<FileInfo> fileInfo = FileInfo::Create(this, id);
     fileInfo->mDBRefCnt = refcount;
 
-    if (!mFileInfos.Put(id, fileInfo)) {
-      NS_WARNING("Out of memory?");
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
+    mFileInfos.Put(id, fileInfo);
 
     mLastFileId = NS_MAX(id, mLastFileId);
   }
 
   mLoaded = true;
 
   return NS_OK;
 }
@@ -268,20 +265,17 @@ FileManager::GetNewFileInfo()
 
   {
     MutexAutoLock lock(IndexedDatabaseManager::FileMutex());
 
     PRInt64 id = mLastFileId + 1;
 
     fileInfo = FileInfo::Create(this, id);
 
-    if (!mFileInfos.Put(id, fileInfo)) {
-      NS_WARNING("Out of memory?");
-      return nsnull;
-    }
+    mFileInfos.Put(id, fileInfo);
 
     mLastFileId = id;
   }
 
   nsRefPtr<FileInfo> result = fileInfo.forget();
   return result.forget();
 }
 
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -131,20 +131,17 @@ IDBTransaction::Create(IDBDatabase* aDat
   
   transaction->mDatabaseInfo = aDatabase->Info();
 
   if (!transaction->mObjectStoreNames.AppendElements(aObjectStoreNames)) {
     NS_ERROR("Out of memory!");
     return nsnull;
   }
 
-  if (!transaction->mCachedStatements.Init()) {
-    NS_ERROR("Failed to initialize hash!");
-    return nsnull;
-  }
+  transaction->mCachedStatements.Init();
 
   if (!aDispatchDelayed) {
     nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
     NS_ENSURE_TRUE(appShell, nsnull);
 
     nsresult rv = appShell->RunBeforeNextEvent(transaction);
     NS_ENSURE_SUCCESS(rv, nsnull);
 
@@ -391,19 +388,17 @@ IDBTransaction::GetCachedStatement(const
       (void)mConnection->GetLastErrorString(msg);
       error.Append(msg);
       error.AppendLiteral("`.");
       NS_ERROR(error.get());
     }
 #endif
     NS_ENSURE_SUCCESS(rv, nsnull);
 
-    if (!mCachedStatements.Put(aQuery, stmt)) {
-      NS_ERROR("Out of memory?!");
-    }
+    mCachedStatements.Put(aQuery, stmt);
   }
 
   return stmt.forget();
 }
 
 bool
 IDBTransaction::IsOpen() const
 {
@@ -840,17 +835,17 @@ CommitHelper::RevertAutoIncrementCounts(
     ObjectStoreInfo* info = mAutoIncrementObjectStores[i]->Info();
     info->nextAutoIncrementId = info->comittedAutoIncrementId;
   }
 }
 
 nsresult
 UpdateRefcountFunction::Init()
 {
-  NS_ENSURE_TRUE(mFileInfoEntries.Init(), NS_ERROR_OUT_OF_MEMORY);
+  mFileInfoEntries.Init();
 
   return NS_OK;
 }
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(UpdateRefcountFunction, mozIStorageFunction)
 
 NS_IMETHODIMP
 UpdateRefcountFunction::OnFunctionCall(mozIStorageValueArray* aValues,
@@ -906,20 +901,17 @@ UpdateRefcountFunction::ProcessValue(moz
     PRInt64 id = fileIds.ElementAt(i);
 
     FileInfoEntry* entry;
     if (!mFileInfoEntries.Get(id, &entry)) {
       nsRefPtr<FileInfo> fileInfo = mFileManager->GetFileInfo(id);
       NS_ASSERTION(fileInfo, "Shouldn't be null!");
 
       nsAutoPtr<FileInfoEntry> newEntry(new FileInfoEntry(fileInfo));
-      if (!mFileInfoEntries.Put(id, newEntry)) {
-        NS_WARNING("Out of memory?");
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
+      mFileInfoEntries.Put(id, newEntry);
       entry = newEntry.forget();
     }
 
     switch (aUpdateType) {
       case eIncrement:
         entry->mDelta++;
         break;
       case eDecrement:
--- a/dom/indexedDB/IndexedDatabaseManager.cpp
+++ b/dom/indexedDB/IndexedDatabaseManager.cpp
@@ -223,22 +223,19 @@ IndexedDatabaseManager::GetOrCreate()
                                               PREF_INDEXEDDB_QUOTA,
                                               DEFAULT_QUOTA_MB))) {
       NS_WARNING("Unable to respond to quota pref changes!");
       gIndexedDBQuotaMB = DEFAULT_QUOTA_MB;
     }
 
     instance = new IndexedDatabaseManager();
 
-    if (!instance->mLiveDatabases.Init() ||
-        !instance->mQuotaHelperHash.Init() ||
-        !instance->mFileManagers.Init()) {
-      NS_WARNING("Out of memory!");
-      return nsnull;
-    }
+    instance->mLiveDatabases.Init();
+    instance->mQuotaHelperHash.Init();
+    instance->mFileManagers.Init();
 
     // We need a thread-local to hold the current window.
     NS_ASSERTION(instance->mCurrentWindowIndex == BAD_TLS_INDEX, "Huh?");
 
     if (PR_NewThreadPrivateIndex(&instance->mCurrentWindowIndex, nsnull) !=
         PR_SUCCESS) {
       NS_ERROR("PR_NewThreadPrivateIndex failed, IndexedDB disabled");
       instance->mCurrentWindowIndex = BAD_TLS_INDEX;
@@ -337,20 +334,17 @@ IndexedDatabaseManager::RegisterDatabase
   if (IsShuttingDown()) {
     return false;
   }
 
   // Add this database to its origin array if it exists, create it otherwise.
   nsTArray<IDBDatabase*>* array;
   if (!mLiveDatabases.Get(aDatabase->Origin(), &array)) {
     nsAutoPtr<nsTArray<IDBDatabase*> > newArray(new nsTArray<IDBDatabase*>());
-    if (!mLiveDatabases.Put(aDatabase->Origin(), newArray)) {
-      NS_WARNING("Out of memory?");
-      return false;
-    }
+    mLiveDatabases.Put(aDatabase->Origin(), newArray);
     array = newArray.forget();
   }
   if (!array->AppendElement(aDatabase)) {
     NS_WARNING("Out of memory?");
     return false;
   }
 
   aDatabase->mRegistered = true;
@@ -725,17 +719,17 @@ IndexedDatabaseManager::EnsureOriginIsIn
 
   nsAutoTArray<nsString, 20> subdirsToProcess;
   nsAutoTArray<nsCOMPtr<nsIFile> , 20> unknownFiles;
 
   nsAutoPtr<nsTArray<nsRefPtr<FileManager> > > fileManagers(
     new nsTArray<nsRefPtr<FileManager> >());
 
   nsTHashtable<nsStringHashKey> validSubdirs;
-  NS_ENSURE_TRUE(validSubdirs.Init(20), NS_ERROR_OUT_OF_MEMORY);
+  validSubdirs.Init(20);
   
   nsCOMPtr<nsISimpleEnumerator> entries;
   rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool hasMore;
   while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) && hasMore) {
     nsCOMPtr<nsISupports> entry;
@@ -803,20 +797,17 @@ IndexedDatabaseManager::EnsureOriginIsIn
     rv = fileManager->Init(fileManagerDirectory, connection);
     NS_ENSURE_SUCCESS(rv, rv);
 
     fileManagers->AppendElement(fileManager);
 
     rv = ss->UpdateQuotaInformationForFile(file);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    if (!validSubdirs.PutEntry(dbBaseFilename)) {
-      NS_WARNING("Out of memory?");
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
+    validSubdirs.PutEntry(dbBaseFilename);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   for (PRUint32 i = 0; i < subdirsToProcess.Length(); i++) {
     const nsString& subdir = subdirsToProcess[i];
     if (!validSubdirs.GetEntry(subdir)) {
       NS_WARNING("Unknown subdirectory found!");
       return NS_ERROR_UNEXPECTED;
@@ -839,21 +830,17 @@ IndexedDatabaseManager::EnsureOriginIsIn
       // The journal file may exists even after db has been correctly opened.
       if (!StringEndsWith(leafName, NS_LITERAL_STRING(".sqlite-journal"))) {
         NS_WARNING("Unknown file found!");
         return NS_ERROR_UNEXPECTED;
       }
     }
   }
 
-  if (!mFileManagers.Put(aOrigin, fileManagers)) {
-    NS_WARNING("Out of memory?");
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
+  mFileManagers.Put(aOrigin, fileManagers);
   fileManagers.forget();
 
   NS_ADDREF(*aDirectory = directory);
   return NS_OK;
 }
 
 bool
 IndexedDatabaseManager::QuotaIsLiftedInternal()
@@ -873,18 +860,17 @@ IndexedDatabaseManager::QuotaIsLiftedInt
   MutexAutoLock autoLock(mQuotaHelperMutex);
 
   mQuotaHelperHash.Get(window, getter_AddRefs(helper));
 
   if (!helper) {
     helper = new CheckQuotaHelper(window, mQuotaHelperMutex);
     createdHelper = true;
 
-    bool result = mQuotaHelperHash.Put(window, helper);
-    NS_ENSURE_TRUE(result, result);
+    mQuotaHelperHash.Put(window, helper);
 
     // Unlock while calling out to XPCOM
     {
       MutexAutoUnlock autoUnlock(mQuotaHelperMutex);
 
       nsresult rv = NS_DispatchToMainThread(helper);
       NS_ENSURE_SUCCESS(rv, false);
     }
@@ -961,20 +947,17 @@ IndexedDatabaseManager::GetASCIIOriginFr
 already_AddRefed<FileManager>
 IndexedDatabaseManager::GetOrCreateFileManager(const nsACString& aOrigin,
                                                const nsAString& aDatabaseName)
 {
   nsTArray<nsRefPtr<FileManager> >* array;
   if (!mFileManagers.Get(aOrigin, &array)) {
     nsAutoPtr<nsTArray<nsRefPtr<FileManager> > > newArray(
       new nsTArray<nsRefPtr<FileManager> >());
-    if (!mFileManagers.Put(aOrigin, newArray)) {
-      NS_WARNING("Out of memory?");
-      return nsnull;
-    }
+    mFileManagers.Put(aOrigin, newArray);
     array = newArray.forget();
   }
 
   nsRefPtr<FileManager> fileManager;
   for (PRUint32 i = 0; i < array->Length(); i++) {
     nsRefPtr<FileManager> fm = array->ElementAt(i);
 
     if (fm->DatabaseName().Equals(aDatabaseName)) {
--- a/dom/indexedDB/TransactionThreadPool.cpp
+++ b/dom/indexedDB/TransactionThreadPool.cpp
@@ -159,20 +159,17 @@ TransactionThreadPool::Shutdown()
   }
 }
 
 nsresult
 TransactionThreadPool::Init()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
-  if (!mTransactionsInProgress.Init()) {
-    NS_WARNING("Failed to init hash!");
-    return NS_ERROR_FAILURE;
-  }
+  mTransactionsInProgress.Init();
 
   nsresult rv;
   mThreadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mThreadPool->SetThreadLimit(kThreadLimit);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -463,20 +460,17 @@ TransactionThreadPool::Dispatch(IDBTrans
   }
 
   if (!transactionInfo->objectStoreNames.AppendElements(objectStoreNames)) {
     NS_WARNING("Out of memory!");
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   if (autoDBTransactionInfo) {
-    if (!mTransactionsInProgress.Put(databaseId, autoDBTransactionInfo)) {
-      NS_WARNING("Failed to put!");
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
+    mTransactionsInProgress.Put(databaseId, autoDBTransactionInfo);
     autoDBTransactionInfo.forget();
   }
 
   return mThreadPool->Dispatch(transactionInfo->queue, NS_DISPATCH_NORMAL);
 }
 
 bool
 TransactionThreadPool::WaitForAllDatabasesToComplete(
--- a/dom/ipc/CrashReporterParent.cpp
+++ b/dom/ipc/CrashReporterParent.cpp
@@ -119,18 +119,17 @@ bool
 CrashReporterParent::GenerateHangCrashReport(const AnnotationTable* processNotes)
 {
     if (mChildDumpID.IsEmpty())
         return false;
 
     GenerateChildData(processNotes);
 
     CrashReporter::AnnotationTable notes;
-    if (!notes.Init(4))
-        return false;
+    notes.Init(4);
     notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID));
     if (!CrashReporter::AppendExtraData(mParentDumpID, notes))
         NS_WARNING("problem appending parent data to .extra");
     return true;
 }
 
 bool
 CrashReporterParent::GenerateChildData(const AnnotationTable* processNotes)
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -379,25 +379,25 @@ static nsInterfaceHashtable<nsPtrHashKey
 
 NS_IMETHODIMP
 TabChild::OpenDialog(PRUint32 aType, const nsACString& aName,
                      const nsACString& aFeatures,
                      nsIDialogParamBlock* aArguments,
                      nsIDOMElement* aFrameElement)
 {
   if (!gActiveDialogs.IsInitialized()) {
-    NS_ENSURE_STATE(gActiveDialogs.Init());
+    gActiveDialogs.Init();
   }
   InfallibleTArray<PRInt32> intParams;
   InfallibleTArray<nsString> stringParams;
   ParamsToArrays(aArguments, intParams, stringParams);
   PContentDialogChild* dialog =
     SendPContentDialogConstructor(aType, nsCString(aName),
                                   nsCString(aFeatures), intParams, stringParams);
-  NS_ENSURE_STATE(gActiveDialogs.Put(dialog, aArguments));
+  gActiveDialogs.Put(dialog, aArguments);
   nsIThread *thread = NS_GetCurrentThread();
   while (gActiveDialogs.GetWeak(dialog)) {
     if (!NS_ProcessNextEvent(thread)) {
       break;
     }
   }
   return NS_OK;
 }
--- a/dom/plugins/base/android/ANPAudio.cpp
+++ b/dom/plugins/base/android/ANPAudio.cpp
@@ -382,19 +382,23 @@ anp_audio_stop(ANPAudioTrack* s)
 bool
 anp_audio_isStopped(ANPAudioTrack* s)
 {
   return s->isStopped;
 }
 
 uint32_t
 anp_audio_trackLatency(ANPAudioTrack* s) {
-  // Bug 721835
-  NOT_IMPLEMENTED();
-  return 1;
+  // Hardcode an estimate of the system's audio latency. Flash hardcodes
+  // similar latency estimates for pre-Honeycomb devices that do not support
+  // ANPAudioTrackInterfaceV1's trackLatency(). The Android stock browser
+  // calls android::AudioTrack::latency(), an internal Android API that is
+  // not available in the public NDK:
+  // https://github.com/android/platform_external_webkit/commit/49bf866973cb3b2a6c74c0eab864e9562e4cbab1
+  return 100; // milliseconds
 }
 
 void InitAudioTrackInterfaceV0(ANPAudioTrackInterfaceV0 *i) {
   _assert(i->inSize == sizeof(*i));
   ASSIGN(i, newTrack);
   ASSIGN(i, deleteTrack);
   ASSIGN(i, start);
   ASSIGN(i, pause);
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1039,19 +1039,19 @@ NS_IMETHODIMP nsPluginInstanceOwner::Get
     *result = PL_strdup("US_ASCII");
   } else if (charset.EqualsLiteral("ISO-8859-1") ||
       !nsCRT::strncmp(PromiseFlatCString(charset).get(), "UTF", 3)) {
     *result = ToNewCString(charset);
   } else {
     if (!gCharsetMap) {
       const int NUM_CHARSETS = sizeof(charsets) / sizeof(moz2javaCharset);
       gCharsetMap = new nsDataHashtable<nsDepCharHashKey, const char*>();
-      if (!gCharsetMap || !gCharsetMap->Init(NUM_CHARSETS))
+      if (!gCharsetMap)
         return NS_ERROR_OUT_OF_MEMORY;
-
+      gCharsetMap->Init(NUM_CHARSETS);
       for (PRUint16 i = 0; i < NUM_CHARSETS; i++) {
         gCharsetMap->Put(charsets[i].mozName, charsets[i].javaName);
       }
     }
     // if found mapping, return it; otherwise return original charset
     const char *mapping;
     *result = gCharsetMap->Get(charset.get(), &mapping) ? PL_strdup(mapping) :
                                                           ToNewCString(charset);
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -132,17 +132,18 @@ PluginInstanceParent::~PluginInstancePar
             DeallocShmem(mRemoteImageDataShmem);
         }
     }
 }
 
 bool
 PluginInstanceParent::Init()
 {
-    return !!mScriptableObjects.Init();
+    mScriptableObjects.Init();
+    return true;
 }
 
 void
 PluginInstanceParent::ActorDestroy(ActorDestroyReason why)
 {
 #if defined(OS_WIN)
     if (why == AbnormalShutdown) {
         // If the plugin process crashes, this is the only
@@ -1537,17 +1538,18 @@ PluginInstanceParent::NPP_URLNotify(cons
 bool
 PluginInstanceParent::RegisterNPObjectForActor(
                                            NPObject* aObject,
                                            PluginScriptableObjectParent* aActor)
 {
     NS_ASSERTION(aObject && aActor, "Null pointers!");
     NS_ASSERTION(mScriptableObjects.IsInitialized(), "Hash not initialized!");
     NS_ASSERTION(!mScriptableObjects.Get(aObject, nsnull), "Duplicate entry!");
-    return !!mScriptableObjects.Put(aObject, aActor);
+    mScriptableObjects.Put(aObject, aActor);
+    return true;
 }
 
 void
 PluginInstanceParent::UnregisterNPObject(NPObject* aObject)
 {
     NS_ASSERTION(aObject, "Null pointer!");
     NS_ASSERTION(mScriptableObjects.IsInitialized(), "Hash not initialized!");
     NS_ASSERTION(mScriptableObjects.Get(aObject, nsnull), "Unknown entry!");
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -172,30 +172,19 @@ PluginModuleChild::Init(const std::strin
     PLUGIN_LOG_DEBUG_METHOD;
 
 #ifdef XP_WIN
     COMMessageFilter::Initialize(this);
 #endif
 
     NS_ASSERTION(aChannel, "need a channel");
 
-    if (!mObjectMap.Init()) {
-       NS_WARNING("Failed to initialize object hashtable!");
-       return false;
-    }
-
-    if (!mStringIdentifiers.Init()) {
-       NS_ERROR("Failed to initialize string identifier hashtable!");
-       return false;
-    }
-
-    if (!mIntIdentifiers.Init()) {
-       NS_ERROR("Failed to initialize int identifier hashtable!");
-       return false;
-    }
+    mObjectMap.Init();
+    mStringIdentifiers.Init();
+    mIntIdentifiers.Init();
 
     if (!InitGraphics())
         return false;
 
     mPluginFilename = aPluginFilename.c_str();
     nsCOMPtr<nsILocalFile> localFile;
     NS_NewLocalFile(NS_ConvertUTF8toUTF16(mPluginFilename),
                     true,
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -132,19 +132,17 @@ PluginModuleParent::PluginModuleParent(c
     , mClearSiteDataSupported(false)
     , mGetSitesWithDataSupported(false)
     , mNPNIface(NULL)
     , mPlugin(NULL)
     , mTaskFactory(this)
 {
     NS_ASSERTION(mSubprocess, "Out of memory!");
 
-    if (!mIdentifiers.Init()) {
-        NS_ERROR("Out of memory");
-    }
+    mIdentifiers.Init();
 
     Preferences::RegisterCallback(TimeoutChanged, kChildTimeoutPref, this);
     Preferences::RegisterCallback(TimeoutChanged, kParentTimeoutPref, this);
 }
 
 PluginModuleParent::~PluginModuleParent()
 {
     NS_ASSERTION(OkToCleanup(), "unsafe destruction");
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -268,22 +268,17 @@ NS_IMPL_ISUPPORTS3(nsDOMStorageManager,
 //static
 nsresult
 nsDOMStorageManager::Initialize()
 {
   gStorageManager = new nsDOMStorageManager();
   if (!gStorageManager)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  if (!gStorageManager->mStorages.Init()) {
-    delete gStorageManager;
-    gStorageManager = nsnull;
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
+  gStorageManager->mStorages.Init();
   NS_ADDREF(gStorageManager);
 
   // No observers needed in non-chrome
   if (XRE_GetProcessType() != GeckoProcessType_Default)
     return NS_OK;
 
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (!os)
--- a/dom/src/storage/nsDOMStorageMemoryDB.cpp
+++ b/dom/src/storage/nsDOMStorageMemoryDB.cpp
@@ -41,18 +41,17 @@
 #include "nsDOMError.h"
 #include "nsDOMStorage.h"
 #include "nsDOMStorageMemoryDB.h"
 #include "nsNetUtil.h"
 
 nsresult
 nsDOMStorageMemoryDB::Init(nsDOMStoragePersistentDB* aPreloadDB)
 {
-  if (!mData.Init(20))
-    return NS_ERROR_OUT_OF_MEMORY;
+  mData.Init(20);
 
   mPreloadDB = aPreloadDB;
   return NS_OK;
 }
 
 static PLDHashOperator
 AllKeyEnum(nsSessionStorageEntry* aEntry, void* userArg)
 {
@@ -81,20 +80,17 @@ nsDOMStorageMemoryDB::GetItemsTable(DOMS
     return NS_OK;
 
   *aMemoryStorage = nsnull;
 
   nsInMemoryStorage* storageData = new nsInMemoryStorage();
   if (!storageData)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  if (!storageData->mTable.Init()) {
-    delete storageData;
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
+  storageData->mTable.Init();
 
   if (mPreloadDB) {
     nsresult rv;
 
     nsTHashtable<nsSessionStorageEntry> keys;
     keys.Init();
 
     rv = mPreloadDB->GetAllKeys(aStorage, &keys);
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -634,21 +634,17 @@ RuntimeService::RegisterWorker(JSContext
 
     MutexAutoLock lock(mMutex);
 
     if (!mDomainMap.Get(domain, &domainInfo)) {
       NS_ASSERTION(!parent, "Shouldn't have a parent here!");
 
       domainInfo = new WorkerDomainInfo();
       domainInfo->mDomain = domain;
-
-      if (!mDomainMap.Put(domain, domainInfo)) {
-        delete domainInfo;
-        domainInfo = nsnull;
-      }
+      mDomainMap.Put(domain, domainInfo);
     }
 
     if (domainInfo) {
       queued = gMaxWorkersPerDomain &&
                domainInfo->ActiveWorkerCount() >= gMaxWorkersPerDomain &&
                !domain.IsEmpty();
 
       if (queued) {
@@ -691,23 +687,17 @@ RuntimeService::RegisterWorker(JSContext
 
     nsPIDOMWindow* window = aWorkerPrivate->GetWindow();
 
     nsTArray<WorkerPrivate*>* windowArray;
     if (!mWindowMap.Get(window, &windowArray)) {
       NS_ASSERTION(!parent, "Shouldn't have a parent here!");
 
       windowArray = new nsTArray<WorkerPrivate*>(1);
-
-      if (!mWindowMap.Put(window, windowArray)) {
-        delete windowArray;
-        UnregisterWorker(aCx, aWorkerPrivate);
-        JS_ReportOutOfMemory(aCx);
-        return false;
-      }
+      mWindowMap.Put(window, windowArray);
     }
 
     NS_ASSERTION(!windowArray->Contains(aWorkerPrivate),
                  "Already know about this worker!");
     windowArray->AppendElement(aWorkerPrivate);
   }
 
   if (!queued && !ScheduleWorker(aCx, aWorkerPrivate)) {
@@ -910,21 +900,18 @@ RuntimeService::ShutdownIdleThreads(nsIT
 nsresult
 RuntimeService::Init()
 {
   AssertIsOnMainThread();
 
   mIdleThreadTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
   NS_ENSURE_STATE(mIdleThreadTimer);
 
-  bool ok = mDomainMap.Init();
-  NS_ENSURE_STATE(ok);
-
-  ok = mWindowMap.Init();
-  NS_ENSURE_STATE(ok);
+  mDomainMap.Init();
+  mWindowMap.Init();
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   NS_ENSURE_TRUE(obs, NS_ERROR_FAILURE);
 
   nsresult rv =
     obs->AddObserver(this, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID, false);
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/embedding/components/commandhandler/src/nsCommandManager.cpp
+++ b/embedding/components/commandhandler/src/nsCommandManager.cpp
@@ -111,17 +111,17 @@ NS_INTERFACE_MAP_END
 /* void init (in nsIDOMWindow aWindow); */
 NS_IMETHODIMP
 nsCommandManager::Init(nsIDOMWindow *aWindow)
 {
   NS_ENSURE_ARG_POINTER(aWindow);
   
   NS_ASSERTION(aWindow, "Need non-null window here");
   mWindow = aWindow;      // weak ptr
-  NS_ENSURE_TRUE(mObserversTable.Init(), NS_ERROR_OUT_OF_MEMORY);
+  mObserversTable.Init();
   return NS_OK;
 }
 
 /* void commandStatusChanged (in DOMString aCommandName, in long aChangeFlags); */
 NS_IMETHODIMP
 nsCommandManager::CommandStatusChanged(const char * aCommandName)
 {
   nsCOMArray<nsIObserver>* commandObservers;
@@ -158,18 +158,17 @@ nsCommandManager::AddCommandObserver(nsI
 
   // XXX todo: handle special cases of aCommandToObserve being null, or empty
 
   // for each command in the table, we make a list of observers for that command
   nsCOMArray<nsIObserver>* commandObservers;
   if (!mObserversTable.Get(aCommandToObserve, &commandObservers))
   {
     nsAutoPtr<nsCOMArray<nsIObserver> > array(new nsCOMArray<nsIObserver>);
-    if (!array || !mObserversTable.Put(aCommandToObserve, array))
-      return NS_ERROR_OUT_OF_MEMORY;
+    mObserversTable.Put(aCommandToObserve, array);
 
     commandObservers = array.forget();
   }
 
   // need to check that this command observer hasn't already been registered
   PRInt32 existingIndex = commandObservers->IndexOf(aCommandObserver);
   if (existingIndex == -1)
     rv = commandObservers->AppendObject(aCommandObserver);
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -188,19 +188,17 @@ nsPermissionManager::GetXPCOMSingleton()
   return gPermissionManager;
 }
 
 nsresult
 nsPermissionManager::Init()
 {
   nsresult rv;
 
-  if (!mHostTable.Init()) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
+  mHostTable.Init();
 
   mObserverService = do_GetService("@mozilla.org/observer-service;1", &rv);
   if (NS_SUCCEEDED(rv)) {
     mObserverService->AddObserver(this, "profile-before-change", true);
     mObserverService->AddObserver(this, "profile-do-change", true);
   }
 
   if (IsChildProcess()) {
--- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp
@@ -118,19 +118,17 @@ NS_MEMORY_REPORTER_IMPLEMENT(Hunspell,
   HunspellGetCurrentAllocatedSize,
   "Memory used by the Hunspell spell checking engine.  This number accounts "
   "for the memory in use by Hunspell's internal data structures."
 )
 
 nsresult
 mozHunspell::Init()
 {
-  if (!mDictionaries.Init())
-    return NS_ERROR_OUT_OF_MEMORY;
-
+  mDictionaries.Init();
   LoadDictionaryList();
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->AddObserver(this, "profile-do-change", true);
     obs->AddObserver(this, "profile-after-change", true);
   }
 
--- a/extensions/spellcheck/src/mozPersonalDictionary.cpp
+++ b/extensions/spellcheck/src/mozPersonalDictionary.cpp
@@ -85,18 +85,18 @@ mozPersonalDictionary::mozPersonalDictio
 }
 
 mozPersonalDictionary::~mozPersonalDictionary()
 {
 }
 
 nsresult mozPersonalDictionary::Init()
 {
-  if (!mDictionaryTable.Init() || !mIgnoreTable.Init())
-    return NS_ERROR_OUT_OF_MEMORY;
+  mDictionaryTable.Init();
+  mIgnoreTable.Init();
 
   nsresult rv;
   nsCOMPtr<nsIObserverService> svc = 
            do_GetService("@mozilla.org/observer-service;1", &rv);
    
   if (NS_SUCCEEDED(rv) && svc) 
     rv = svc->AddObserver(this, "profile-do-change", true); // we want to reload the dictionary if the profile switches
 
--- a/gfx/layers/opengl/LayerManagerOGLProgram.h
+++ b/gfx/layers/opengl/LayerManagerOGLProgram.h
@@ -73,34 +73,34 @@ struct ProgramProfileOGL
    */
   static ProgramProfileOGL GetProfileFor(gl::ShaderProgramType aType,
                                          MaskType aMask);
 
   /**
    * returns true if such a shader program exists
    */
   static bool ProgramExists(gl::ShaderProgramType aType, MaskType aMask)
-  {
-    if (aType < 0 ||
-        aType >= gl::NumProgramTypes)
-      return false;
-
-    if (aMask < MaskNone ||
-        aMask >= NumMaskTypes)
-      return false;
-
-    if (aMask == Mask2d &&
-        (aType == gl::Copy2DProgramType ||
-         aType == gl::Copy2DRectProgramType))
-      return false;
-
-    return aMask != Mask3d ||
-           aType == gl::RGBARectLayerProgramType ||
-           aType == gl::RGBALayerProgramType;
-  }
+  {
+    if (aType < 0 ||
+        aType >= gl::NumProgramTypes)
+      return false;
+
+    if (aMask < MaskNone ||
+        aMask >= NumMaskTypes)
+      return false;
+
+    if (aMask == Mask2d &&
+        (aType == gl::Copy2DProgramType ||
+         aType == gl::Copy2DRectProgramType))
+      return false;
+
+    return aMask != Mask3d ||
+           aType == gl::RGBARectLayerProgramType ||
+           aType == gl::RGBALayerProgramType;
+  }
 
 
   /**
    * These two methods lookup the location of a uniform and attribute,
    * respectively. Returns -1 if the named uniform/attribute does not
    * have a location for the shaders represented by this profile.
    */
   GLint LookupUniformLocation(const char* aName)
@@ -165,18 +165,18 @@ private:
  * by a ProgramProfileOGL
  */
 class ShaderProgramOGL
 {
 public:
   typedef mozilla::gl::GLContext GLContext;
 
   ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile) :
-    mGL(aGL), mProgram(0), mProgramState(STATE_NEW),
-    mIsProjectionMatrixStale(false), mProfile(aProfile) { }
+    mIsProjectionMatrixStale(false), mGL(aGL), mProgram(0),
+    mProfile(aProfile), mProgramState(STATE_NEW) { }
 
 
   ~ShaderProgramOGL() {
     if (mProgram <= 0) {
       return;
     }
 
     nsRefPtr<GLContext> ctx = mGL->GetSharedContext();
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -4931,17 +4931,19 @@ gfxTextRun::BreakAndMeasureText(PRUint32
 
         // There can't be a word-wrap break opportunity at the beginning of the
         // line: if the width is too small for even one character to fit, it 
         // could be the first and last break opportunity on the line, and that
         // would trigger an infinite loop.
         if (!aSuppressInitialBreak || i > aStart) {
             bool lineBreakHere = mCharacterGlyphs[i].CanBreakBefore() == 1;
             bool hyphenation = haveHyphenation && hyphenBuffer[i - bufferStart];
-            bool wordWrapping = aCanWordWrap && *aBreakPriority <= eWordWrapBreak;
+            bool wordWrapping =
+                aCanWordWrap && mCharacterGlyphs[i].IsClusterStart() &&
+                *aBreakPriority <= eWordWrapBreak;
 
             if (lineBreakHere || hyphenation || wordWrapping) {
                 gfxFloat hyphenatedAdvance = advance;
                 if (!lineBreakHere && !wordWrapping) {
                     hyphenatedAdvance += aProvider->GetHyphenWidth();
                 }
             
                 if (lastBreak < 0 || width + hyphenatedAdvance - trimmableAdvance <= aWidth) {
@@ -5328,17 +5330,19 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun
         mSkipDrawing = true;
     }
 
     // Copy base glyph data, and DetailedGlyph data where present
     const CompressedGlyph *srcGlyphs = aSource->mCharacterGlyphs + aStart;
     CompressedGlyph *dstGlyphs = mCharacterGlyphs + aDest;
     for (PRUint32 i = 0; i < aLength; ++i) {
         CompressedGlyph g = srcGlyphs[i];
-        g.SetCanBreakBefore(dstGlyphs[i].CanBreakBefore());
+        g.SetCanBreakBefore(!g.IsClusterStart() ?
+            CompressedGlyph::FLAG_BREAK_TYPE_NONE :
+            dstGlyphs[i].CanBreakBefore());
         if (!g.IsSimpleGlyph()) {
             PRUint32 count = g.GetGlyphCount();
             if (count > 0) {
                 DetailedGlyph *dst = AllocateDetailedGlyphs(i + aDest, count);
                 if (dst) {
                     DetailedGlyph *src = aSource->GetDetailedGlyphs(i + aStart);
                     if (src) {
                         ::memcpy(dst, src, count * sizeof(DetailedGlyph));
--- a/image/src/imgLoader.cpp
+++ b/image/src/imgLoader.cpp
@@ -910,20 +910,18 @@ nsresult imgLoader::InitCache()
   NS_ADDREF(gCacheObserver);
 
   os->AddObserver(gCacheObserver, "memory-pressure", false);
   os->AddObserver(gCacheObserver, "chrome-flush-skin-caches", false);
   os->AddObserver(gCacheObserver, "chrome-flush-caches", false);
 
   gCacheTracker = new imgCacheExpirationTracker();
 
-  if (!sCache.Init())
-      return NS_ERROR_OUT_OF_MEMORY;
-  if (!sChromeCache.Init())
-      return NS_ERROR_OUT_OF_MEMORY;
+  sCache.Init();
+  sChromeCache.Init();
 
   PRInt32 timeweight;
   rv = Preferences::GetInt("image.cache.timeweight", &timeweight);
   if (NS_SUCCEEDED(rv))
     sCacheTimeWeight = timeweight / 1000.0;
   else
     sCacheTimeWeight = 0.5;
 
@@ -1078,18 +1076,17 @@ bool imgLoader::PutIntoCache(nsIURI *key
            ("[this=%p] imgLoader::PutIntoCache -- Replacing cached element", nsnull));
 
     RemoveFromCache(key);
   } else {
     PR_LOG(gImgLog, PR_LOG_DEBUG,
            ("[this=%p] imgLoader::PutIntoCache -- Element NOT already in the cache", nsnull));
   }
 
-  if (!cache.Put(spec, entry))
-    return false;
+  cache.Put(spec, entry);
 
   // We can be called to resurrect an evicted entry.
   if (entry->Evicted())
     entry->SetEvicted(false);
 
   // If we're resurrecting an entry with no proxies, put it back in the
   // tracker and queue.
   if (entry->HasNoProxies()) {
--- a/js/jsd/jsd_val.c
+++ b/js/jsd/jsd_val.c
@@ -796,17 +796,17 @@ jsd_GetValueClassName(JSDContext* jsdc, 
         JSObject* obj = JSVAL_TO_OBJECT(val);
         JS_BeginRequest(jsdc->dumbContext);
         call = JS_EnterCrossCompartmentCall(jsdc->dumbContext, obj);
         if(!call) {
             JS_EndRequest(jsdc->dumbContext);
 
             return NULL;
         }
-        jsdval->className = JS_GetClass(obj)->name;
+        jsdval->className = JS_GetDebugClassName(obj);
         JS_LeaveCrossCompartmentCall(call);
         JS_EndRequest(jsdc->dumbContext);
     }
     return jsdval->className;
 }
 
 JSDScript*
 jsd_GetScriptForValue(JSDContext* jsdc, JSDValue* jsdval)
--- a/js/jsd/test/test_jsval_retval.js
+++ b/js/jsd/test/test_jsval_retval.js
@@ -31,9 +31,12 @@ function run_test() {
         var wrapped = scope.getWrappedValue();
         // Do not try to print 'wrapped'; it may be an internal Call object
         // that will crash when you toString it. Different bug.
         do_check_eq(typeof(wrapped), "object");
         return Ci.jsdIExecutionHook.RETURN_CONTINUE;
     };
 
     f();
+
+    jsd.breakpointHook = null;
+    jsd = null;
 }
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -4123,16 +4123,17 @@ Parser::statement()
             return NULL;
         return pn;
 
       case TOK_DEBUGGER:
         pn = new_<DebuggerStatement>(tokenStream.currentToken().pos);
         if (!pn)
             return NULL;
         tc->sc->setFunIsHeavyweight();
+        tc->sc->setBindingsAccessedDynamically();
         break;
 
 #if JS_HAS_XML_SUPPORT
       case TOK_DEFAULT:
       {
         if (tc->sc->inStrictMode())
             return expressionStatement();
 
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -983,29 +983,59 @@ GCMarker::restoreValueArray(JSObject *ob
         }
     }
 
     JS_ASSERT(*vpp <= *endp);
     return true;
 }
 
 void
-GCMarker::processMarkStackOther(uintptr_t tag, uintptr_t addr)
+GCMarker::processMarkStackOther(SliceBudget &budget, uintptr_t tag, uintptr_t addr)
 {
     if (tag == TypeTag) {
         ScanTypeObject(this, reinterpret_cast<types::TypeObject *>(addr));
     } else if (tag == SavedValueArrayTag) {
         JS_ASSERT(!(addr & Cell::CellMask));
         JSObject *obj = reinterpret_cast<JSObject *>(addr);
         HeapValue *vp, *end;
         if (restoreValueArray(obj, (void **)&vp, (void **)&end))
             pushValueArray(obj, vp, end);
         else
             pushObject(obj);
+    } else if (tag == ArenaTag) {
+        ArenaHeader *aheader = reinterpret_cast<ArenaHeader *>(addr);
+        AllocKind thingKind = aheader->getAllocKind();
+        size_t thingSize = Arena::thingSize(thingKind);
+
+        for ( ; aheader; aheader = aheader->next) {
+            Arena *arena = aheader->getArena();
+            FreeSpan firstSpan(aheader->getFirstFreeSpan());
+            const FreeSpan *span = &firstSpan;
+
+            for (uintptr_t thing = arena->thingsStart(thingKind); ; thing += thingSize) {
+                JS_ASSERT(thing <= arena->thingsEnd());
+                if (thing == span->first) {
+                    if (!span->hasNext())
+                        break;
+                    thing = span->last;
+                    span = span->nextSpan();
+                } else {
+                    JSObject *object = reinterpret_cast<JSObject *>(thing);
+                    if (object->hasSingletonType())
+                        pushObject(object);
+                    budget.step();
+                }
+            }
+            if (budget.isOverBudget()) {
+                pushArenaList(aheader);
+                return;
+            }
+        }
     }
+
 #if JS_HAS_XML_SUPPORT
     else {
         JS_ASSERT(tag == XmlTag);
         MarkChildren(this, reinterpret_cast<JSXML *>(addr));
     }
 #endif
 }
 
@@ -1038,17 +1068,17 @@ GCMarker::processMarkStackTop(SliceBudge
     }
 
     if (tag == ObjectTag) {
         obj = reinterpret_cast<JSObject *>(addr);
         JS_COMPARTMENT_ASSERT(runtime, obj);
         goto scan_obj;
     }
 
-    processMarkStackOther(tag, addr);
+    processMarkStackOther(budget, tag, addr);
     return;
 
   scan_value_array:
     JS_ASSERT(vp <= end);
     while (vp != end) {
         const Value &v = *vp++;
         if (v.isString()) {
             JSString *str = v.toString();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/eif-generator.js
@@ -0,0 +1,54 @@
+// |jit-test| debug
+function f() {
+    let (x = 1) {
+        while (true) {
+            yield evalInFrame(0, "x");
+            x++;
+            let (y = 1) {
+                yield evalInFrame(0, "++y");
+                yield evalInFrame(0, "++y");
+            }
+        }
+    }
+}
+
+var gen = f();
+assertEq(gen.next(), 1);
+assertEq(gen.next(), 2);
+gc();
+assertEq(gen.next(), 3);
+gc();
+assertEq(gen.next(), 2);
+assertEq(gen.next(), 2);
+gc();
+assertEq(gen.next(), 3);
+gc();
+assertEq(gen.next(), 3);
+assertEq(gen.next(), 2);
+gc();
+assertEq(gen.next(), 3);
+gen = null;
+gc();
+
+function g() {
+    let (x = 1) {
+        while (true) {
+            var inner = function (inc) { x += inc; return evalInFrame(0, "x") };
+            assertEq(inner(0), x);
+            yield inner;
+            assertEq(inner(0), x);
+        }
+    }
+}
+
+var gen = g();
+var g1 = gen.next();
+var g2 = gen.next();
+gc();
+assertEq(g1(1), 2);
+assertEq(g2(1), 3);
+gc();
+assertEq(g1(1), 4);
+assertEq(g2(1), 5);
+gen = g1 = g2 = null;
+gc();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testBug755916.js
@@ -0,0 +1,13 @@
+// |jit-test| error:InternalError
+
+Object.defineProperty(this, "t2", {
+    get: function() {
+        for (p in h2) {
+            t2
+        }
+    }
+})
+h2 = {}
+mjitChunkLimit(8)
+h2.a = function() {}
+Object(t2)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testLetOverridingArgs.js
@@ -0,0 +1,5 @@
+function f1() { let (arguments = 42) { return arguments } }
+assertEq(f1(), 42);
+
+function f2() { let (arguments) { return arguments } }
+assertEq(f2(), undefined);
--- a/js/src/jit-test/tests/debug/Environment-gc-01.js
+++ b/js/src/jit-test/tests/debug/Environment-gc-01.js
@@ -4,16 +4,16 @@ var g = newGlobal('new-compartment');
 g.eval("function f(x) { return 2 * x; }");
 var dbg = Debugger(g);
 var env;
 dbg.onEnterFrame = function (frame) { env = frame.environment; };
 assertEq(g.f(22), 44);
 dbg.onEnterFrame = undefined;
 
 assertEq(env.find("x"), env);
-assertEq(env.names().join(","), "x");
+assertEq(env.names().join(","), "arguments,x");
 
 gc();
 g.gc(g);
 gc(env);
 
 assertEq(env.find("x"), env);
-assertEq(env.names().join(","), "x");
+assertEq(env.names().join(","), "arguments,x");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Environment-getVariable-12.js
@@ -0,0 +1,61 @@
+var g = newGlobal('new-compartment');
+var dbg = new Debugger;
+var gw = dbg.addDebuggee(g);
+
+var hits = 0;
+dbg.onDebuggerStatement = function (frame) {
+    hits++;
+    assertEq(frame.environment.parent.getVariable('y'), true);
+};
+
+g.eval("var g;" +
+       "function f(x) {" +
+       "  let (y = x) {" +
+       "    if (x)" +
+       "      g = function() { eval('debugger') };" +
+       "    else" +
+       "      g();" +
+       "  }" +
+       "}" +
+       "f(true);" +
+       "f(false);");
+assertEq(hits, 1);
+
+var hits = 0;
+dbg.onDebuggerStatement = function (frame) {
+    hits++;
+    assertEq(frame.environment.parent.getVariable('y'), 1);
+    assertEq(frame.environment.parent.names().indexOf('z'), -1);
+};
+
+g.eval("var g;" +
+       "let (y = 1) {" +
+       "  g = function () { debugger; };" +
+       "  let (z = 2) {" +
+       "    g();" +
+       "  }"+
+       "}");
+assertEq(hits, 1);
+
+var hits = 0;
+dbg.onDebuggerStatement = function (frame) {
+    hits++;
+    var e = frame.older.environment.parent;
+    assertEq(e.getVariable('z'), true);
+    e = e.parent;
+    assertEq(e.getVariable('y'), true);
+};
+
+g.eval("var g;" +
+       "function h() { debugger };" +
+       "for (var x of [true, false]) {" +
+       "  let (y = x) {" +
+       "    let (z = x) {" +
+       "      if (x)" +
+       "        g = function () { print(z); h() };" +
+       "      else" +
+       "        g();" +
+       "    }" +
+       "  }" +
+       "}");
+assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Environment-names-01.js
+++ b/js/src/jit-test/tests/debug/Environment-names-01.js
@@ -2,16 +2,18 @@
 
 var g = newGlobal('new-compartment');
 var dbg = Debugger(g);
 var hits = 0;
 g.h = function () {
     var env = dbg.getNewestFrame().environment;
     var names = env.names();
     assertEq(names.indexOf("a") !== -1, true);
-    assertEq(names.indexOf("b") !== -1, true);
-    assertEq(names.indexOf("isPrototypeOf") !== -1, true);
+
+    // FIXME: Bug 748592 - proxies don't correctly propagate JSITER_HIDDEN
+    //assertEq(names.indexOf("b") !== -1, true);
+    //assertEq(names.indexOf("isPrototypeOf") !== -1, true);
     hits++;
 };
 g.eval("var obj = {a: 1};\n" +
        "Object.defineProperty(obj, 'b', {value: 2});\n" +
        "with (obj) h();");
 assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Frame-environment-04.js
+++ b/js/src/jit-test/tests/debug/Frame-environment-04.js
@@ -1,12 +1,12 @@
 // frame.environment can be called from the onEnterFrame hook.
 
 var g = newGlobal('new-compartment');
 g.eval("function f(x) { return 2 * x; }");
 var dbg = Debugger(g);
 var hits = 0;
 dbg.onEnterFrame = function (frame) {
-    assertEq(frame.environment.names().join(","), "x");
+    assertEq(frame.environment.names().join(","), "arguments,x");
     hits++;
 };
 assertEq(g.f(22), 44);
 assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Frame-eval-08.js
+++ b/js/src/jit-test/tests/debug/Frame-eval-08.js
@@ -1,15 +1,23 @@
-// Test that 'arguments' access in a function that doesn't expect 'arguments'
-// doesn't crash.
-
-// TODO bug 659577: the debugger should be improved to throw an error in such
-// cases rather than silently returning whatever it finds on the scope chain.
+// The arguments can escape from a function via a debugging hook.
 
 var g = newGlobal('new-compartment');
 var dbg = new Debugger(g);
 
 // capture arguments object and test function
+var args, testfn;
 dbg.onDebuggerStatement = function (frame) {
-    args = frame.eval("arguments");
+    args = frame.eval("arguments").return;
+    testfn = frame.eval("test").return;
 };
 g.eval("function f() { debugger; }");
+g.eval("var test = " + function test(args) {
+        assertEq(args.length, 3);
+        assertEq(args[0], this);
+        assertEq(args[1], f);
+        assertEq(args[2].toString(), "[object Object]");
+        return 42;
+    } + ";");
 g.eval("f(this, f, {});");
+
+var cv = testfn.apply(null, [args]);
+assertEq(cv.return, 42);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-eval-11.js
@@ -0,0 +1,15 @@
+// The arguments can escape from a function via a debugging hook.
+
+var g = newGlobal('new-compartment');
+var dbg = new Debugger(g);
+
+// capture arguments object and test function
+var hits = 0;
+dbg.onDebuggerStatement = function (frame) {
+    assertEq(frame.older.eval('arguments[0]').return, 'ponies');
+    hits++;
+};
+g.eval("function g() { debugger; }");
+g.eval("function f() { g(); }");
+g.eval("f('ponies')");
+assertEq(hits, 1);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-eval-12.js
@@ -0,0 +1,19 @@
+// The arguments can escape from a function via a debugging hook.
+
+var g = newGlobal('new-compartment');
+var dbg = new Debugger(g);
+
+// capture arguments object and test function
+var hits = 0;
+dbg.onDebuggerStatement = function (frame) {
+    try {
+        frame.older.environment.parent.getVariable('arguments')
+    } catch (e) {
+        assertEq(''+e, "Error: Debugger scope is not live");
+        hits++;
+    }
+};
+g.eval("function h() { debugger; }");
+g.eval("function f() { var x = 0; return function() { x++; h() } }");
+g.eval("f('ponies')()");
+assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-03.js
@@ -1,17 +1,16 @@
 // arguments works in evalWithBindings (it does not interpose a function scope)
-// when the function expects 'arguments'
 var g = newGlobal('new-compartment');
 var dbg = new Debugger;
 var global = dbg.addDebuggee(g);
 var hits = 0;
 dbg.onDebuggerStatement = function (frame) {
     var argc = frame.arguments.length;
     assertEq(argc, 7);
     assertEq(frame.evalWithBindings("arguments[prop]", {prop: "length"}).return, argc);
     for (var i = 0; i < argc; i++)
         assertEq(frame.evalWithBindings("arguments[i]", {i: i}).return, frame.arguments[i]);
     hits++;
 };
-g.eval("function f() { eval('arguments'); debugger; }");
+g.eval("function f() { debugger; }");
 g.eval("f(undefined, -0, NaN, '\uffff', Array.prototype, Math, f);");
 assertEq(hits, 1);
--- a/js/src/jit-test/tests/debug/Frame-onPop-21.js
+++ b/js/src/jit-test/tests/debug/Frame-onPop-21.js
@@ -11,16 +11,17 @@ dbg.onDebuggerStatement = function handl
 };
 
 function handlePop(c) {
     log += ')';
 
     // Arguments must be live.
     assertEq(this.eval('a').return, 'frieze');
     assertEq(this.eval('b = "architrave"').return, 'architrave');
+    assertEq(this.eval('arguments[1]').return, 'architrave');
     assertEq(this.eval('b').return, 'architrave');
 
     // function-scope variables must be live.
     assertEq(this.eval('x').return, 'entablature');
     assertEq(this.eval('y = "cornice"').return, 'cornice');
     assertEq(this.eval('y').return, 'cornice');
 }
 
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-call-newvar.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-call-newvar.js
@@ -1,13 +1,21 @@
 // |jit-test| mjitalways;debug
 setDebug(true);
 
 function callee() {
-  evalInFrame(1, "var x = 'success'");
+  var caught = false;
+  try {
+    // attempting to add a new binding to an existing scope is a dynamic error
+    evalInFrame(1, "var y = 'success'");
+  } catch (e) {
+    assertEq(String.prototype.indexOf.call(e, "TypeError"), 0);
+    caught = true;
+  }
+  assertEq(caught, true);
 }
 function caller(code) {
   eval(code);
   callee();
   return x;
 }
-assertEq(caller('var y = "ignominy"'), "success");
+assertEq(caller('var x = "success"'), "success");
 assertEq(typeof x, "undefined");
--- a/js/src/jit-test/tests/jaeger/bug563000/eif-getter-newvar.js
+++ b/js/src/jit-test/tests/jaeger/bug563000/eif-getter-newvar.js
@@ -1,10 +1,10 @@
 // |jit-test| mjitalways;debug
 setDebug(true);
 
 this.__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
-function caller(code, obj) {
-  eval(code); // Make the compiler give up on binding analysis.
+function caller(obj) {
+  var x = 'ignominy';
   obj.someProperty;
   return x;
 }
-assertEq(caller("var y = 'ignominy'", this), "success");
+assertEq(caller(this), "success");
--- 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.
+function caller(obj) {
+  var x = 'ignominy';
   return x;
 }
-trap(caller, 32, "var x = 'success'; nop()");
-assertEq(caller("var y = 'ignominy'", this), "success");
+trap(caller, 9 /* getlocal 'x' */, "var x = 'success'; nop()");
+assertEq(caller(this), "success");
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -785,16 +785,17 @@ JSRuntime::JSRuntime()
     NaNValue(UndefinedValue()),
     negativeInfinityValue(UndefinedValue()),
     positiveInfinityValue(UndefinedValue()),
     emptyString(NULL),
     debugMode(false),
     profilingScripts(false),
     alwaysPreserveCode(false),
     hadOutOfMemory(false),
+    debugScopes(NULL),
     data(NULL),
 #ifdef JS_THREADSAFE
     gcLock(NULL),
     gcHelperThread(thisFromCtor()),
 #endif
     defaultFreeOp_(thisFromCtor(), false, false),
     debuggerMutations(0),
     securityCallbacks(const_cast<JSSecurityCallbacks *>(&NullSecurityCallbacks)),
@@ -874,30 +875,38 @@ JSRuntime::init(uint32_t maxbytes)
         return false;
 
     if (!stackSpace.init())
         return false;
 
     if (!scriptFilenameTable.init())
         return false;
 
+    debugScopes = this->new_<DebugScopes>(this);
+    if (!debugScopes || !debugScopes->init()) {
+        Foreground::delete_(debugScopes);
+        return false;
+    }
+
     nativeStackBase = GetNativeStackBase();
     return true;
 }
 
 JSRuntime::~JSRuntime()
 {
+    JS_ASSERT(onOwnerThread());
+
+    delete_(debugScopes);
+
     /*
      * Even though all objects in the compartment are dead, we may have keep
      * some filenames around because of gcKeepAtoms.
      */
     FreeScriptFilenames(this);
 
-    JS_ASSERT(onOwnerThread());
-
 #ifdef DEBUG
     /* Don't hurt everyone in leaky ol' Mozilla with a fatal JS_ASSERT! */
     if (!JS_CLIST_IS_EMPTY(&contextList)) {
         unsigned cxcount = 0;
         for (ContextIter acx(this); !acx.done(); acx.next()) {
             fprintf(stderr,
 "JS API usage error: found live context at %p\n",
                     (void *) acx.get());
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1022,20 +1022,21 @@ JSContext::JSContext(JSRuntime *rt)
 #ifdef JS_METHODJIT
     methodJitEnabled(false),
 #endif
     inferenceEnabled(false),
 #ifdef MOZ_TRACE_JSCALLS
     functionCallback(NULL),
 #endif
     enumerators(NULL),
+#ifdef DEBUG
+    stackIterAssertionEnabled(true),
+    okToAccessUnaliasedBindings(0),
+#endif
     activeCompilations(0)
-#ifdef DEBUG
-    , stackIterAssertionEnabled(true)
-#endif
 {
     PodZero(&link);
 #ifdef JSGC_ROOT_ANALYSIS
     PodArrayZero(thingGCRooters);
 #ifdef DEBUG
     skipGCRooters = NULL;
 #endif
 #endif
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -98,16 +98,17 @@ namespace js {
 
 namespace mjit {
 class JaegerRuntime;
 }
 
 class MathCache;
 class WeakMapBase;
 class InterpreterFrames;
+class DebugScopes;
 
 /*
  * GetSrcNote cache to avoid O(n^2) growth in finding a source note for a
  * given pc in a script. We use the script->code pointer to tag the cache,
  * instead of the script address itself, so that source notes are always found
  * by offset from the bytecode with which they were generated.
  */
 struct GSNCache {
@@ -696,16 +697,19 @@ struct JSRuntime : js::RuntimeFriendFiel
     JSBool              hadOutOfMemory;
 
     /*
      * Linked list of all js::Debugger objects. This may be accessed by the GC
      * thread, if any, or a thread that is in a request and holds gcLock.
      */
     JSCList             debuggerList;
 
+    /* Bookkeeping information for debug scope objects. */
+    js::DebugScopes     *debugScopes;
+
     /* Client opaque pointers */
     void                *data;
 
 #ifdef JS_THREADSAFE
     /* These combine to interlock the GC and new requests. */
     PRLock              *gcLock;
 
     js::GCHelperThread  gcHelperThread;
@@ -1258,17 +1262,16 @@ struct JSContext : js::ContextFriendFiel
     }
 
     inline void* mallocNoReport(size_t bytes) {
         JS_ASSERT(bytes != 0);
         return runtime->malloc_(bytes, NULL);
     }
 
     inline void* calloc_(size_t bytes) {
-        JS_ASSERT(bytes != 0);
         return runtime->calloc_(bytes, this);
     }
 
     inline void* realloc_(void* p, size_t bytes) {
         return runtime->realloc_(p, bytes, this);
     }
 
     inline void* realloc_(void* p, size_t oldBytes, size_t newBytes) {
@@ -1298,31 +1301,37 @@ struct JSContext : js::ContextFriendFiel
 
     void setPendingException(js::Value v);
 
     void clearPendingException() {
         this->throwing = false;
         this->exception.setUndefined();
     }
 
+#ifdef DEBUG
+    /*
+     * Controls whether a quadratic-complexity assertion is performed during
+     * stack iteration; defaults to true.
+     */
+    bool stackIterAssertionEnabled;
+
+    /*
+     * When greather than zero, it is ok to accessed non-aliased fields of
+     * ScopeObjects because the accesses are coming from the DebugScopeProxy.
+     */
+    unsigned okToAccessUnaliasedBindings;
+#endif
+
     /*
      * Count of currently active compilations.
      * When there are compilations active for the context, the GC must not
      * purge the ParseMapPool.
      */
     unsigned activeCompilations;
 
-#ifdef DEBUG
-    /*
-     * Controls whether a quadratic-complexity assertion is performed during
-     * stack iteration, defaults to true.
-     */
-    bool stackIterAssertionEnabled;
-#endif
-
     /*
      * See JS_SetTrustedPrincipals in jsapi.h.
      * Note: !cx->compartment is treated as trusted.
      */
     bool runningWithTrustedPrincipals() const;
 
     JS_FRIEND_API(size_t) sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf) const;
 
@@ -1340,16 +1349,33 @@ struct JSContext : js::ContextFriendFiel
      * threshold when p is not null. The function takes the pointer and not
      * a boolean flag to minimize the amount of code in its inlined callers.
      */
     JS_FRIEND_API(void) checkMallocGCPressure(void *p);
 }; /* struct JSContext */
 
 namespace js {
 
+class AutoAllowUnaliasedVarAccess
+{
+    JSContext *cx;
+  public:
+    AutoAllowUnaliasedVarAccess(JSContext *cx) : cx(cx) {
+#ifdef DEBUG
+        cx->okToAccessUnaliasedBindings++;
+#endif
+    }
+    ~AutoAllowUnaliasedVarAccess() {
+#ifdef DEBUG
+        JS_ASSERT(cx->okToAccessUnaliasedBindings);
+        cx->okToAccessUnaliasedBindings--;
+#endif
+    }
+};
+
 struct AutoResolving {
   public:
     enum Kind {
         LOOKUP,
         WATCH
     };
 
     AutoResolving(JSContext *cx, JSObject *obj, jsid id, Kind kind = LOOKUP
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -404,26 +404,20 @@ JSCompartment::markTypes(JSTracer *trc)
     JS_ASSERT(activeAnalysis || gcPreserveCode);
 
     for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
         JSScript *script = i.get<JSScript>();
         MarkScriptRoot(trc, &script, "mark_types_script");
         JS_ASSERT(script == i.get<JSScript>());
     }
 
-    for (size_t thingKind = FINALIZE_OBJECT0;
-         thingKind < FINALIZE_OBJECT_LIMIT;
-         thingKind++) {
-        for (CellIterUnderGC i(this, AllocKind(thingKind)); !i.done(); i.next()) {
-            JSObject *object = i.get<JSObject>();
-            if (object->hasSingletonType()) {
-                MarkObjectRoot(trc, &object, "mark_types_singleton");
-                JS_ASSERT(object == i.get<JSObject>());
-            }
-        }
+    for (size_t thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) {
+        ArenaHeader *aheader = arenas.getFirstArena(static_cast<AllocKind>(thingKind));
+        if (aheader)
+            rt->gcMarker.pushArenaList(aheader);
     }
 
     for (CellIterUnderGC i(this, FINALIZE_TYPE_OBJECT); !i.done(); i.next()) {
         types::TypeObject *type = i.get<types::TypeObject>();
         MarkTypeObjectRoot(trc, &type, "mark_types_scan");
         JS_ASSERT(type == i.get<types::TypeObject>());
     }
 }
@@ -620,18 +614,21 @@ JSCompartment::setDebugModeFromC(JSConte
         if (b && onStack) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_IDLE);
             return false;
         }
     }
 
     debugModeBits = (debugModeBits & ~unsigned(DebugFromC)) | (b ? DebugFromC : 0);
     JS_ASSERT(debugMode() == enabledAfter);
-    if (enabledBefore != enabledAfter)
+    if (enabledBefore != enabledAfter) {
         updateForDebugMode(cx->runtime->defaultFreeOp(), dmgc);
+        if (!enabledAfter)
+            cx->runtime->debugScopes->onCompartmentLeaveDebugMode(this);
+    }
     return true;
 }
 
 void
 JSCompartment::updateForDebugMode(FreeOp *fop, AutoDebugModeGC &dmgc)
 {
     for (ContextIter acx(rt); !acx.done(); acx.next()) {
         if (acx->compartment == this) 
@@ -693,16 +690,17 @@ JSCompartment::removeDebuggee(FreeOp *fo
         debuggeesEnum->removeFront();
     else
         debuggees.remove(global);
 
     if (debuggees.empty()) {
         debugModeBits &= ~DebugFromJS;
         if (wasEnabled && !debugMode()) {
             AutoDebugModeGC dmgc(rt);
+            fop->runtime()->debugScopes->onCompartmentLeaveDebugMode(this);
             updateForDebugMode(fop, dmgc);
         }
     }
 }
 
 void
 JSCompartment::clearBreakpointsIn(FreeOp *fop, js::Debugger *dbg, JSObject *handler)
 {
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -571,44 +571,48 @@ JS_GetFrameScopeChain(JSContext *cx, JSS
 {
     StackFrame *fp = Valueify(fpArg);
     JS_ASSERT(cx->stack.space().containsSlow(fp));
 
     js::AutoCompartment ac(cx, fp->scopeChain());
     if (!ac.enter())
         return NULL;
 
-    /* Force creation of argument and call objects if not yet created */
-    (void) JS_GetFrameCallObject(cx, Jsvalify(fp));
-    return GetScopeChain(cx, fp);
+    return GetDebugScopeForFrame(cx, fp);
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fpArg)
 {
     StackFrame *fp = Valueify(fpArg);
     JS_ASSERT(cx->stack.space().containsSlow(fp));
 
-    if (!fp->compartment()->debugMode())
-        return NULL;
-
     if (!fp->isFunctionFrame())
         return NULL;
 
-    js::AutoCompartment ac(cx, fp->scopeChain());
-    if (!ac.enter())
-        return NULL;
+    JSObject *o = GetDebugScopeForFrame(cx, fp);
 
     /*
-     * XXX ill-defined: null return here means error was reported, unlike a
-     *     null returned above or in the #else
+     * Given that fp is a function frame and GetDebugScopeForFrame always fills
+     * in missing scopes, we can expect to find fp's CallObject on 'o'. Note:
+     *  - GetDebugScopeForFrame wraps every ScopeObject (missing or not) with
+     *    a DebugScopeObject proxy.
+     *  - If fp is an eval-in-function, then fp has no callobj of its own and
+     *    JS_GetFrameCallObject will return the innermost function's callobj.
      */
-    if (!fp->hasCallObj() && fp->isNonEvalFunctionFrame())
-        return CallObject::createForFunction(cx, fp);
-    return &fp->callObj();
+    while (o) {
+        ScopeObject &scope = o->asDebugScope().scope();
+        if (scope.isCall()) {
+            JS_ASSERT_IF(cx->compartment->debugMode() && fp->isNonEvalFunctionFrame(),
+                         fp == scope.asCall().maybeStackFrame());
+            return o;
+        }
+        o = o->enclosingScope();
+    }
+    return NULL;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetFrameThis(JSContext *cx, JSStackFrame *fpArg, jsval *thisv)
 {
     StackFrame *fp = Valueify(fpArg);
     if (fp->isDummyFrame())
         return false;
@@ -659,16 +663,24 @@ JS_IsConstructorFrame(JSContext *cx, JSS
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp)
 {
     return Valueify(fp)->maybeCalleev().toObjectOrNull();
 }
 
+JS_PUBLIC_API(const char *)
+JS_GetDebugClassName(JSObject *obj)
+{
+    if (obj->isDebugScope())
+        return obj->asDebugScope().scope().getClass()->name;
+    return obj->getClass()->name;
+}
+
 JS_PUBLIC_API(JSBool)
 JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
 {
     return Valueify(fp)->isDebuggerFrame();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp)
@@ -841,76 +853,103 @@ GetPropertyDesc(JSContext *cx, JSObject 
 
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
 {
     assertSameCompartment(cx, obj);
+    uint32_t i = 0;
+    JSPropertyDesc *pd = NULL;
 
-    Class *clasp = obj->getClass();
+    if (obj->isDebugScope()) {
+        AutoIdVector props(cx);
+        if (!Proxy::enumerate(cx, obj, props))
+            return false;
+
+        pd = (JSPropertyDesc *)cx->calloc_(props.length() * sizeof(JSPropertyDesc));
+        if (!pd)
+            return false;
+
+        for (i = 0; i < props.length(); ++i) {
+            if (!js_AddRoot(cx, &pd[i].id, NULL))
+                goto bad;
+            pd[i].id = IdToValue(props[i]);
+            if (!js_AddRoot(cx, &pd[i].value, NULL))
+                goto bad;
+            if (!Proxy::get(cx, obj, obj, props[i], &pd[i].value))
+                goto bad;
+        }
+
+        pda->length = props.length();
+        pda->array = pd;
+        return true;
+    }
+
+    Class *clasp;
+    clasp = obj->getClass();
     if (!obj->isNative() || (clasp->flags & JSCLASS_NEW_ENUMERATE)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_CANT_DESCRIBE_PROPS, clasp->name);
-        return JS_FALSE;
+        return false;
     }
     if (!clasp->enumerate(cx, obj))
-        return JS_FALSE;
+        return false;
 
     /* Return an empty pda early if obj has no own properties. */
     if (obj->nativeEmpty()) {
         pda->length = 0;
         pda->array = NULL;
-        return JS_TRUE;
+        return true;
     }
 
-    uint32_t n = obj->propertyCount();
-    JSPropertyDesc *pd = (JSPropertyDesc *) cx->malloc_(size_t(n) * sizeof(JSPropertyDesc));
+    pd = (JSPropertyDesc *)cx->malloc_(obj->propertyCount() * sizeof(JSPropertyDesc));
     if (!pd)
-        return JS_FALSE;
-    uint32_t i = 0;
+        return false;
     for (Shape::Range r = obj->lastProperty()->all(); !r.empty(); r.popFront()) {
         if (!js_AddRoot(cx, &pd[i].id, NULL))
             goto bad;
         if (!js_AddRoot(cx, &pd[i].value, NULL))
             goto bad;
         Shape *shape = const_cast<Shape *>(&r.front());
         if (!GetPropertyDesc(cx, obj, shape, &pd[i]))
             goto bad;
         if ((pd[i].flags & JSPD_ALIAS) && !js_AddRoot(cx, &pd[i].alias, NULL))
             goto bad;
-        if (++i == n)
+        if (++i == obj->propertyCount())
             break;
     }
     pda->length = i;
     pda->array = pd;
-    return JS_TRUE;
+    return true;
 
 bad:
     pda->length = i + 1;
     pda->array = pd;
     JS_PutPropertyDescArray(cx, pda);
-    return JS_FALSE;
+    return false;
 }
 
 JS_PUBLIC_API(void)
 JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda)
 {
     JSPropertyDesc *pd;
     uint32_t i;
 
     pd = pda->array;
     for (i = 0; i < pda->length; i++) {
         js_RemoveRoot(cx->runtime, &pd[i].id);
         js_RemoveRoot(cx->runtime, &pd[i].value);
         if (pd[i].flags & JSPD_ALIAS)
             js_RemoveRoot(cx->runtime, &pd[i].alias);
     }
     cx->free_(pd);
+    pda->array = NULL;
+    pda->length = 0;
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(JSBool)
 JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler handler, void *closure)
 {
     rt->debugHooks.debuggerHandler = handler;
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -301,16 +301,27 @@ JS_SetFrameReturnValue(JSContext *cx, JS
  * this API cannot fail. A null return means "no callee": fp is a global or
  * eval-from-global frame, not a call frame.
  */
 extern JS_PUBLIC_API(JSObject *)
 JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp);
 
 /************************************************************************/
 
+/*
+ * This is almost JS_GetClass(obj)->name except that certain debug-only
+ * proxies are made transparent. In particular, this function turns the class
+ * of any scope (returned via JS_GetFrameScopeChain or JS_GetFrameCalleeObject)
+ * from "Proxy" to "Call", "Block", "With" etc.
+ */
+extern JS_PUBLIC_API(const char *)
+JS_GetDebugClassName(JSObject *obj);
+
+/************************************************************************/
+
 extern JS_PUBLIC_API(const char *)
 JS_GetScriptFilename(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(const jschar *)
 JS_GetScriptSourceMap(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(unsigned)
 JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -261,17 +261,17 @@ js_ValueToFunction(JSContext *cx, const 
 
 extern JSObject *
 js_ValueToCallableObject(JSContext *cx, js::Value *vp, unsigned flags);
 
 extern void
 js_ReportIsNotFunction(JSContext *cx, const js::Value *vp, unsigned flags);
 
 extern void
-js_PutCallObject(js::StackFrame *fp);
+js_PutCallObject(js::StackFrame *fp, js::CallObject &callobj);
 
 namespace js {
 
 /*
  * Function extended with reserved slots for use by various kinds of functions.
  * Most functions do not have these extensions, but enough are that efficient
  * storage is required (no malloc'ed reserved slots).
  */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2320,16 +2320,17 @@ MarkRuntime(JSTracer *trc, bool useSaved
 
 #ifdef JS_METHODJIT
     /* We need to expand inline frames before stack scanning. */
     for (CompartmentsIter c(rt); !c.done(); c.next())
         mjit::ExpandInlineFrames(c);
 #endif
 
     rt->stackSpace.mark(trc);
+    rt->debugScopes->mark(trc);
 
     /* The embedding can register additional roots here. */
     if (JSTraceDataOp op = rt->gcBlackRootsTraceOp)
         (*op)(trc, rt->gcBlackRootsData);
 
     /* During GC, this buffers up the gray roots and doesn't mark them. */
     if (JSTraceDataOp op = rt->gcGrayRootsTraceOp) {
         if (IS_GC_MARKING_TRACER(trc)) {
@@ -3173,16 +3174,17 @@ SweepPhase(JSRuntime *rt, JSGCInvocation
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_START);
         if (rt->gcFinalizeCallback)
             rt->gcFinalizeCallback(&fop, JSFINALIZE_START);
     }
 
     /* Finalize unreachable (key,value) pairs in all weak maps. */
     WeakMapBase::sweepAll(&rt->gcMarker);
+    rt->debugScopes->sweep();
 
     SweepAtomState(rt);
 
     /* Collect watch points associated with unreachable objects. */
     WatchpointMap::sweepAll(rt);
 
     /* Detach unreachable debuggers and global objects from each other. */
     Debugger::sweepAll(&fop);
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -886,16 +886,17 @@ struct GCMarker : public JSTracer {
      * the explicit tags to distinguish them when it cannot be deduced from
      * the context of push or pop operation.
      */
     enum StackTag {
         ValueArrayTag,
         ObjectTag,
         TypeTag,
         XmlTag,
+        ArenaTag,
         SavedValueArrayTag,
         LastTag = SavedValueArrayTag
     };
 
     static const uintptr_t StackTagMask = 7;
 
     static void staticAsserts() {
         JS_STATIC_ASSERT(StackTagMask >= uintptr_t(LastTag));
@@ -912,16 +913,20 @@ struct GCMarker : public JSTracer {
     void start(JSRuntime *rt);
     void stop();
     void reset();
 
     void pushObject(JSObject *obj) {
         pushTaggedPtr(ObjectTag, obj);
     }
 
+    void pushArenaList(gc::ArenaHeader *firstArena) {
+        pushTaggedPtr(ArenaTag, firstArena);
+    }
+
     void pushType(types::TypeObject *type) {
         pushTaggedPtr(TypeTag, type);
     }
 
 #if JS_HAS_XML_SUPPORT
     void pushXML(JSXML *xml) {
         pushTaggedPtr(XmlTag, xml);
     }
@@ -1011,17 +1016,17 @@ struct GCMarker : public JSTracer {
 
     bool isMarkStackEmpty() {
         return stack.isEmpty();
     }
 
     bool restoreValueArray(JSObject *obj, void **vpp, void **endp);
     void saveValueRanges();
     inline void processMarkStackTop(SliceBudget &budget);
-    void processMarkStackOther(uintptr_t tag, uintptr_t addr);
+    void processMarkStackOther(SliceBudget &budget, uintptr_t tag, uintptr_t addr);
 
     void appendGrayRoot(void *thing, JSGCTraceKind kind);
 
     /* The color is only applied to objects, functions and xml. */
     uint32_t color;
 
     DebugOnly<bool> started;
 
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -102,196 +102,16 @@
 #if defined(JS_METHODJIT) && defined(JS_MONOIC)
 #include "methodjit/MonoIC.h"
 #endif
 
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 
-/*
- * We can't determine in advance which local variables can live on the stack and
- * be freed when their dynamic scope ends, and which will be closed over and
- * need to live in the heap.  So we place variables on the stack initially, note
- * when they are closed over, and copy those that are out to the heap when we
- * leave their dynamic scope.
- *
- * The bytecode compiler produces a tree of block objects accompanying each
- * JSScript representing those lexical blocks in the script that have let-bound
- * variables associated with them.  These block objects are never modified, and
- * never become part of any function's scope chain.  Their parent slots point to
- * the innermost block that encloses them, or are NULL in the outermost blocks
- * within a function or in eval or global code.
- *
- * When we are in the static scope of such a block, blockChain points to its
- * compiler-allocated block object; otherwise, it is NULL.
- *
- * scopeChain is the current scope chain, including 'call' and 'block' objects
- * for those function calls and lexical blocks whose static scope we are
- * currently executing in, and 'with' objects for with statements; the chain is
- * typically terminated by a global object.  However, as an optimization, the
- * young end of the chain omits block objects we have not yet cloned.  To create
- * a closure, we clone the missing blocks from blockChain (which is always
- * current), place them at the head of scopeChain, and use that for the
- * closure's scope chain.  If we never close over a lexical block, we never
- * place a mutable clone of it on scopeChain.
- *
- * This lazy cloning is implemented in GetScopeChain, which is also used in
- * some other cases --- entering 'with' blocks, for example.
- */
-JSObject *
-js::GetScopeChain(JSContext *cx, StackFrame *fp)
-{
-    StaticBlockObject *sharedBlock = fp->maybeBlockChain();
-
-    if (!sharedBlock) {
-        /*
-         * Don't force a call object for a lightweight function call, but do
-         * insist that there is a call object for a heavyweight function call.
-         */
-        JS_ASSERT_IF(fp->isNonEvalFunctionFrame() && fp->fun()->isHeavyweight(),
-                     fp->hasCallObj());
-        return fp->scopeChain();
-    }
-
-    Root<StaticBlockObject*> sharedBlockRoot(cx, &sharedBlock);
-
-    /*
-     * We have one or more lexical scopes to reflect into fp->scopeChain, so
-     * make sure there's a call object at the current head of the scope chain,
-     * if this frame is a call frame.
-     *
-     * Also, identify the innermost compiler-allocated block we needn't clone.
-     */
-    RootedVarObject limitBlock(cx), limitClone(cx);
-    if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj()) {
-        JS_ASSERT_IF(fp->scopeChain()->isClonedBlock(), fp->scopeChain()->getPrivate() != fp);
-        if (!CallObject::createForFunction(cx, fp))
-            return NULL;
-
-        /* We know we must clone everything on blockChain. */
-        limitBlock = limitClone = NULL;
-    } else {
-        /*
-         * scopeChain includes all blocks whose static scope we're within that
-         * have already been cloned.  Find the innermost such block.  Its
-         * prototype should appear on blockChain; we'll clone blockChain up
-         * to, but not including, that prototype.
-         */
-        limitClone = fp->scopeChain();
-        while (limitClone->isWith())
-            limitClone = &limitClone->asWith().enclosingScope();
-        JS_ASSERT(limitClone);
-
-        /*
-         * It may seem like we don't know enough about limitClone to be able
-         * to just grab its prototype as we do here, but it's actually okay.
-         *
-         * If limitClone is a block object belonging to this frame, then its
-         * prototype is the innermost entry in blockChain that we have already
-         * cloned, and is thus the place to stop when we clone below.
-         *
-         * Otherwise, there are no blocks for this frame on scopeChain, and we
-         * need to clone the whole blockChain.  In this case, limitBlock can
-         * point to any object known not to be on blockChain, since we simply
-         * loop until we hit limitBlock or NULL.  If limitClone is a block, it
-         * isn't a block from this function, since blocks can't be nested
-         * within themselves on scopeChain (recursion is dynamic nesting, not
-         * static nesting).  If limitClone isn't a block, its prototype won't
-         * be a block either.  So we can just grab limitClone's prototype here
-         * regardless of its type or which frame it belongs to.
-         */
-        limitBlock = limitClone->getProto();
-
-        /* If the innermost block has already been cloned, we are done. */
-        if (limitBlock == sharedBlock)
-            return fp->scopeChain();
-    }
-
-    /*
-     * Special-case cloning the innermost block; this doesn't have enough in
-     * common with subsequent steps to include in the loop.
-     *
-     * create() leaves the clone's enclosingScope unset. We set it below.
-     */
-    RootedVar<ClonedBlockObject *> innermostNewChild(cx);
-    innermostNewChild = ClonedBlockObject::create(cx, sharedBlockRoot, fp);
-    if (!innermostNewChild)
-        return NULL;
-
-    /*
-     * Clone our way towards outer scopes until we reach the innermost
-     * enclosing function, or the innermost block we've already cloned.
-     */
-    RootedVar<ClonedBlockObject *> newChild(cx, innermostNewChild);
-    for (;;) {
-        JS_ASSERT(newChild->getProto() == sharedBlock);
-        sharedBlock = sharedBlock->enclosingBlock();
-
-        /* Sometimes limitBlock will be NULL, so check that first.  */
-        if (sharedBlock == limitBlock || !sharedBlock)
-            break;
-
-        /* As in the call above, we don't know the real parent yet.  */
-        RootedVar<ClonedBlockObject *> clone(cx, ClonedBlockObject::create(cx, sharedBlockRoot, fp));
-        if (!clone)
-            return NULL;
-
-        if (!newChild->setEnclosingScope(cx, clone))
-            return NULL;
-        newChild = clone;
-    }
-    if (!newChild->setEnclosingScope(cx, fp->scopeChain()))
-        return NULL;
-
-    /*
-     * If we found a limit block belonging to this frame, then we should have
-     * found it in blockChain.
-     */
-    JS_ASSERT_IF(limitBlock &&
-                 limitBlock->isClonedBlock() &&
-                 limitClone->getPrivate() == js_FloatingFrameIfGenerator(cx, fp),
-                 sharedBlock);
-
-    /* Place our newly cloned blocks at the head of the scope chain.  */
-    fp->setScopeChainNoCallObj(*innermostNewChild);
-    return innermostNewChild;
-}
-
-JSObject *
-js::GetScopeChain(JSContext *cx)
-{
-    /*
-     * Note: we don't need to expand inline frames here, because frames are
-     * only inlined when the caller and callee share the same scope chain.
-     */
-    StackFrame *fp = js_GetTopStackFrame(cx, FRAME_EXPAND_NONE);
-    if (!fp) {
-        /*
-         * There is no code active on this context. In place of an actual
-         * scope chain, use the context's global object, which is set in
-         * js_InitFunctionAndObjectClasses, and which represents the default
-         * scope chain for the embedding. See also js_FindClassObject.
-         *
-         * For embeddings that use the inner and outer object hooks, the inner
-         * object represents the ultimate global object, with the outer object
-         * acting as a stand-in.
-         */
-        JSObject *obj = cx->globalObject;
-        if (!obj) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INACTIVE);
-            return NULL;
-        }
-
-        OBJ_TO_INNER_OBJECT(cx, obj);
-        return obj;
-    }
-    return GetScopeChain(cx, fp);
-}
-
 /* Some objects (e.g., With) delegate 'this' to another object. */
 static inline JSObject *
 CallThisObjectHook(JSContext *cx, JSObject *obj, Value *argv)
 {
     JSObject *thisp = obj->thisObject(cx);
     if (!thisp)
         return NULL;
     argv[-1].setObject(*thisp);
@@ -645,16 +465,17 @@ js::InvokeGetterOrSetter(JSContext *cx, 
     return Invoke(cx, ObjectValue(*obj), fval, argc, argv, rval);
 }
 
 bool
 js::ExecuteKernel(JSContext *cx, JSScript *script, JSObject &scopeChain, const Value &thisv,
                   ExecuteType type, StackFrame *evalInFrame, Value *result)
 {
     JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
+    JS_ASSERT_IF(type == EXECUTE_GLOBAL, !scopeChain.isScope());
 
     JS::Root<JSScript*> scriptRoot(cx, &script);
 
     if (script->isEmpty()) {
         if (result)
             result->setUndefined();
         return true;
     }
@@ -673,17 +494,17 @@ js::ExecuteKernel(JSContext *cx, JSScrip
 
     Probes::startExecution(cx, script);
 
     TypeScript::SetThis(cx, script, fp->thisValue());
 
     bool ok = RunScript(cx, script, fp);
 
     if (fp->isStrictEvalFrame())
-        js_PutCallObject(fp);
+        js_PutCallObject(fp, fp->callObj());
 
     Probes::stopExecution(cx, script);
 
     /* Propgate the return value out. */
     if (result)
         *result = fp->returnValue();
     return ok;
 }
@@ -914,69 +735,48 @@ EnterWith(JSContext *cx, int stackIndex)
         obj = &sp[-1].toObject();
     } else {
         obj = js_ValueToNonNullObject(cx, sp[-1]);
         if (!obj)
             return JS_FALSE;
         sp[-1].setObject(*obj);
     }
 
-    RootedVarObject parent(cx, GetScopeChain(cx, fp));
-    if (!parent)
-        return JS_FALSE;
-
-    JSObject *withobj = WithObject::create(cx, fp, obj, parent,
+    JSObject *withobj = WithObject::create(cx, obj, fp->scopeChain(),
                                            sp + stackIndex - fp->base());
     if (!withobj)
         return JS_FALSE;
 
-    fp->setScopeChainNoCallObj(*withobj);
+    fp->setScopeChain(*withobj);
     return JS_TRUE;
 }
 
-static void
-LeaveWith(JSContext *cx)
-{
-    WithObject &withobj = cx->fp()->scopeChain()->asWith();
-    JS_ASSERT(withobj.maybeStackFrame() == js_FloatingFrameIfGenerator(cx, cx->fp()));
-    withobj.setStackFrame(NULL);
-    cx->fp()->setScopeChainNoCallObj(withobj.enclosingScope());
-}
-
-bool
-js::IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth)
-{
-    return (obj.isWith() || obj.isBlock()) &&
-           obj.getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()) &&
-           obj.asNestedScope().stackDepth() >= stackDepth;
-}
-
 /* Unwind block and scope chains to match the given depth. */
 void
 js::UnwindScope(JSContext *cx, uint32_t stackDepth)
 {
-    JS_ASSERT(cx->fp()->base() + stackDepth <= cx->regs().sp);
-
     StackFrame *fp = cx->fp();
-    StaticBlockObject *block = fp->maybeBlockChain();
-    while (block) {
-        if (block->stackDepth() < stackDepth)
+    JS_ASSERT(fp->base() + stackDepth <= cx->regs().sp);
+
+    for (ScopeIter si(fp); !si.done(); si = si.enclosing()) {
+        switch (si.type()) {
+          case ScopeIter::Block:
+            if (si.staticBlock().stackDepth() < stackDepth)
+                return;
+            fp->popBlock(cx);
             break;
-        block = block->enclosingBlock();
-    }
-    fp->setBlockChain(block);
-
-    for (;;) {
-        JSObject &scopeChain = *fp->scopeChain();
-        if (!IsActiveWithOrBlock(cx, scopeChain, stackDepth))
+          case ScopeIter::With:
+            if (si.scope().asWith().stackDepth() < stackDepth)
+                return;
+            fp->popWith(cx);
             break;
-        if (scopeChain.isClonedBlock())
-            scopeChain.asClonedBlock().put(cx);
-        else
-            LeaveWith(cx);
+          case ScopeIter::Call:
+          case ScopeIter::StrictEvalScope:
+            break;
+        }
     }
 }
 
 void
 js::UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs)
 {
 
     /* c.f. the regular (catchable) TryNoteIter loop in Interpret. */
@@ -1101,31 +901,32 @@ CheckLocalAccess(StackFrame *fp, unsigne
          */
     }
 #endif
 }
 
 static inline void
 CheckArgAccess(StackFrame *fp, unsigned index)
 {
-    JS_ASSERT(fp->script()->argLivesInArgumentsObject(index) == fp->script()->needsArgsObj());
+    JS_ASSERT(fp->script()->formalLivesInArgumentsObject(index) ==
+              fp->script()->argsObjAliasesFormals());
 }
 
 /*
  * This function is temporary. Bug 659577 will change all ALIASEDVAR
  * access to use the scope chain instead.
  */
 static inline Value &
 AliasedVar(StackFrame *fp, ScopeCoordinate sc)
 {
     JSScript *script = fp->script();
 #ifdef DEBUG
     JS_ASSERT(sc.hops == 0);  /* Temporary */
     if (script->bindings.bindingIsArg(sc.binding))
-        JS_ASSERT(script->argLivesInCallObject(script->bindings.bindingToArg(sc.binding)));
+        JS_ASSERT(script->formalLivesInCallObject(script->bindings.bindingToArg(sc.binding)));
     else
         CheckLocalAccess(fp, script->bindings.bindingToLocal(sc.binding), true);
 #endif
     return script->bindings.bindingIsArg(sc.binding)
            ? fp->formalArg(script->bindings.bindingToArg(sc.binding))
            : fp->localSlot(script->bindings.bindingToLocal(sc.binding));
 }
 
@@ -1860,18 +1661,18 @@ BEGIN_CASE(JSOP_ENTERWITH)
      * We set sp[-1] to the current "with" object to help asserting the
      * enter/leave balance in [leavewith].
      */
     regs.sp[-1].setObject(*regs.fp()->scopeChain());
 END_CASE(JSOP_ENTERWITH)
 
 BEGIN_CASE(JSOP_LEAVEWITH)
     JS_ASSERT(regs.sp[-1].toObject() == *regs.fp()->scopeChain());
+    regs.fp()->popWith(cx);
     regs.sp--;
-    LeaveWith(cx);
 END_CASE(JSOP_LEAVEWITH)
 
 BEGIN_CASE(JSOP_RETURN)
     POP_RETURN_VALUE();
     /* FALL THROUGH */
 
 BEGIN_CASE(JSOP_RETRVAL)    /* fp return value already set */
 BEGIN_CASE(JSOP_STOP)
@@ -1881,18 +1682,17 @@ BEGIN_CASE(JSOP_STOP)
      * false after the inline_return label.
      */
     CHECK_BRANCH();
 
     interpReturnOK = true;
     if (entryFrame != regs.fp())
   inline_return:
     {
-        JS_ASSERT(!regs.fp()->hasBlockChain());
-        JS_ASSERT(!IsActiveWithOrBlock(cx, *regs.fp()->scopeChain(), 0));
+        AssertValidFunctionScopeChainAtExit(regs.fp());
 
         if (cx->compartment->debugMode())
             interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
  
         interpReturnOK = ScriptEpilogue(cx, regs.fp(), interpReturnOK);
 
         /* The JIT inlines ScriptEpilogue. */
 #ifdef JS_METHODJIT
@@ -3142,43 +2942,33 @@ BEGIN_CASE(JSOP_DEFFUN)
      * A top-level function defined in Global or Eval code (see ECMA-262
      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
      * a compound statement (not at the top statement level of global code, or
      * at the top level of a function body).
      */
     RootedVarFunction &fun = rootFunction0;
     fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
 
-    RootedVarObject &obj2 = rootObject0;
-    if (fun->isNullClosure()) {
-        /*
-         * Even a null closure needs a parent for principals finding.
-         * FIXME: bug 476950, although debugger users may also demand some kind
-         * of scope link for debugger-assisted eval-in-frame.
-         */
-        obj2 = regs.fp()->scopeChain();
-    } else {
-        obj2 = GetScopeChain(cx, regs.fp());
-        if (!obj2)
-            goto error;
-    }
-
     /*
      * If static link is not current scope, clone fun's object to link to the
      * current scope via parent. We do this to enable sharing of compiled
      * functions among multiple equivalent scopes, amortizing the cost of
      * compilation over a number of executions.  Examples include XUL scripts
      * and event handlers shared among Firefox or other Mozilla app chrome
      * windows, and user-defined JS functions precompiled and then shared among
      * requests in server-side JS.
      */
-    if (fun->environment() != obj2) {
-        fun = CloneFunctionObjectIfNotSingleton(cx, fun, obj2);
+    HandleObject scopeChain = regs.fp()->scopeChain();
+    if (fun->environment() != scopeChain) {
+        fun = CloneFunctionObjectIfNotSingleton(cx, fun, scopeChain);
         if (!fun)
             goto error;
+    } else {
+        JS_ASSERT(script->compileAndGo);
+        JS_ASSERT(regs.fp()->isGlobalFrame() || regs.fp()->isEvalInFunction());
     }
 
     /*
      * ECMA requires functions defined when entering Eval code to be
      * impermanent.
      */
     unsigned attrs = regs.fp()->isEvalFrame()
                   ? JSPROP_ENUMERATE
@@ -3251,37 +3041,22 @@ BEGIN_CASE(JSOP_DEFFUN)
 }
 END_CASE(JSOP_DEFFUN)
 
 BEGIN_CASE(JSOP_LAMBDA)
 {
     /* Load the specified function object literal. */
     RootedVarFunction &fun = rootFunction0;
     fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
-    JSObject *obj = fun;
-
-    /* do-while(0) so we can break instead of using a goto. */
-    do {
-        RootedVarObject &parent = rootObject0;
-        if (fun->isNullClosure()) {
-            parent = regs.fp()->scopeChain();
-        } else {
-            parent = GetScopeChain(cx, regs.fp());
-            if (!parent)
-                goto error;
-        }
-
-        obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
-        if (!obj)
-            goto error;
-    } while (0);
+
+    JSFunction *obj = CloneFunctionObjectIfNotSingleton(cx, fun, regs.fp()->scopeChain());
+    if (!obj)
+        goto error;
 
     JS_ASSERT(obj->getProto());
-    JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
-
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_LAMBDA)
 
 BEGIN_CASE(JSOP_CALLEE)
     JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
     PUSH_COPY(argv[-2]);
 END_CASE(JSOP_CALLEE)
@@ -3818,17 +3593,17 @@ END_VARLEN_CASE
 
 BEGIN_CASE(JSOP_ENDFILTER)
 {
     JS_ASSERT(!script->strictModeCode);
 
     bool cond = !regs.sp[-1].isMagic();
     if (cond) {
         /* Exit the "with" block left from the previous iteration. */
-        LeaveWith(cx);
+        regs.fp()->popWith(cx);
     }
     if (!js_StepXMLListFilter(cx, cond))
         goto error;
     if (!regs.sp[-1].isNull()) {
         /*
          * Decrease sp after EnterWith returns as we use sp[-1] there to root
          * temporaries.
          */
@@ -3951,87 +3726,55 @@ BEGIN_CASE(JSOP_GETFUNNS)
 END_CASE(JSOP_GETFUNNS)
 #endif /* JS_HAS_XML_SUPPORT */
 
 BEGIN_CASE(JSOP_ENTERBLOCK)
 BEGIN_CASE(JSOP_ENTERLET0)
 BEGIN_CASE(JSOP_ENTERLET1)
 {
     StaticBlockObject &blockObj = script->getObject(GET_UINT32_INDEX(regs.pc))->asStaticBlock();
-    JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
+
+    /* Clone block iff there are any closed-over variables. */
+    if (!regs.fp()->pushBlock(cx, blockObj))
+        goto error;
 
     if (op == JSOP_ENTERBLOCK) {
         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
         Value *vp = regs.sp + blockObj.slotCount();
         JS_ASSERT(regs.sp < vp);
         JS_ASSERT(vp <= regs.fp()->slots() + script->nslots);
         SetValueRangeToUndefined(regs.sp, vp);
         regs.sp = vp;
     } else if (op == JSOP_ENTERLET0) {
         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
                   == regs.sp);
     } else if (op == JSOP_ENTERLET1) {
         JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
                   == regs.sp - 1);
     }
-
-#ifdef DEBUG
-    JS_ASSERT(regs.fp()->maybeBlockChain() == blockObj.enclosingBlock());
-
-    /*
-     * The young end of fp->scopeChain may omit blocks if we haven't closed
-     * over them, but if there are any closure blocks on fp->scopeChain, they'd
-     * better be (clones of) ancestors of the block we're entering now;
-     * anything else we should have popped off fp->scopeChain when we left its
-     * static scope.
-     */
-    JSObject *obj2 = regs.fp()->scopeChain();
-    while (obj2->isWith())
-        obj2 = &obj2->asWith().enclosingScope();
-    if (obj2->isBlock() &&
-        obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp()))
-    {
-        StaticBlockObject &youngestProto = obj2->asClonedBlock().staticBlock();
-        StaticBlockObject *parent = &blockObj;
-        while ((parent = parent->enclosingBlock()) != &youngestProto)
-            JS_ASSERT(parent);
-    }
-#endif
-
-    regs.fp()->setBlockChain(&blockObj);
 }
 END_CASE(JSOP_ENTERBLOCK)
 
 BEGIN_CASE(JSOP_LEAVEBLOCK)
 BEGIN_CASE(JSOP_LEAVEFORLETIN)
 BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
 {
-    StaticBlockObject &blockObj = regs.fp()->blockChain();
-    JS_ASSERT(blockObj.stackDepth() <= StackDepth(script));
-
-    /*
-     * If we're about to leave the dynamic scope of a block that has been
-     * cloned onto fp->scopeChain, clear its private data, move its locals from
-     * the stack into the clone, and pop it off the chain.
-     */
-    JSObject &scope = *regs.fp()->scopeChain();
-    if (scope.getProto() == &blockObj)
-        scope.asClonedBlock().put(cx);
-
-    regs.fp()->setBlockChain(blockObj.enclosingBlock());
+    DebugOnly<uint32_t> blockDepth = regs.fp()->blockChain().stackDepth();
+
+    regs.fp()->popBlock(cx);
 
     if (op == JSOP_LEAVEBLOCK) {
         /* Pop the block's slots. */
         regs.sp -= GET_UINT16(regs.pc);
-        JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp);
+        JS_ASSERT(regs.fp()->base() + blockDepth == regs.sp);
     } else if (op == JSOP_LEAVEBLOCKEXPR) {
         /* Pop the block's slots maintaining the topmost expr. */
         Value *vp = &regs.sp[-1];
         regs.sp -= GET_UINT16(regs.pc);
-        JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() == regs.sp - 1);
+        JS_ASSERT(regs.fp()->base() + blockDepth == regs.sp - 1);
         regs.sp[-1] = *vp;
     } else {
         /* Another op will pop; nothing to do here. */
         len = JSOP_LEAVEFORLETIN_LENGTH;
         DO_NEXT_OP(len);
     }
 }
 END_CASE(JSOP_LEAVEBLOCK)
@@ -4255,32 +3998,25 @@ END_CASE(JSOP_ARRAYPUSH)
         goto inline_return;
 
   exit:
     if (cx->compartment->debugMode())
         interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
     interpReturnOK = ScriptEpilogueOrGeneratorYield(cx, regs.fp(), interpReturnOK);
     regs.fp()->setFinishedInInterpreter();
 
-    /*
-     * At this point we are inevitably leaving an interpreted function or a
-     * top-level script, and returning to one of:
-     * (a) an "out of line" call made through Invoke;
-     * (b) a js_Execute activation;
-     * (c) a generator (SendToGenerator, jsiter.c).
-     *
-     * We must not be in an inline frame. The check above ensures that for the
-     * error case and for a normal return, the code jumps directly to parent's
-     * frame pc.
-     */
+#ifdef DEBUG
     JS_ASSERT(entryFrame == regs.fp());
-    if (!regs.fp()->isGeneratorFrame()) {
-        JS_ASSERT(!IsActiveWithOrBlock(cx, *regs.fp()->scopeChain(), 0));
-        JS_ASSERT(!regs.fp()->hasBlockChain());
-    }
+    if (regs.fp()->isFunctionFrame())
+        AssertValidFunctionScopeChainAtExit(regs.fp());
+    else if (regs.fp()->isEvalFrame())
+        AssertValidEvalFrameScopeChainAtExit(regs.fp());
+    else if (!regs.fp()->isGeneratorFrame())
+        JS_ASSERT(!regs.fp()->scopeChain()->isScope());
+#endif
 
 #ifdef JS_METHODJIT
     /*
      * This path is used when it's guaranteed the method can be finished
      * inside the JIT.
      */
   leave_on_safe_point:
 #endif
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -47,30 +47,16 @@
 #include "jspubtd.h"
 #include "jsopcode.h"
 
 #include "vm/Stack.h"
 
 namespace js {
 
 /*
- * Refresh and return fp->scopeChain.  It may be stale if block scopes are
- * active but not yet reflected by objects in the scope chain.  If a block
- * scope contains a with, eval, XML filtering predicate, or similar such
- * dynamically scoped construct, then compile-time block scope at fp->blocks
- * must reflect at runtime.
- */
-
-extern JSObject *
-GetScopeChain(JSContext *cx);
-
-extern JSObject *
-GetScopeChain(JSContext *cx, StackFrame *fp);
-
-/*
  * ScriptPrologue/ScriptEpilogue must be called in pairs. ScriptPrologue
  * must be called before the script executes. ScriptEpilogue must be called
  * after the script returns or exits via exception.
  */
 
 inline bool
 ScriptPrologue(JSContext *cx, StackFrame *fp, JSScript *script);
 
@@ -316,18 +302,18 @@ UnwindScope(JSContext *cx, uint32_t stac
  * just preserving the basic engine stack invariants.
  */
 extern void
 UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs);
 
 extern bool
 OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval, Value *vp);
 
-extern bool
-IsActiveWithOrBlock(JSContext *cx, JSObject &obj, uint32_t stackDepth);
+inline void
+AssertValidFunctionScopeChainAtExit(StackFrame *fp);
 
 class TryNoteIter
 {
     const FrameRegs &regs;
     JSScript *script;
     uint32_t pcOffset;
     JSTryNote *tn, *tnEnd;
     void settle();
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -418,28 +418,27 @@ NameOperation(JSContext *cx, jsbytecode 
 
     return true;
 }
 
 inline bool
 DefVarOrConstOperation(JSContext *cx, HandleObject varobj, PropertyName *dn, unsigned attrs)
 {
     JS_ASSERT(varobj->isVarObj());
-    JS_ASSERT(!varobj->getOps()->defineProperty);
+    JS_ASSERT(!varobj->getOps()->defineProperty || varobj->isDebugScope());
 
     JSProperty *prop;
     JSObject *obj2;
     if (!varobj->lookupProperty(cx, dn, &obj2, &prop))
         return false;
 
     /* Steps 8c, 8d. */
     if (!prop || (obj2 != varobj && varobj->isGlobal())) {
-        if (!DefineNativeProperty(cx, varobj, dn, UndefinedValue(),
-                                  JS_PropertyStub, JS_StrictPropertyStub, attrs, 0, 0))
-        {
+        if (!varobj->defineProperty(cx, dn, UndefinedValue(), JS_PropertyStub,
+                                    JS_StrictPropertyStub, attrs)) {
             return false;
         }
     } else {
         /*
          * Extension: ordinarily we'd be done here -- but for |const|.  If we
          * see a redeclaration that's |const|, we consider it a conflict.
          */
         unsigned oldAttrs;
@@ -529,16 +528,59 @@ ScriptEpilogueOrGeneratorYield(JSContext
 
 inline void
 InterpreterFrames::enableInterruptsIfRunning(JSScript *script)
 {
     if (script == regs->fp()->script())
         enabler.enableInterrupts();
 }
 
+inline void
+AssertValidEvalFrameScopeChainAtExit(StackFrame *fp)
+{
+#ifdef DEBUG
+    JS_ASSERT(fp->isEvalFrame());
+
+    JS_ASSERT(!fp->hasBlockChain());
+    JSObject &scope = *fp->scopeChain();
+
+    if (fp->isStrictEvalFrame())
+        JS_ASSERT(scope.asCall().maybeStackFrame() == fp);
+    else if (fp->isDebuggerFrame())
+        JS_ASSERT(!scope.isScope());
+    else if (fp->isDirectEvalFrame())
+        JS_ASSERT(scope == *fp->prev()->scopeChain());
+    else
+        JS_ASSERT(scope.isGlobal());
+#endif
+}
+
+inline void
+AssertValidFunctionScopeChainAtExit(StackFrame *fp)
+{
+#ifdef DEBUG
+    JS_ASSERT(fp->isFunctionFrame());
+    if (fp->isGeneratorFrame() || fp->isYielding())
+        return;
+
+    if (fp->isEvalFrame()) {
+        AssertValidEvalFrameScopeChainAtExit(fp);
+        return;
+    }
+
+    JS_ASSERT(!fp->hasBlockChain());
+    JSObject &scope = *fp->scopeChain();
+
+    if (fp->fun()->isHeavyweight())
+        JS_ASSERT(scope.asCall().maybeStackFrame() == fp);
+    else if (scope.isCall() || scope.isBlock())
+        JS_ASSERT(scope.asScope().maybeStackFrame() != fp);
+#endif
+}
+
 static JS_ALWAYS_INLINE bool
 AddOperation(JSContext *cx, const Value &lhs, const Value &rhs, Value *res)
 {
     if (lhs.isInt32() && rhs.isInt32()) {
         int32_t l = lhs.toInt32(), r = rhs.toInt32();
         int32_t sum = l + r;
         if (JS_UNLIKELY(bool((l ^ sum) & (r ^ sum) & 0x80000000))) {
             res->setDouble(double(l) + double(r));
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1480,18 +1480,19 @@ js_NewGenerator(JSContext *cx)
     gen->obj.init(obj);
     gen->state = JSGEN_NEWBORN;
     gen->enumerators = NULL;
     gen->floating = genfp;
 
     /* Copy from the stack to the generator's floating frame. */
     gen->regs.rebaseFromTo(stackRegs, *genfp);
     genfp->stealFrameAndSlots<HeapValue, Value, StackFrame::DoPostBarrier>(
-                              genfp, genvp, stackfp, stackvp, stackRegs.sp);
+                              cx, genfp, genvp, stackfp, stackvp, stackRegs.sp);
     genfp->initFloatingGenerator();
+    stackfp->setYielding();  /* XXX: to be removed */
 
     obj->setPrivate(gen);
     return obj;
 }
 
 JSGenerator *
 js_FloatingFrameToGenerator(StackFrame *fp)
 {
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -932,16 +932,17 @@ enum EvalType { DIRECT_EVAL = EXECUTE_DI
  *
  * On success, store the completion value in call.rval and return true.
  */
 static bool
 EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, StackFrame *caller,
            HandleObject scopeobj)
 {
     JS_ASSERT((evalType == INDIRECT_EVAL) == (caller == NULL));
+    JS_ASSERT_IF(evalType == INDIRECT_EVAL, scopeobj->isGlobal());
     AssertInnerizedScopeChain(cx, *scopeobj);
 
     if (!scopeobj->global().isRuntimeCodeGenEnabled(cx)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_EVAL);
         return false;
     }
 
     /* ES5 15.1.2.1 step 1. */
@@ -1127,24 +1128,20 @@ DirectEval(JSContext *cx, const CallArgs
     /* Direct eval can assume it was called from an interpreted frame. */
     StackFrame *caller = cx->fp();
     JS_ASSERT(caller->isScriptFrame());
     JS_ASSERT(IsBuiltinEvalForScope(caller->scopeChain(), args.calleev()));
     JS_ASSERT(JSOp(*cx->regs().pc) == JSOP_EVAL);
 
     AutoFunctionCallProbe callProbe(cx, args.callee().toFunction(), caller->script());
 
-    RootedVarObject scopeChain(cx, GetScopeChain(cx, caller));
-    if (!scopeChain)
-        return false;
-
     if (!WarnOnTooManyArgs(cx, args))
         return false;
 
-    return EvalKernel(cx, args, DIRECT_EVAL, caller, scopeChain);
+    return EvalKernel(cx, args, DIRECT_EVAL, caller, caller->scopeChain());
 }
 
 bool
 IsBuiltinEvalForScope(JSObject *scopeChain, const Value &v)
 {
     return scopeChain->global().getOriginalEval() == v;
 }
 
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -256,16 +256,17 @@ extern Class WithClass;
 extern Class XMLFilterClass;
 
 class ArgumentsObject;
 class ArrayBufferObject;
 class BlockObject;
 class BooleanObject;
 class ClonedBlockObject;
 class DataViewObject;
+class DebugScopeObject;
 class DeclEnvObject;
 class ElementIteratorObject;
 class GlobalObject;
 class NestedScopeObject;
 class NewObjectCache;
 class NormalArgumentsObject;
 class NumberObject;
 class ScopeObject;
@@ -355,17 +356,17 @@ struct JSObject : public js::ObjectImpl
     inline bool setSystem(JSContext *cx);
 
     inline bool hasSpecialEquality() const;
 
     inline bool watched() const;
     inline bool setWatched(JSContext *cx);
 
     /* See StackFrame::varObj. */
-    inline bool isVarObj() const;
+    inline bool isVarObj();
     inline bool setVarObj(JSContext *cx);
 
     /*
      * Objects with an uncacheable proto can have their prototype mutated
      * without inducing a shape change on the object. Property cache entries
      * and JIT inline caches should not be filled for lookups across prototype
      * lookups on the object.
      */
@@ -956,29 +957,31 @@ struct JSObject : public js::ObjectImpl
     inline bool isNumber() const;
     inline bool isString() const;
 
     /* Subtypes of ArgumentsObject. */
     inline bool isNormalArguments() const;
     inline bool isStrictArguments() const;
 
     /* Subtypes of Proxy. */
+    inline bool isDebugScope() const;
     inline bool isWrapper() const;
     inline bool isFunctionProxy() const;
     inline bool isCrossCompartmentWrapper() const;
 
     inline js::ArgumentsObject &asArguments();
     inline js::ArrayBufferObject &asArrayBuffer();
     inline const js::ArgumentsObject &asArguments() const;
     inline js::BlockObject &asBlock();
     inline js::BooleanObject &asBoolean();
     inline js::CallObject &asCall();
     inline js::ClonedBlockObject &asClonedBlock();
     inline js::DataViewObject &asDataView();
     inline js::DeclEnvObject &asDeclEnv();
+    inline js::DebugScopeObject &asDebugScope();
     inline js::GlobalObject &asGlobal();
     inline js::NestedScopeObject &asNestedScope();
     inline js::NormalArgumentsObject &asNormalArguments();
     inline js::NumberObject &asNumber();
     inline js::RegExpObject &asRegExp();
     inline js::ScopeObject &asScope();
     inline js::StrictArgumentsObject &asStrictArguments();
     inline js::StaticBlockObject &asStaticBlock();
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -270,17 +270,21 @@ inline JSObject *
 JSObject::getParent() const
 {
     return lastProperty()->getObjectParent();
 }
 
 inline JSObject *
 JSObject::enclosingScope()
 {
-    return isScope() ? &asScope().enclosingScope() : getParent();
+    return isScope()
+           ? &asScope().enclosingScope()
+           : isDebugScope()
+           ? &asDebugScope().enclosingScope()
+           : getParent();
 }
 
 inline bool
 JSObject::isFixedSlot(size_t slot)
 {
     JS_ASSERT(!isDenseArray());
     return slot < numFixedSlots();
 }
@@ -738,18 +742,20 @@ inline bool JSObject::setSystem(JSContex
     return setFlag(cx, js::BaseShape::SYSTEM);
 }
 
 inline bool JSObject::setDelegate(JSContext *cx)
 {
     return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
 }
 
-inline bool JSObject::isVarObj() const
+inline bool JSObject::isVarObj()
 {
+    if (isDebugScope())
+        return asDebugScope().scope().isVarObj();
     return lastProperty()->hasObjectFlag(js::BaseShape::VAROBJ);
 }
 
 inline bool JSObject::setVarObj(JSContext *cx)
 {
     return setFlag(cx, js::BaseShape::VAROBJ);
 }
 
@@ -814,16 +820,23 @@ inline bool JSObject::isScope() const { 
 inline bool JSObject::isStaticBlock() const { return isBlock() && !getProto(); }
 inline bool JSObject::isStopIteration() const { return hasClass(&js::StopIterationClass); }
 inline bool JSObject::isStrictArguments() const { return hasClass(&js::StrictArgumentsObjectClass); }
 inline bool JSObject::isString() const { return hasClass(&js::StringClass); }
 inline bool JSObject::isTypedArray() const { return IsTypedArrayClass(getClass()); }
 inline bool JSObject::isWeakMap() const { return hasClass(&js::WeakMapClass); }
 inline bool JSObject::isWith() const { return hasClass(&js::WithClass); }
 
+inline bool
+JSObject::isDebugScope() const
+{
+    extern bool js_IsDebugScopeSlow(const JSObject *obj);
+    return getClass() == &js::ObjectProxyClass && js_IsDebugScopeSlow(this);
+}
+
 #if JS_HAS_XML_SUPPORT
 inline bool JSObject::isNamespace() const { return hasClass(&js::NamespaceClass); }
 inline bool JSObject::isXML() const { return hasClass(&js::XMLClass); }
 
 inline bool
 JSObject::isXMLId() const
 {
     return hasClass(&js::QNameClass)
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1333,16 +1333,20 @@ JSScript::NewScriptFromEmitter(JSContext
     if (bce->parser->compileAndGo) {
         script->compileAndGo = true;
         const StackFrame *fp = bce->parser->callerFrame;
         if (fp && fp->isFunctionFrame())
             script->savedCallerFun = true;
     }
     script->bindingsAccessedDynamically = bce->sc->bindingsAccessedDynamically();
     script->hasSingletons = bce->hasSingletons;
+#ifdef JS_METHODJIT
+    if (cx->compartment->debugMode())
+        script->debugMode = true;
+#endif
 
     if (bce->sc->inFunction) {
         if (bce->sc->funArgumentsHasLocalBinding()) {
             // This must precede the script->bindings.transfer() call below.
             script->setArgumentsHasLocalBinding(bce->sc->argumentsLocalSlot());
             if (bce->sc->funDefinitelyNeedsArgsObj())
                 script->setNeedsArgsObj(true);
         } else {
@@ -2263,29 +2267,29 @@ JSScript::varIsAliased(unsigned varSlot)
             return true;
         }
     }
 
     return false;
 }
 
 bool
-JSScript::argIsAliased(unsigned argSlot)
+JSScript::formalIsAliased(unsigned argSlot)
 {
-    return argLivesInCallObject(argSlot) || needsArgsObj();
+    return formalLivesInCallObject(argSlot) || argsObjAliasesFormals();
 }
 
 bool
-JSScript::argLivesInArgumentsObject(unsigned argSlot)
+JSScript::formalLivesInArgumentsObject(unsigned argSlot)
 {
-    return needsArgsObj() && !argLivesInCallObject(argSlot);
+    return argsObjAliasesFormals() && !formalLivesInCallObject(argSlot);
 }
 
 bool
-JSScript::argLivesInCallObject(unsigned argSlot)
+JSScript::formalLivesInCallObject(unsigned argSlot)
 {
     if (bindingsAccessedDynamically)
         return true;
 
     for (uint32_t i = 0; i < numClosedArgs(); ++i) {
         if (closedArgs()->vector[i] == argSlot) {
             JS_ASSERT(function()->isHeavyweight());
             return true;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -605,16 +605,29 @@ struct JSScript : public js::gc::Cell
      * So avoid spurious arguments object creation, we maintain the invariant
      * that needsArgsObj is only called after the script has been analyzed.
      */
     bool analyzedArgsUsage() const { return !needsArgsAnalysis_; }
     bool needsArgsObj() const { JS_ASSERT(analyzedArgsUsage()); return needsArgsObj_; }
     void setNeedsArgsObj(bool needsArgsObj);
     static bool applySpeculationFailed(JSContext *cx, JSScript *script);
 
+    /*
+     * Arguments access (via JSOP_*ARG* opcodes) must access the canonical
+     * location for the argument. If an arguments object exists AND this is a
+     * non-strict function (where 'arguments' aliases formals), then all access
+     * must go through the arguments object. Otherwise, the local slot is the
+     * canonical location for the arguments. Note: if a formal is aliased
+     * through the scope chain, then script->argLivesInCallObject and
+     * JSOP_*ARG* opcodes won't be emitted at all.
+     */
+    bool argsObjAliasesFormals() const {
+        return needsArgsObj() && !strictModeCode;
+    }
+
     /* Hash table chaining for JSCompartment::evalCache. */
     JSScript *&evalHashLink() { return *globalObject.unsafeGetUnioned(); }
 
     /*
      * Original compiled function for the script, if it has a function.
      * NULL for global and eval scripts.
      */
     JSFunction *function() const { return function_; }
@@ -850,19 +863,19 @@ struct JSScript : public js::gc::Cell
         js::ClosedSlotArray *arr = closedVars();
         JS_ASSERT(index < arr->length);
         return arr->vector[index];
     }
 
 
 #ifdef DEBUG
     bool varIsAliased(unsigned varSlot);
-    bool argIsAliased(unsigned argSlot);
-    bool argLivesInArgumentsObject(unsigned argSlot);
-    bool argLivesInCallObject(unsigned argSlot);
+    bool formalIsAliased(unsigned argSlot);
+    bool formalLivesInArgumentsObject(unsigned argSlot);
+    bool formalLivesInCallObject(unsigned argSlot);
 #endif
   private:
     /*
      * Recompile with or without single-stepping support, as directed
      * by stepModeEnabled().
      */
     void recompileForStepMode(js::FreeOp *fop);
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1013,32 +1013,30 @@ mjit::CanMethodJIT(JSContext *cx, JSScri
                  cx->isExceptionPending() || cx->runtime->hadOutOfMemory);
 
     return status;
 }
 
 CompileStatus
 mjit::Compiler::generatePrologue()
 {
-    invokeLabel = masm.label();
+    fastEntryLabel = masm.label();
 
     /*
      * If there is no function, then this can only be called via JaegerShot(),
      * which expects an existing frame to be initialized like the interpreter.
      */
     if (script->function()) {
         Jump j = masm.jump();
 
         /*
          * Entry point #2: The caller has partially constructed a frame, and
          * either argc >= nargs or the arity check has corrected the frame.
          */
-        invokeLabel = masm.label();
-
-        Label fastPath = masm.label();
+        fastEntryLabel = masm.label();
 
         /* Store this early on so slow paths can access it. */
         masm.storePtr(ImmPtr(script->function()),
                       Address(JSFrameReg, StackFrame::offsetOfExec()));
 
         {
             /*
              * Entry point #3: The caller has partially constructed a frame,
@@ -1073,17 +1071,17 @@ mjit::Compiler::generatePrologue()
                 stubcc.masm.storePtr(ImmPtr(script->function()),
                                      Address(JSFrameReg, StackFrame::offsetOfExec()));
                 OOL_STUBCALL(stubs::CheckArgumentTypes, REJOIN_CHECK_ARGUMENTS);
 #ifdef JS_MONOIC
                 this->argsCheckFallthrough = stubcc.masm.label();
 #endif
             }
 
-            stubcc.crossJump(stubcc.masm.jump(), fastPath);
+            stubcc.crossJump(stubcc.masm.jump(), fastEntryLabel);
         }
 
         /*
          * Guard that there is enough stack space. Note we reserve space for
          * any inline frames we end up generating, or a callee's stack frame
          * we write to before the callee checks the stack.
          */
         uint32_t nvals = VALUES_PER_STACK_FRAME + script->nslots + StackSpace::STACK_JIT_EXTRA;
@@ -1108,17 +1106,17 @@ mjit::Compiler::generatePrologue()
 
         types::TypeScriptNesting *nesting = script->nesting();
 
         /*
          * Run the function prologue if necessary. This is always done in a
          * stub for heavyweight functions (including nesting outer functions).
          */
         JS_ASSERT_IF(nesting && nesting->children, script->function()->isHeavyweight());
-        if (script->function()->isHeavyweight() || script->needsArgsObj()) {
+        if (script->function()->isHeavyweight()) {
             prepareStubCall(Uses(0));
             INLINE_STUBCALL(stubs::FunctionFramePrologue, REJOIN_FUNCTION_PROLOGUE);
         } else {
             /*
              * Load the scope chain into the frame if it will be needed by NAME
              * opcodes or by the nesting prologue below. The scope chain is
              * always set for global and eval frames, and will have been set by
              * CreateFunCallObject for heavyweight function frames.
@@ -1378,17 +1376,17 @@ mjit::Compiler::finishThisUp()
     chunk->code = JSC::MacroAssemblerCodeRef(result, execPool, masm.size() + stubcc.size());
     chunk->pcLengths = pcLengths;
 
     if (chunkIndex == 0) {
         jit->invokeEntry = result;
         if (script->function()) {
             jit->arityCheckEntry = stubCode.locationOf(arityLabel).executableAddress();
             jit->argsCheckEntry = stubCode.locationOf(argsCheckLabel).executableAddress();
-            jit->fastEntry = fullCode.locationOf(invokeLabel).executableAddress();
+            jit->fastEntry = fullCode.locationOf(fastEntryLabel).executableAddress();
         }
     }
 
     /*
      * WARNING: mics(), callICs() et al depend on the ordering of these
      * variable-length sections.  See JITChunk's declaration for details.
      */
 
@@ -3812,17 +3810,17 @@ mjit::Compiler::emitReturn(FrameEntry *f
      *
      * To avoid double-putting, EnterMethodJIT calls updateEpilogueFlags to clear the
      * entry frame's hasArgsObj() and hasCallObj() flags if the given objects have already
      * been put.
      */
     if (script->function()) {
         types::TypeScriptNesting *nesting = script->nesting();
         if (script->function()->isHeavyweight() || script->needsArgsObj() ||
-            (nesting && nesting->children))
+            (nesting && nesting->children) || debugMode())
         {
             prepareStubCall(Uses(fe ? 1 : 0));
             INLINE_STUBCALL(stubs::FunctionFrameEpilogue, REJOIN_NONE);
         } else {
             /* if hasCallObj() */
             Jump putObjs = masm.branchTest32(Assembler::NonZero,
                                              Address(JSFrameReg, StackFrame::offsetOfFlags()),
                                              Imm32(StackFrame::HAS_CALL_OBJ));
@@ -7025,17 +7023,17 @@ mjit::Compiler::jumpAndRun(Jump j, jsbyt
 }
 
 void
 mjit::Compiler::enterBlock(StaticBlockObject *block)
 {
     /* For now, don't bother doing anything for this opcode. */
     frame.syncAndForgetEverything();
     masm.move(ImmPtr(block), Registers::ArgReg1);
-    INLINE_STUBCALL(stubs::EnterBlock, REJOIN_NONE);
+    INLINE_STUBCALL(stubs::EnterBlock, REJOIN_FALLTHROUGH);
     if (*PC == JSOP_ENTERBLOCK)
         frame.enterBlock(StackDefs(script, PC));
 }
 
 void
 mjit::Compiler::leaveBlock()
 {
     /*
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -474,17 +474,17 @@ private:
     js::Vector<RegExpShared*, 0, CompilerAllocPolicy> rootedRegExps;
     js::Vector<uint32_t> fixedIntToDoubleEntries;
     js::Vector<uint32_t> fixedDoubleToAnyEntries;
     js::Vector<JumpTable, 16> jumpTables;
     js::Vector<JumpTableEdge, 16> jumpTableEdges;
     js::Vector<LoopEntry, 16> loopEntries;
     js::Vector<OutgoingChunkEdge, 16> chunkEdges;
     StubCompiler stubcc;
-    Label invokeLabel;
+    Label fastEntryLabel;
     Label arityLabel;
     Label argsCheckLabel;
 #ifdef JS_MONOIC
     Label argsCheckStub;
     Label argsCheckFallthrough;
     Jump argsCheckJump;
 #endif
     bool debugMode_;
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -151,18 +151,18 @@ FindExceptionHandler(JSContext *cx)
 
 /*
  * Clean up a frame and return.
  */
 static void
 InlineReturn(VMFrame &f)
 {
     JS_ASSERT(f.fp() != f.entryfp);
-    JS_ASSERT(!IsActiveWithOrBlock(f.cx, *f.fp()->scopeChain(), 0));
-    JS_ASSERT(!f.fp()->hasBlockChain());
+    AssertValidFunctionScopeChainAtExit(f.fp());
+
     f.cx->stack.popInlineFrame(f.regs);
 
     DebugOnly<JSOp> op = JSOp(*f.regs.pc);
     JS_ASSERT(op == JSOP_CALL ||
               op == JSOP_NEW ||
               op == JSOP_EVAL ||
               op == JSOP_FUNCALL ||
               op == JSOP_FUNAPPLY);
@@ -615,25 +615,28 @@ js_InternalThrow(VMFrame &f)
     /*
      * Interpret the ENTERBLOCK and EXCEPTION opcodes, so that we don't go
      * back into the interpreter with a pending exception. This will cause
      * it to immediately rethrow.
      */
     if (cx->isExceptionPending()) {
         JS_ASSERT(JSOp(*pc) == JSOP_ENTERBLOCK);
         StaticBlockObject &blockObj = script->getObject(GET_UINT32_INDEX(pc))->asStaticBlock();
+        if (!cx->regs().fp()->pushBlock(cx, blockObj))
+            return NULL;
         Value *vp = cx->regs().sp + blockObj.slotCount();
         SetValueRangeToUndefined(cx->regs().sp, vp);
         cx->regs().sp = vp;
+
         JS_ASSERT(JSOp(pc[JSOP_ENTERBLOCK_LENGTH]) == JSOP_EXCEPTION);
         cx->regs().sp[0] = cx->getPendingException();
         cx->clearPendingException();
         cx->regs().sp++;
+
         cx->regs().pc = pc + JSOP_ENTERBLOCK_LENGTH + JSOP_EXCEPTION_LENGTH;
-        cx->regs().fp()->setBlockChain(&blockObj);
     }
 
     *f.oldregs = f.regs;
 
     return NULL;
 }
 
 void JS_FASTCALL
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -1092,17 +1092,17 @@ mjit::EnterMethodJIT(JSContext *cx, Stac
         fp->updateEpilogueFlags();
 
     return ok ? Jaeger_Returned : Jaeger_Throwing;
 }
 
 static inline JaegerStatus
 CheckStackAndEnterMethodJIT(JSContext *cx, StackFrame *fp, void *code, bool partial)
 {
-    JS_CHECK_RECURSION(cx, return Jaeger_Throwing);
+    JS_CHECK_RECURSION(cx, return Jaeger_ThrowBeforeEnter);
 
     JS_ASSERT(!cx->compartment->activeAnalysis);
     JS_ASSERT(code);
 
     Value *stackLimit = cx->stack.space().getStackLimit(cx, REPORT_ERROR);
     if (!stackLimit)
         return Jaeger_ThrowBeforeEnter;
 
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -321,57 +321,43 @@ stubs::Ursh(VMFrame &f)
 	if (!f.regs.sp[-2].setNumber(uint32_t(u)))
         TypeScript::MonitorOverflow(f.cx, f.script(), f.pc());
 }
 
 template<JSBool strict>
 void JS_FASTCALL
 stubs::DefFun(VMFrame &f, JSFunction *fun_)
 {
-    RootedVarFunction fun(f.cx, fun_);
-
-    JSContext *cx = f.cx;
-    StackFrame *fp = f.fp();
-
     /*
      * A top-level function defined in Global or Eval code (see ECMA-262
      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
      * a compound statement (not at the top statement level of global code, or
      * at the top level of a function body).
      */
-    JSObject *obj = fun;
-
-    RootedVarObject obj2(f.cx);
-    if (fun->isNullClosure()) {
-        /*
-         * Even a null closure needs a parent for principals finding.
-         * FIXME: bug 476950, although debugger users may also demand some kind
-         * of scope link for debugger-assisted eval-in-frame.
-         */
-        obj2 = fp->scopeChain();
-    } else {
-        obj2 = GetScopeChain(cx, fp);
-        if (!obj2)
-            THROW();
-    }
+    JSContext *cx = f.cx;
+    StackFrame *fp = f.fp();
+    RootedVarFunction fun(f.cx, fun_);
 
     /*
      * If static link is not current scope, clone fun's object to link to the
      * current scope via parent. We do this to enable sharing of compiled
      * functions among multiple equivalent scopes, amortizing the cost of
      * compilation over a number of executions.  Examples include XUL scripts
      * and event handlers shared among Firefox or other Mozilla app chrome
      * windows, and user-defined JS functions precompiled and then shared among
      * requests in server-side JS.
      */
-    if (obj->toFunction()->environment() != obj2) {
-        obj = CloneFunctionObjectIfNotSingleton(cx, fun, obj2);
-        if (!obj)
+    HandleObject scopeChain = f.fp()->scopeChain();
+    if (fun->environment() != scopeChain) {
+        fun = CloneFunctionObjectIfNotSingleton(cx, fun, scopeChain);
+        if (!fun)
             THROW();
-        JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
+    } else {
+        JS_ASSERT(f.script()->compileAndGo);
+        JS_ASSERT(f.fp()->isGlobalFrame() || f.fp()->isEvalInFunction());
     }
 
     /*
      * ECMA requires functions defined when entering Eval code to be
      * impermanent.
      */
     unsigned attrs = fp->isEvalFrame()
                   ? JSPROP_ENUMERATE
@@ -386,17 +372,17 @@ stubs::DefFun(VMFrame &f, JSFunction *fu
 
     /* ES5 10.5 (NB: with subsequent errata). */
     PropertyName *name = fun->atom->asPropertyName();
     JSProperty *prop = NULL;
     JSObject *pobj;
     if (!parent->lookupProperty(cx, name, &pobj, &prop))
         THROW();
 
-    Value rval = ObjectValue(*obj);
+    Value rval = ObjectValue(*fun);
 
     do {
         /* Steps 5d, 5f. */
         if (!prop || pobj != parent) {
             if (!parent->defineProperty(cx, name, rval,
                                         JS_PropertyStub, JS_StrictPropertyStub, attrs))
             {
                 THROW();
@@ -1006,32 +992,21 @@ stubs::RegExp(VMFrame &f, JSObject *rege
         THROW();
     f.regs.sp[0].setObject(*obj);
 }
 
 JSObject * JS_FASTCALL
 stubs::Lambda(VMFrame &f, JSFunction *fun_)
 {
     RootedVarFunction fun(f.cx, fun_);
-
-    RootedVarObject parent(f.cx);
-    if (fun->isNullClosure()) {
-        parent = f.fp()->scopeChain();
-    } else {
-        parent = GetScopeChain(f.cx, f.fp());
-        if (!parent)
-            THROWV(NULL);
-    }
-
-    JSObject *obj = CloneFunctionObjectIfNotSingleton(f.cx, fun, parent);
-    if (!obj)
+    fun = CloneFunctionObjectIfNotSingleton(f.cx, fun, f.fp()->scopeChain());
+    if (!fun)
         THROWV(NULL);
 
-    JS_ASSERT_IF(f.script()->compileAndGo, obj->global() == fun->global());
-    return obj;
+    return fun;
 }
 
 void JS_FASTCALL
 stubs::GetProp(VMFrame &f, PropertyName *name)
 {
     JSContext *cx = f.cx;
     FrameRegs &regs = f.regs;
 
@@ -1227,74 +1202,42 @@ stubs::FastInstanceOf(VMFrame &f)
     f.regs.sp[-3].setBoolean(js_IsDelegate(f.cx, &lref.toObject(), f.regs.sp[-3]));
 }
 
 void JS_FASTCALL
 stubs::EnterBlock(VMFrame &f, JSObject *obj)
 {
     FrameRegs &regs = f.regs;
     StackFrame *fp = f.fp();
-    StaticBlockObject &blockObj = obj->asStaticBlock();
+    JS_ASSERT(!f.regs.inlined());
 
-    JS_ASSERT(!f.regs.inlined());
+    StaticBlockObject &blockObj = obj->asStaticBlock();
+    if (!fp->pushBlock(f.cx, blockObj))
+        THROW();
 
     if (*regs.pc == JSOP_ENTERBLOCK) {
         JS_ASSERT(fp->base() + blockObj.stackDepth() == regs.sp);
         Value *vp = regs.sp + blockObj.slotCount();
         JS_ASSERT(regs.sp < vp);
         JS_ASSERT(vp <= fp->slots() + fp->script()->nslots);
         SetValueRangeToUndefined(regs.sp, vp);
         regs.sp = vp;
+    } else if (*regs.pc == JSOP_ENTERLET0) {
+        JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
+                  == regs.sp);
+    } else if (*regs.pc == JSOP_ENTERLET1) {
+        JS_ASSERT(regs.fp()->base() + blockObj.stackDepth() + blockObj.slotCount()
+                  == regs.sp - 1);
     }
-
-#ifdef DEBUG
-    JSContext *cx = f.cx;
-    JS_ASSERT(fp->maybeBlockChain() == blockObj.enclosingBlock());
-
-    /*
-     * The young end of fp->scopeChain() may omit blocks if we haven't closed
-     * over them, but if there are any closure blocks on fp->scopeChain(), they'd
-     * better be (clones of) ancestors of the block we're entering now;
-     * anything else we should have popped off fp->scopeChain() when we left its
-     * static scope.
-     */
-    JSObject *obj2 = fp->scopeChain();
-    while (obj2->isWith())
-        obj2 = &obj2->asWith().enclosingScope();
-    if (obj2->isBlock() &&
-        obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, fp)) {
-        JSObject &youngestProto = obj2->asClonedBlock().staticBlock();
-        StaticBlockObject *parent = &blockObj;
-        while ((parent = parent->enclosingBlock()) != &youngestProto)
-            JS_ASSERT(parent);
-    }
-#endif
-
-    fp->setBlockChain(&blockObj);
 }
 
 void JS_FASTCALL
 stubs::LeaveBlock(VMFrame &f)
 {
-    JSContext *cx = f.cx;
-    StackFrame *fp = f.fp();
-
-    StaticBlockObject &blockObj = fp->blockChain();
-    JS_ASSERT(blockObj.stackDepth() <= StackDepth(fp->script()));
-
-    /*
-     * If we're about to leave the dynamic scope of a block that has been
-     * cloned onto fp->scopeChain(), clear its private data, move its locals from
-     * the stack into the clone, and pop it off the chain.
-     */
-    JSObject &obj = *fp->scopeChain();
-    if (obj.getProto() == &blockObj)
-        obj.asClonedBlock().put(cx);
-
-    fp->setBlockChain(blockObj.enclosingBlock());
+    f.fp()->popBlock(f.cx);
 }
 
 inline void *
 FindNativeCode(VMFrame &f, jsbytecode *target)
 {
     void* native = f.fp()->script()->nativeCodeForPC(f.fp()->isConstructing(), target);
     if (native)
         return native;
@@ -1702,17 +1645,17 @@ stubs::FunctionFramePrologue(VMFrame &f)
 {
     if (!f.fp()->functionPrologue(f.cx))
         THROW();
 }
 
 void JS_FASTCALL
 stubs::FunctionFrameEpilogue(VMFrame &f)
 {
-    f.fp()->functionEpilogue();
+    f.fp()->functionEpilogue(f.cx);
 }
 
 void JS_FASTCALL
 stubs::AnyFrameEpilogue(VMFrame &f)
 {
     /*
      * On the normal execution path, emitReturn calls ScriptDebugEpilogue
      * and inlines ScriptEpilogue. This function implements forced early
@@ -1720,17 +1663,17 @@ stubs::AnyFrameEpilogue(VMFrame &f)
      */
     bool ok = true;
     if (f.cx->compartment->debugMode())
         ok = js::ScriptDebugEpilogue(f.cx, f.fp(), ok);
     ok = ScriptEpilogue(f.cx, f.fp(), ok);
     if (!ok)
         THROW();
     if (f.fp()->isNonEvalFunctionFrame())
-        f.fp()->functionEpilogue();
+        f.fp()->functionEpilogue(f.cx);
 }
 
 template <bool Clamped>
 int32_t JS_FASTCALL
 stubs::ConvertToTypedInt(JSContext *cx, Value *vp)
 {
     JS_ASSERT(!vp->isInt32());
 
--- a/js/src/vm/ArgumentsObject.cpp
+++ b/js/src/vm/ArgumentsObject.cpp
@@ -207,17 +207,17 @@ ArgGetter(JSContext *cx, JSObject *obj, 
     if (JSID_IS_INT(id)) {
         /*
          * arg can exceed the number of arguments if a script changed the
          * prototype to point to another Arguments object with a bigger argc.
          */
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj.initialLength() && !argsobj.isElementDeleted(arg)) {
             if (StackFrame *fp = argsobj.maybeStackFrame()) {
-                JS_ASSERT_IF(arg < fp->numFormalArgs(), fp->script()->argIsAliased(arg));
+                JS_ASSERT_IF(arg < fp->numFormalArgs(), fp->script()->formalIsAliased(arg));
                 *vp = fp->canonicalActualArg(arg);
             } else {
                 *vp = argsobj.element(arg);
             }
         }
     } else if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) {
         if (!argsobj.hasOverriddenLength())
             vp->setInt32(argsobj.initialLength());
@@ -240,17 +240,17 @@ ArgSetter(JSContext *cx, JSObject *obj, 
 
     if (JSID_IS_INT(id)) {
         unsigned arg = unsigned(JSID_TO_INT(id));
         if (arg < argsobj.initialLength()) {
             if (StackFrame *fp = argsobj.maybeStackFrame()) {
                 JSScript *script = fp->functionScript();
                 JS_ASSERT(script->needsArgsObj());
                 if (arg < fp->numFormalArgs()) {
-                    JS_ASSERT(fp->script()->argIsAliased(arg));
+                    JS_ASSERT(fp->script()->formalIsAliased(arg));
                     types::TypeScript::SetArgument(cx, script, arg, *vp);
                 }
                 fp->canonicalActualArg(arg) = *vp;
                 return true;
             }
         }
     } else {
         JS_ASSERT(JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom) ||
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ * vim: set ts=4 sw=4 et tw=99 ft=cpp:
  *
  * ***** 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/
@@ -649,16 +649,22 @@ Debugger::slowPathOnLeaveFrame(JSContext
 bool
 Debugger::wrapEnvironment(JSContext *cx, Handle<Env*> env, Value *rval)
 {
     if (!env) {
         rval->setNull();
         return true;
     }
 
+    /*
+     * DebuggerEnv should only wrap a debug scope chain obtained (transitively)
+     * from GetDebugScopeFor(Frame|Function).
+     */
+    JS_ASSERT(!env->isScope());
+
     JSObject *envobj;
     ObjectWeakMap::AddPtr p = environments.lookupForAdd(env);
     if (p) {
         envobj = p->value;
     } else {
         /* Create a new Debugger.Environment for env. */
         JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_ENV_PROTO).toObject();
         envobj = NewObjectWithGivenProto(cx, &DebuggerEnv_class, proto, NULL);
@@ -2583,16 +2589,18 @@ class BytecodeRangeWithLineNumbers : pri
     using BytecodeRange::frontOffset;
 
     BytecodeRangeWithLineNumbers(JSScript *script)
       : BytecodeRange(script), lineno(script->lineno), sn(script->notes()), snpc(script->code)
     {
         if (!SN_IS_TERMINATOR(sn))
             snpc += SN_DELTA(sn);
         updateLine();
+        while (frontPC() != script->main())
+            popFront();
     }
 
     void popFront() {
         BytecodeRange::popFront();
         if (!empty())
             updateLine();
     }
 
@@ -2659,18 +2667,19 @@ class FlowGraphSummary : public Vector<s
     void addEdgeFromAnywhere(size_t targetOffset) {
         (*this)[targetOffset] = MultipleEdges;
     }
 
     bool populate(JSContext *cx, JSScript *script) {
         if (!growBy(script->length))
             return false;
         FlowGraphSummary &self = *this;
-        self[0] = MultipleEdges;
-        for (size_t i = 1; i < script->length; i++)
+        unsigned mainOffset = script->main() - script->code;
+        self[mainOffset] = MultipleEdges;
+        for (size_t i = mainOffset + 1; i < script->length; i++)
             self[i] = NoEdges;
 
         size_t prevLine = script->lineno;
         JSOp prevOp = JSOP_NOP;
         for (BytecodeRangeWithLineNumbers r(script); !r.empty(); r.popFront()) {
             size_t lineno = r.frontLineNumber();
             JSOp op = r.frontOpcode();
 
@@ -2998,17 +3007,17 @@ CheckThisFrame(JSContext *cx, const Call
     if (!thisobj->getPrivate()) {
         if (thisobj->getReservedSlot(JSSLOT_DEBUGFRAME_OWNER).isUndefined()) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
                                  "Debugger.Frame", fnname, "prototype object");
             return NULL;
         }
         if (checkLive) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_LIVE,
-                                 "Debugger.Frame", fnname, "stack frame");
+                                 "Debugger.Frame");
             return NULL;
         }
     }
     return thisobj;
 }
 
 #define THIS_FRAME(cx, argc, vp, fnname, args, thisobj, fp)                  \
     CallArgs args = CallArgsFromVp(argc, vp);                                \
@@ -3034,36 +3043,27 @@ DebuggerFrame_getType(JSContext *cx, uns
     args.rval().setString(fp->isEvalFrame()
                           ? cx->runtime->atomState.evalAtom
                           : fp->isGlobalFrame()
                           ? cx->runtime->atomState.globalAtom
                           : cx->runtime->atomState.callAtom);
     return true;
 }
 
-static Env *
-Frame_GetEnv(JSContext *cx, StackFrame *fp)
-{
-    assertSameCompartment(cx, fp);
-    if (fp->isNonEvalFunctionFrame() && !fp->hasCallObj() && !CallObject::createForFunction(cx, fp))
-        return NULL;
-    return GetScopeChain(cx, fp);
-}
-
 static JSBool
 DebuggerFrame_getEnvironment(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_FRAME_OWNER(cx, argc, vp, "get environment", args, thisobj, fp, dbg);
 
     RootedVar<Env*> env(cx);
     {
         AutoCompartment ac(cx, fp->scopeChain());
         if (!ac.enter())
             return false;
-        env = Frame_GetEnv(cx, fp);
+        env = GetDebugScopeForFrame(cx, fp);
         if (!env)
             return false;
     }
 
     return dbg->wrapEnvironment(cx, env, &args.rval());
 }
 
 static JSBool
@@ -3231,19 +3231,19 @@ DebuggerFrame_getArguments(JSContext *cx
 static JSBool
 DebuggerFrame_getScript(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_FRAME(cx, argc, vp, "get script", args, thisobj, fp);
     Debugger *debug = Debugger::fromChildJSObject(thisobj);
 
     JSObject *scriptObject = NULL;
     if (fp->isFunctionFrame() && !fp->isEvalFrame()) {
-        JSFunction *callee = fp->callee().toFunction();
-        if (callee->isInterpreted()) {
-            scriptObject = debug->wrapScript(cx, RootedVar<JSScript*>(cx, callee->script()));
+        JSFunction &callee = fp->callee();
+        if (callee.isInterpreted()) {
+            scriptObject = debug->wrapScript(cx, RootedVar<JSScript*>(cx, callee.script()));
             if (!scriptObject)
                 return false;
         }
     } else if (fp->isScriptFrame()) {
         /*
          * We got eval, JS_Evaluate*, or JS_ExecuteScript non-function script
          * frames.
          */
@@ -3358,21 +3358,19 @@ DebuggerFrame_setOnPop(JSContext *cx, un
         return false;
     }
 
     thisobj->setReservedSlot(JSSLOT_DEBUGFRAME_ONPOP_HANDLER, args[0]);
     args.rval().setUndefined();
     return true;
 }
 
-namespace js {
-
 JSBool
-EvaluateInEnv(JSContext *cx, Handle<Env*> env, StackFrame *fp, const jschar *chars,
-              unsigned length, const char *filename, unsigned lineno, Value *rval)
+js::EvaluateInEnv(JSContext *cx, Handle<Env*> env, StackFrame *fp, const jschar *chars,
+                  unsigned length, const char *filename, unsigned lineno, Value *rval)
 {
     assertSameCompartment(cx, env, fp);
 
     JS_ASSERT(!IsPoisonedPtr(chars));
     SkipRoot skip(cx, &chars);
 
     if (fp) {
         /* Execute assumes an already-computed 'this" value. */
@@ -3396,18 +3394,16 @@ EvaluateInEnv(JSContext *cx, Handle<Env*
                                                cx->findVersion(), NULL,
                                                UpvarCookie::UPVAR_LEVEL_LIMIT);
     if (!script)
         return false;
 
     return ExecuteKernel(cx, script, *env, fp->thisValue(), EXECUTE_DEBUG, fp, rval);
 }
 
-}
-
 enum EvalBindingsMode { WithoutBindings, WithBindings };
 
 static JSBool
 DebuggerFrameEval(JSContext *cx, unsigned argc, Value *vp, EvalBindingsMode mode)
 {
     if (mode == WithBindings)
         REQUIRE_ARGC("Debugger.Frame.evalWithBindings", 2);
     else
@@ -3450,17 +3446,17 @@ DebuggerFrameEval(JSContext *cx, unsigne
             }
         }
     }
 
     AutoCompartment ac(cx, fp->scopeChain());
     if (!ac.enter())
         return false;
 
-    RootedVar<Env*> env(cx, JS_GetFrameScopeChain(cx, Jsvalify(fp)));
+    RootedVar<Env *> env(cx, GetDebugScopeForFrame(cx, fp));
     if (!env)
         return false;
 
     /* If evalWithBindings, create the inner environment. */
     if (mode == WithBindings) {
         /* TODO - This should probably be a Call object, like ES5 strict eval. */
         env = NewObjectWithGivenProto(cx, &ObjectClass, NULL, env);
         if (!env)
@@ -3724,17 +3720,27 @@ DebuggerObject_getEnvironment(JSContext 
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "get environment", args, dbg, obj);
 
     /* Don't bother switching compartments just to check obj's type and get its env. */
     if (!obj->isFunction() || !obj->toFunction()->isInterpreted()) {
         args.rval().setUndefined();
         return true;
     }
 
-    RootedVar<Env*> env(cx, obj->toFunction()->environment());
+    RootedVar<Env*> env(cx);
+    {
+        AutoCompartment ac(cx, obj);
+        if (!ac.enter())
+            return false;
+
+        env = GetDebugScopeForFunction(cx, obj->toFunction());
+        if (!env)
+            return false;
+    }
+
     return dbg->wrapEnvironment(cx, env, &args.rval());
 }
 
 static JSBool
 DebuggerObject_getOwnPropertyDescriptor(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGOBJECT_OWNER_REFERENT(cx, argc, vp, "getOwnPropertyDescriptor", args, dbg, obj);
 
@@ -4220,39 +4226,52 @@ DebuggerEnv_checkThis(JSContext *cx, con
 }
 
 #define THIS_DEBUGENV(cx, argc, vp, fnname, args, envobj, env)                \
     CallArgs args = CallArgsFromVp(argc, vp);                                 \
     JSObject *envobj = DebuggerEnv_checkThis(cx, args, fnname);               \
     if (!envobj)                                                              \
         return false;                                                         \
     RootedVar<Env*> env(cx, static_cast<Env *>(envobj->getPrivate()));        \
-    JS_ASSERT(env)
+    JS_ASSERT(env);                                                           \
+    JS_ASSERT(!env->isScope())
 
 #define THIS_DEBUGENV_OWNER(cx, argc, vp, fnname, args, envobj, env, dbg)     \
     THIS_DEBUGENV(cx, argc, vp, fnname, args, envobj, env);                   \
     Debugger *dbg = Debugger::fromChildJSObject(envobj)
 
 static JSBool
 DebuggerEnv_construct(JSContext *cx, unsigned argc, Value *vp)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NO_CONSTRUCTOR, "Debugger.Environment");
     return false;
 }
 
+static bool
+IsDeclarative(Env *env)
+{
+    return env->isDebugScope() && env->asDebugScope().isForDeclarative();
+}
+
+static bool
+IsWith(Env *env)
+{
+    return env->isDebugScope() && env->asDebugScope().scope().isWith();
+}
+
 static JSBool
 DebuggerEnv_getType(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGENV(cx, argc, vp, "get type", args, envobj, env);
 
     /* Don't bother switching compartments just to check env's class. */
     const char *s;
-    if (env->isCall() || env->isBlock() || env->isDeclEnv())
+    if (IsDeclarative(env))
         s = "declarative";
-    else if (env->isWith())
+    else if (IsWith(env))
         s = "with";
     else
         s = "object";
 
     JSAtom *str = js_Atomize(cx, s, strlen(s), InternAtom, NormalEncoding);
     if (!str)
         return false;
     args.rval().setString(str);
@@ -4273,21 +4292,24 @@ static JSBool
 DebuggerEnv_getObject(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGENV_OWNER(cx, argc, vp, "get type", args, envobj, env, dbg);
 
     /*
      * Don't bother switching compartments just to check env's class and
      * possibly get its proto.
      */
-    if (env->isCall() || env->isBlock() || env->isDeclEnv()) {
+    if (IsDeclarative(env)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NO_SCOPE_OBJECT);
         return false;
     }
-    JSObject *obj = env->isWith() ? env->getProto() : env;
+
+    JSObject *obj = IsWith(env)
+                    ? &env->asDebugScope().scope().asWith().object()
+                    : env;
 
     Value rval = ObjectValue(*obj);
     if (!dbg->wrapDebuggeeValue(cx, &rval))
         return false;
     args.rval() = rval;
     return true;
 }
 
--- a/js/src/vm/ScopeObject-inl.h
+++ b/js/src/vm/ScopeObject-inl.h
@@ -73,17 +73,17 @@ ScopeObject::setEnclosingScope(JSContext
         return false;
     self->setFixedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*obj));
     return true;
 }
 
 inline StackFrame *
 ScopeObject::maybeStackFrame() const
 {
-    JS_ASSERT(!isStaticBlock());
+    JS_ASSERT(!isStaticBlock() && !isWith());
     return reinterpret_cast<StackFrame *>(JSObject::getPrivate());
 }
 
 inline void
 ScopeObject::setStackFrame(StackFrame *frame)
 {
     return setPrivate(frame);
 }
@@ -259,25 +259,33 @@ StaticBlockObject::maybeDefinitionParseN
     Value v = slotValue(i);
     return v.isUndefined() ? NULL : reinterpret_cast<Definition *>(v.toPrivate());
 }
 
 inline void
 StaticBlockObject::setAliased(unsigned i, bool aliased)
 {
     slotValue(i).init(this, i, BooleanValue(aliased));
+    if (aliased)
+        JSObject::setPrivate(reinterpret_cast<void *>(1));
 }
 
 inline bool
 StaticBlockObject::isAliased(unsigned i)
 {
     return slotValue(i).isTrue();
 }
 
 inline bool
+StaticBlockObject::needsClone() const
+{
+    return JSObject::getPrivate() != NULL;
+}
+
+inline bool
 StaticBlockObject::containsVarAtDepth(uint32_t depth)
 {
     return depth >= stackDepth() && depth < stackDepth() + slotCount();
 }
 
 inline StaticBlockObject &
 ClonedBlockObject::staticBlock() const
 {
@@ -344,9 +352,16 @@ JSObject::asStaticBlock()
 
 inline js::ClonedBlockObject &
 JSObject::asClonedBlock()
 {
     JS_ASSERT(isClonedBlock());
     return *static_cast<js::ClonedBlockObject *>(this);
 }
 
+inline js::DebugScopeObject &
+JSObject::asDebugScope()
+{
+    JS_ASSERT(isDebugScope());
+    return *static_cast<js::DebugScopeObject *>(this);
+}
+
 #endif /* CallObject_inl_h___ */
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -50,20 +50,21 @@
 #include "jsatominlines.h"
 #include "jsobjinlines.h"
 
 #include "ScopeObject-inl.h"
 
 using namespace js;
 using namespace js::types;
 
+/*****************************************************************************/
+
 void
-js_PutCallObject(StackFrame *fp)
+js_PutCallObject(StackFrame *fp, CallObject &callobj)
 {
-    CallObject &callobj = fp->callObj().asCall();
     JS_ASSERT(callobj.maybeStackFrame() == fp);
     JS_ASSERT_IF(fp->isEvalFrame(), fp->isStrictEvalFrame());
     JS_ASSERT(fp->isEvalFrame() == callobj.isForEval());
 
     JSScript *script = fp->script();
     Bindings &bindings = script->bindings;
 
     if (callobj.isForEval()) {
@@ -213,67 +214,57 @@ CallObject::create(JSContext *cx, JSScri
 
 CallObject *
 CallObject::createForFunction(JSContext *cx, StackFrame *fp)
 {
     JS_ASSERT(fp->isNonEvalFunctionFrame());
     JS_ASSERT(!fp->hasCallObj());
 
     RootedVarObject scopeChain(cx, fp->scopeChain());
-    JS_ASSERT_IF(scopeChain->isWith() || scopeChain->isBlock() || scopeChain->isCall(),
-                 scopeChain->getPrivate() != fp);
 
     /*
      * For a named function expression Call's parent points to an environment
      * object holding function's name.
      */
-    RootedVarAtom lambdaName(cx, CallObjectLambdaName(fp->fun()));
-    if (lambdaName) {
+    if (js_IsNamedLambda(fp->fun())) {
         scopeChain = DeclEnvObject::create(cx, fp);
         if (!scopeChain)
             return NULL;
-
-        if (!DefineNativeProperty(cx, scopeChain, AtomToId(lambdaName),
-                                  ObjectValue(fp->callee()), NULL, NULL,
-                                  JSPROP_PERMANENT | JSPROP_READONLY, 0, 0)) {
-            return NULL;
-        }
     }
 
     CallObject *callobj = create(cx, fp->script(), scopeChain, RootedVarObject(cx, &fp->callee()));
     if (!callobj)
         return NULL;
 
     callobj->setStackFrame(fp);
-    fp->setScopeChainWithOwnCallObj(*callobj);
     return callobj;
 }
 
 CallObject *
 CallObject::createForStrictEval(JSContext *cx, StackFrame *fp)
 {
     CallObject *callobj = create(cx, fp->script(), fp->scopeChain(), RootedVarObject(cx));
     if (!callobj)
         return NULL;
 
     callobj->setStackFrame(fp);
-    fp->setScopeChainWithOwnCallObj(*callobj);
+    fp->initScopeChain(*callobj);
     return callobj;
 }
 
 JSBool
 CallObject::getArgOp(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     CallObject &callobj = obj->asCall();
 
     JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
     unsigned i = (uint16_t) JSID_TO_INT(id);
 
     DebugOnly<JSScript *> script = callobj.getCalleeFunction()->script();
-    JS_ASSERT_IF(!callobj.compartment()->debugMode(), script->argLivesInCallObject(i));
+    JS_ASSERT_IF(!cx->okToAccessUnaliasedBindings, script->formalLivesInCallObject(i));
 
     if (StackFrame *fp = callobj.maybeStackFrame())
         *vp = fp->formalArg(i);
     else
         *vp = callobj.arg(i);
     return true;
 }
 
@@ -281,17 +272,17 @@ JSBool
 CallObject::setArgOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
 {
     CallObject &callobj = obj->asCall();
 
     JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
     unsigned i = (uint16_t) JSID_TO_INT(id);
 
     JSScript *script = callobj.getCalleeFunction()->script();
-    JS_ASSERT_IF(!callobj.compartment()->debugMode(), script->argLivesInCallObject(i));
+    JS_ASSERT_IF(!cx->okToAccessUnaliasedBindings, script->formalLivesInCallObject(i));
 
     if (StackFrame *fp = callobj.maybeStackFrame())
         fp->formalArg(i) = *vp;
     else
         callobj.setArg(i, *vp);
 
     if (!script->ensureHasTypes(cx))
         return false;
@@ -305,40 +296,37 @@ JSBool
 CallObject::getVarOp(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     CallObject &callobj = obj->asCall();
 
     JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
     unsigned i = (uint16_t) JSID_TO_INT(id);
 
     DebugOnly<JSScript *> script = callobj.getCalleeFunction()->script();
-    JS_ASSERT_IF(!callobj.compartment()->debugMode(), script->varIsAliased(i));
+    JS_ASSERT_IF(!cx->okToAccessUnaliasedBindings, script->varIsAliased(i));
 
     if (StackFrame *fp = callobj.maybeStackFrame())
         *vp = fp->varSlot(i);
     else
         *vp = callobj.var(i);
 
-    /* This can only happen via the debugger. Bug 659577 will remove it. */
-    if (vp->isMagic(JS_OPTIMIZED_ARGUMENTS))
-        *vp = UndefinedValue();
-
+    JS_ASSERT(!vp->isMagic(JS_OPTIMIZED_ARGUMENTS));
     return true;
 }
 
 JSBool
 CallObject::setVarOp(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
 {
     CallObject &callobj = obj->asCall();
 
     JS_ASSERT((int16_t) JSID_TO_INT(id) == JSID_TO_INT(id));
     unsigned i = (uint16_t) JSID_TO_INT(id);
 
     JSScript *script = callobj.getCalleeFunction()->script();
-    JS_ASSERT_IF(!callobj.compartment()->debugMode(), script->varIsAliased(i));
+    JS_ASSERT_IF(!cx->okToAccessUnaliasedBindings, script->varIsAliased(i));
 
     if (StackFrame *fp = callobj.maybeStackFrame())
         fp->varSlot(i) = *vp;
     else
         callobj.setVar(i, *vp);
 
     if (!script->ensureHasTypes(cx))
         return false;
@@ -426,22 +414,29 @@ DeclEnvObject::create(JSContext *cx, Sta
     RootedVarObject obj(cx, JSObject::create(cx, FINALIZE_KIND, emptyDeclEnvShape, type, NULL));
     if (!obj)
         return NULL;
 
     obj->setPrivate(fp);
     if (!obj->asScope().setEnclosingScope(cx, fp->scopeChain()))
         return NULL;
 
+
+    if (!DefineNativeProperty(cx, obj, AtomToId(fp->fun()->atom),
+                              ObjectValue(fp->callee()), NULL, NULL,
+                              JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY,
+                              0, 0)) {
+        return NULL;
+    }
+
     return &obj->asDeclEnv();
 }
 
 WithObject *
-WithObject::create(JSContext *cx, StackFrame *fp, HandleObject proto, HandleObject enclosing,
-                   uint32_t depth)
+WithObject::create(JSContext *cx, HandleObject proto, HandleObject enclosing, uint32_t depth)
 {
     RootedVarTypeObject type(cx);
     type = proto->getNewType(cx);
     if (!type)
         return NULL;
 
     RootedVarShape emptyWithShape(cx);
     emptyWithShape = EmptyShape::getInitialShape(cx, &WithClass, proto,
@@ -452,17 +447,16 @@ WithObject::create(JSContext *cx, StackF
     RootedVarObject obj(cx, JSObject::create(cx, FINALIZE_KIND, emptyWithShape, type, NULL));
     if (!obj)
         return NULL;
 
     if (!obj->asScope().setEnclosingScope(cx, enclosing))
         return NULL;
 
     obj->setReservedSlot(DEPTH_SLOT, PrivateUint32Value(depth));
-    obj->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
 
     JSObject *thisp = proto->thisObject(cx);
     if (!thisp)
         return NULL;
 
     obj->setFixedSlot(THIS_SLOT, ObjectValue(*thisp));
 
     return &obj->asWith();
@@ -635,17 +629,16 @@ with_TypeOf(JSContext *cx, JSObject *obj
 static JSObject *
 with_ThisObject(JSContext *cx, JSObject *obj)
 {
     return &obj->asWith().withThis();
 }
 
 Class js::WithClass = {
     "With",
-    JSCLASS_HAS_PRIVATE |
     JSCLASS_HAS_RESERVED_SLOTS(WithObject::RESERVED_SLOTS) |
     JSCLASS_IS_ANONYMOUS,
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
@@ -688,18 +681,20 @@ Class js::WithClass = {
         with_DeleteSpecial,
         with_Enumerate,
         with_TypeOf,
         with_ThisObject,
         NULL,             /* clear */
     }
 };
 
+/*****************************************************************************/
+
 ClonedBlockObject *
-ClonedBlockObject::create(JSContext *cx, Handle<StaticBlockObject*> block, StackFrame *fp)
+ClonedBlockObject::create(JSContext *cx, Handle<StaticBlockObject *> block, StackFrame *fp)
 {
     RootedVarTypeObject type(cx);
     type = block->getNewType(cx);
     if (!type)
         return NULL;
 
     HeapSlot *slots;
     if (!PreallocateObjectDynamicSlots(cx, block->lastProperty(), &slots))
@@ -717,46 +712,39 @@ ClonedBlockObject::create(JSContext *cx,
         JS_ASSERT(obj->getParent() == NULL);
         if (!JSObject::setParent(cx, obj, RootedVarObject(cx, &fp->global())))
             return NULL;
     }
 
     JS_ASSERT(!obj->inDictionaryMode());
     JS_ASSERT(obj->slotSpan() >= block->slotCount() + RESERVED_SLOTS);
 
+    obj->setReservedSlot(SCOPE_CHAIN_SLOT, ObjectValue(*fp->scopeChain()));
     obj->setReservedSlot(DEPTH_SLOT, PrivateUint32Value(block->stackDepth()));
     obj->setPrivate(js_FloatingFrameIfGenerator(cx, fp));
 
     if (obj->lastProperty()->extensibleParents() && !obj->generateOwnShape(cx))
         return NULL;
 
     return &obj->asClonedBlock();
 }
 
 void
-ClonedBlockObject::put(JSContext *cx)
+ClonedBlockObject::put(StackFrame *fp)
 {
-    StackFrame *fp = cx->fp();
-    JS_ASSERT(maybeStackFrame() == js_FloatingFrameIfGenerator(cx, fp));
-
     uint32_t count = slotCount();
     uint32_t depth = stackDepth();
 
-    /* The block and its locals must be on the current stack for GC safety. */
-    JS_ASSERT(depth <= uint32_t(cx->regs().sp - fp->base()));
-    JS_ASSERT(count <= uint32_t(cx->regs().sp - fp->base() - depth));
-
     /* See comments in CheckDestructuring in frontend/Parser.cpp. */
     JS_ASSERT(count >= 1);
 
     copySlotRange(RESERVED_SLOTS, fp->base() + depth, count);
 
     /* We must clear the private slot even with errors. */
     setPrivate(NULL);
-    fp->setScopeChainNoCallObj(enclosingScope());
 }
 
 static JSBool
 block_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     /*
      * Block objects are never exposed to script, and the engine handles them
      * with care. So unlike other getters, this one can assert (rather than
@@ -828,16 +816,17 @@ StaticBlockObject::create(JSContext *cx)
     emptyBlockShape = EmptyShape::getInitialShape(cx, &BlockClass, NULL, NULL, FINALIZE_KIND);
     if (!emptyBlockShape)
         return NULL;
 
     JSObject *obj = JSObject::create(cx, FINALIZE_KIND, emptyBlockShape, type, NULL);
     if (!obj)
         return NULL;
 
+    obj->setPrivate(NULL);
     return &obj->asStaticBlock();
 }
 
 const Shape *
 StaticBlockObject::addVar(JSContext *cx, jsid id, int index, bool *redeclared)
 {
     JS_ASSERT(JSID_IS_ATOM(id) || (JSID_IS_INT(id) && JSID_TO_INT(id) == index));
 
@@ -856,28 +845,48 @@ StaticBlockObject::addVar(JSContext *cx,
      */
     uint32_t slot = JSSLOT_FREE(&BlockClass) + index;
     return addPropertyInternal(cx, id, block_getProperty, block_setProperty,
                                slot, JSPROP_ENUMERATE | JSPROP_PERMANENT,
                                Shape::HAS_SHORTID, index, spp,
                                /* allowDictionary = */ false);
 }
 
+static void
+block_trace(JSTracer *trc, JSObject *obj)
+{
+    if (obj->isStaticBlock())
+        return;
+
+    /* XXX: this will be removed again with bug 659577. */
+#if JS_HAS_GENERATORS
+    StackFrame *fp = obj->asClonedBlock().maybeStackFrame();
+    if (fp && fp->isFloatingGenerator())
+        MarkObject(trc, &js_FloatingFrameToGenerator(fp)->obj, "generator object");
+#endif
+}
+
 Class js::BlockClass = {
     "Block",
     JSCLASS_HAS_PRIVATE |
     JSCLASS_HAS_RESERVED_SLOTS(BlockObject::RESERVED_SLOTS) |
     JSCLASS_IS_ANONYMOUS,
     JS_PropertyStub,         /* addProperty */
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
-    JS_ConvertStub
+    JS_ConvertStub,
+    NULL,                    /* finalize */
+    NULL,                    /* checkAccess */
+    NULL,                    /* call        */
+    NULL,                    /* construct   */
+    NULL,                    /* hasInstance */
+    block_trace
 };
 
 #define NO_PARENT_INDEX UINT32_MAX
 
 /*
  * If there's a parent id, then get the parent out of our script's object
  * array. We know that we clone block objects in outer-to-inner order, which
  * means that getting the parent now will work.
@@ -1051,8 +1060,754 @@ js::CloneStaticBlockObject(JSContext *cx
             return NULL;
         }
 
         clone->setAliased(i, srcBlock.isAliased(i));
     }
 
     return clone;
 }
+
+/*****************************************************************************/
+
+ScopeIter::ScopeIter()
+ : fp_(NULL),
+   cur_(reinterpret_cast<JSObject *>(-1)),
+   block_(reinterpret_cast<StaticBlockObject *>(-1)),
+   type_(Type(-1))
+{}
+
+ScopeIter::ScopeIter(JSObject &enclosingScope)
+  : fp_(NULL),
+    cur_(&enclosingScope),
+    block_(reinterpret_cast<StaticBlockObject *>(-1)),
+    type_(Type(-1))
+{}
+
+ScopeIter::ScopeIter(StackFrame *fp)
+  : fp_(fp),
+    cur_(fp->scopeChain()),
+    block_(fp->maybeBlockChain())
+{
+    settle();
+}
+
+ScopeIter::ScopeIter(ScopeIter si, StackFrame *fp)
+  : fp_(fp),
+    cur_(si.cur_),
+    block_(si.block_),
+    type_(si.type_),
+    hasScopeObject_(si.hasScopeObject_)
+{}
+
+ScopeIter::ScopeIter(StackFrame *fp, ScopeObject &scope)
+  : fp_(fp),
+    cur_(&scope)
+{
+    /*
+     * Find the appropriate static block for this iterator, given 'scope'. We
+     * know that 'scope' is a (non-optimized) scope on fp's scope chain. We do
+     * not, however, know whether fp->maybeScopeChain() encloses 'scope'. E.g.:
+     *
+     *   let (x = 1) {
+     *     g = function() { eval('debugger') };
+     *     let (y = 1) g();
+     *   }
+     *
+     * g will have x's block in its enclosing scope but not y's. However, at
+     * the debugger statement, both the x's and y's blocks will be on
+     * fp->blockChain. Fortunately, we can compare scope object stack depths to
+     * determine the block (if any) that encloses 'scope'.
+     */
+    if (cur_->isNestedScope()) {
+        block_ = fp->maybeBlockChain();
+        while (block_) {
+            if (block_->stackDepth() <= cur_->asNestedScope().stackDepth())
+                break;
+            block_ = block_->enclosingBlock();
+        }
+        JS_ASSERT_IF(cur_->isClonedBlock(), cur_->asClonedBlock().staticBlock() == *block_);
+    } else {
+        block_ = NULL;
+    }
+    settle();
+}
+
+ScopeObject &
+ScopeIter::scope() const
+{
+    JS_ASSERT(hasScopeObject());
+    return cur_->asScope();
+}
+
+ScopeIter
+ScopeIter::enclosing() const
+{
+    JS_ASSERT(!done());
+    ScopeIter si = *this;
+    switch (type_) {
+      case Call:
+        if (hasScopeObject_) {
+            si.cur_ = &cur_->asCall().enclosingScope();
+            if (CallObjectLambdaName(si.fp_->fun()))
+                si.cur_ = &si.cur_->asDeclEnv().enclosingScope();
+        }
+        si.fp_ = NULL;
+        break;
+      case Block:
+        si.block_ = block_->enclosingBlock();
+        if (hasScopeObject_)
+            si.cur_ = &cur_->asClonedBlock().enclosingScope();
+        si.settle();
+        break;
+      case With:
+        JS_ASSERT(hasScopeObject_);
+        si.cur_ = &cur_->asWith().enclosingScope();
+        si.settle();
+        break;
+      case StrictEvalScope:
+        if (hasScopeObject_)
+            si.cur_ = &cur_->asCall().enclosingScope();
+        si.fp_ = NULL;
+        break;
+    }
+    return si;
+}
+
+void
+ScopeIter::settle()
+{
+    /*
+     * Given an iterator state (cur_, block_), figure out which (potentially
+     * optimized) scope the iterator should report. Thus, the result is a pair
+     * (type_, hasScopeObject_) where hasScopeObject_ indicates whether the
+     * scope object has been optimized away and does not exist on the scope
+     * chain. Beware: while ScopeIter iterates over the scopes of a single
+     * frame, the scope chain (pointed to by cur_) continues into the scopes of
+     * enclosing frames. Thus, it is important not to look at cur_ until it is
+     * certain that cur_ points to a scope object in the current frame. In
+     * particular, there are two tricky corner cases:
+     *  - nested non-heavyweight functions;
+     *  - non-strict direct eval.
+     * In both cases, cur_ can already be pointing into an enclosing frame's
+     * scope chain. As a final twist: even if cur_ points into an enclosing
+     * frame's scope chain, the current frame may still have uncloned blocks.
+     *
+     * Note: DebugScopeObject falls nicely into this plan: since they are only
+     * ever introduced as the *enclosing* scope of a frame, they should never
+     * show up in scope iteration and fall into the final non-scope case.
+     */
+    if (fp_->isNonEvalFunctionFrame() && !fp_->fun()->isHeavyweight()) {
+        if (block_) {
+            type_ = Block;
+            hasScopeObject_ = block_->needsClone();
+        } else {
+            type_ = Call;
+            hasScopeObject_ = false;
+        }
+    } else if (fp_->isNonStrictDirectEvalFrame() && cur_ == fp_->prev()->scopeChain()) {
+        if (block_) {
+            JS_ASSERT(!block_->needsClone());
+            type_ = Block;
+            hasScopeObject_ = false;
+        } else {
+            fp_ = NULL;
+        }
+    } else if (cur_->isWith()) {
+        JS_ASSERT_IF(fp_->isFunctionFrame(), fp_->fun()->isHeavyweight());
+        JS_ASSERT_IF(block_, block_->needsClone());
+        JS_ASSERT_IF(block_, block_->stackDepth() < cur_->asWith().stackDepth());
+        type_ = With;
+        hasScopeObject_ = true;
+    } else if (block_) {
+        type_ = Block;
+        hasScopeObject_ = block_->needsClone();
+        JS_ASSERT_IF(hasScopeObject_, cur_->asClonedBlock().staticBlock() == *block_);
+    } else if (cur_->isCall()) {
+        CallObject &callobj = cur_->asCall();
+        type_ = callobj.isForEval() ? StrictEvalScope : Call;
+        hasScopeObject_ = true;
+        JS_ASSERT_IF(type_ == Call, callobj.getCalleeFunction()->script() == fp_->script());
+    } else {
+        JS_ASSERT(!cur_->isScope());
+        JS_ASSERT(fp_->isGlobalFrame() || fp_->isDebuggerFrame());
+        fp_ = NULL;
+    }
+}
+
+/* static */ HashNumber
+ScopeIter::hash(ScopeIter si)
+{
+    /* hasScopeObject_ is determined by the other fields. */
+    return size_t(si.fp_) ^ size_t(si.cur_) ^ size_t(si.block_) ^ si.type_;
+}
+
+/* static */ bool
+ScopeIter::match(ScopeIter si1, ScopeIter si2)
+{
+    /* hasScopeObject_ is determined by the other fields. */
+    return si1.fp_ == si2.fp_ &&
+           (!si1.fp_ ||
+            (si1.cur_   == si2.cur_   &&
+             si1.block_ == si2.block_ &&
+             si1.type_  == si2.type_));
+}
+
+/*****************************************************************************/
+
+namespace js {
+
+/*
+ * DebugScopeProxy is the handler for DebugScopeObject proxy objects and mostly
+ * just wraps ScopeObjects. Having a custom handler (rather than trying to
+ * reuse js::Wrapper) gives us several important abilities:
+ *  - We want to pass the ScopeObject as the receiver to forwarded scope
+ *    property ops so that Call/Block/With ops do not all require a
+ *    'normalization' step.
+ *  - The engine has made certain assumptions about the possible reads/writes
+ *    in a scope. DebugScopeProxy allows us to prevent the debugger from
+ *    breaking those assumptions. Examples include adding shadowing variables
+ *    or changing the property attributes of bindings.
+ *  - The engine makes optimizations that are observable to the debugger. The
+ *    proxy can either hide these optimizations or make the situation more
+ *    clear to the debugger. An example is 'arguments'.
+ */
+class DebugScopeProxy : public BaseProxyHandler
+{
+    static bool isArguments(JSContext *cx, jsid id)
+    {
+        return id == NameToId(cx->runtime->atomState.argumentsAtom);
+    }
+
+    static bool isFunctionScope(ScopeObject &scope)
+    {
+        return scope.isCall() && !scope.asCall().isForEval();
+    }
+
+    /*
+     * In theory, every function scope contains an 'arguments' bindings.
+     * However, the engine only adds a binding if 'arguments' is used in the
+     * function body. Thus, from the debugger's perspective, 'arguments' may be
+     * missing from the list of bindings.
+     */
+    static bool isMissingArgumentsBinding(ScopeObject &scope)
+    {
+        return isFunctionScope(scope) &&
+               !scope.asCall().getCalleeFunction()->script()->argumentsHasLocalBinding();
+    }
+
+    /*
+     * This function creates an arguments object when the debugger requests
+     * 'arguments' for a function scope where the arguments object has been
+     * optimized away (either because the binding is missing altogether or
+     * because !ScriptAnalysis::needsArgsObj).
+     */
+    static bool checkForMissingArguments(JSContext *cx, jsid id, ScopeObject &scope,
+                                         ArgumentsObject **maybeArgsObj)
+    {
+        *maybeArgsObj = NULL;
+
+        if (!isArguments(cx, id) || !isFunctionScope(scope))
+            return true;
+
+        JSScript *script = scope.asCall().getCalleeFunction()->script();
+        if (script->needsArgsObj())
+            return true;
+
+        StackFrame *fp = scope.maybeStackFrame();
+        if (!fp) {
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_DEBUG_NOT_LIVE,
+                                 "Debugger scope");
+            return false;
+        }
+
+        *maybeArgsObj = ArgumentsObject::createUnexpected(cx, fp);
+        return true;
+    }
+
+  public:
+    static int family;
+    static DebugScopeProxy singleton;
+
+    DebugScopeProxy() : BaseProxyHandler(&family) {}
+
+    bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
+                               PropertyDescriptor *desc) MOZ_OVERRIDE
+    {
+        return getOwnPropertyDescriptor(cx, proxy, id, set, desc);
+    }
+
+    bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
+                                  PropertyDescriptor *desc) MOZ_OVERRIDE
+    {
+        ScopeObject &scope = proxy->asDebugScope().scope();
+
+        ArgumentsObject *maybeArgsObj;
+        if (!checkForMissingArguments(cx, id, scope, &maybeArgsObj))
+            return false;
+
+        if (maybeArgsObj) {
+            PodZero(desc);
+            desc->obj = proxy;
+            desc->attrs = JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT;
+            desc->value = ObjectValue(*maybeArgsObj);
+            return true;
+        }
+
+        AutoAllowUnaliasedVarAccess a(cx);
+        return JS_GetPropertyDescriptorById(cx, &scope, id, JSRESOLVE_QUALIFIED, desc);
+    }
+
+    bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp) MOZ_OVERRIDE
+    {
+        ScopeObject &scope = proxy->asDebugScope().scope();
+
+        ArgumentsObject *maybeArgsObj;
+        if (!checkForMissingArguments(cx, id, scope, &maybeArgsObj))
+            return false;
+
+        if (maybeArgsObj) {
+            *vp = ObjectValue(*maybeArgsObj);
+            return true;
+        }
+
+        AutoAllowUnaliasedVarAccess a(cx);
+        return scope.getGeneric(cx, &scope, id, vp);
+    }
+
+    bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
+                     Value *vp) MOZ_OVERRIDE
+    {
+        AutoAllowUnaliasedVarAccess a(cx);
+        ScopeObject &scope = proxy->asDebugScope().scope();
+        return scope.setGeneric(cx, id, vp, strict);
+    }
+
+    bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc) MOZ_OVERRIDE
+    {
+        return Throw(cx, id, JSMSG_CANT_REDEFINE_PROP);
+    }
+
+    bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) MOZ_OVERRIDE
+    {
+        ScopeObject &scope = proxy->asDebugScope().scope();
+
+        if (isMissingArgumentsBinding(scope) &&
+            !props.append(NameToId(cx->runtime->atomState.argumentsAtom)))
+        {
+            return false;
+        }
+
+        return GetPropertyNames(cx, &scope, JSITER_OWNONLY, &props);
+    }
+
+    bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) MOZ_OVERRIDE
+    {
+        return js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_CANT_DELETE,
+                                        JSDVG_IGNORE_STACK, IdToValue(id), NULL,
+                                        NULL, NULL);
+    }
+
+    bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) MOZ_OVERRIDE
+    {
+        ScopeObject &scope = proxy->asDebugScope().scope();
+
+        if (isMissingArgumentsBinding(scope) &&
+            !props.append(NameToId(cx->runtime->atomState.argumentsAtom)))
+        {
+            return false;
+        }
+
+        return GetPropertyNames(cx, &scope, 0, &props);
+    }
+
+    bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp) MOZ_OVERRIDE
+    {
+        ScopeObject &scope = proxy->asDebugScope().scope();
+
+        if (isArguments(cx, id) && isFunctionScope(scope)) {
+            *bp = true;
+            return true;
+        }
+
+        JSBool found;
+        if (!JS_HasPropertyById(cx, &scope, id, &found))
+            return false;
+
+        *bp = found;
+        return true;
+    }
+};
+
+}  /* namespace js */
+
+int DebugScopeProxy::family = 0;
+DebugScopeProxy DebugScopeProxy::singleton;
+
+/* static */ DebugScopeObject *
+DebugScopeObject::create(JSContext *cx, ScopeObject &scope, JSObject &enclosing)
+{
+    JSObject *obj = NewProxyObject(cx, &DebugScopeProxy::singleton, ObjectValue(scope),
+                                   NULL /* proto */, &scope.global(),
+                                   NULL /* call */, NULL /* construct */);
+    if (!obj)
+        return NULL;
+
+    JS_ASSERT(!enclosing.isScope());
+    SetProxyExtra(obj, ENCLOSING_EXTRA, ObjectValue(enclosing));
+
+    return &obj->asDebugScope();
+}
+
+ScopeObject &
+DebugScopeObject::scope() const
+{
+    return Wrapper::wrappedObject(this)->asScope();
+}
+
+JSObject &
+DebugScopeObject::enclosingScope() const
+{
+    return GetProxyExtra(this, ENCLOSING_EXTRA).toObject();
+}
+
+bool
+DebugScopeObject::isForDeclarative() const
+{
+    ScopeObject &s = scope();
+    return s.isCall() || s.isBlock() || s.isDeclEnv();
+}
+
+bool
+js_IsDebugScopeSlow(const JSObject *obj)
+{
+    return obj->getClass() == &ObjectProxyClass &&
+           GetProxyHandler(obj) == &DebugScopeProxy::singleton;
+}
+
+/*****************************************************************************/
+
+DebugScopes::DebugScopes(JSRuntime *rt)
+ : proxiedScopes(rt),
+   missingScopes(rt)
+{}
+
+DebugScopes::~DebugScopes()
+{
+    JS_ASSERT(missingScopes.empty());
+}
+
+bool
+DebugScopes::init()
+{
+    if (!proxiedScopes.init() ||
+        !missingScopes.init())
+    {
+        return false;
+    }
+    return true;
+}
+
+void
+DebugScopes::mark(JSTracer *trc)
+{
+    proxiedScopes.trace(trc);
+}
+
+void
+DebugScopes::sweep()
+{
+    /*
+     * Note: missingScopes points to debug scopes weakly not just so that debug
+     * scopes can be released more eagerly, but, more importantly, to avoid
+     * creating an uncollectable cycle with suspended generator frames.
+     */
+    for (MissingScopeMap::Enum e(missingScopes); !e.empty(); e.popFront()) {
+        if (IsAboutToBeFinalized(e.front().value))
+            e.removeFront();
+    }
+}
+
+/*
+ * Unfortunately, GetDebugScopeForFrame needs to work even outside debug mode
+ * (in particular, JS_GetFrameScopeChain does not require debug mode). Since
+ * DebugScopes::onPop* are only called in debug mode, this means we cannot
+ * use any of the maps in DebugScopes. This will produce debug scope chains
+ * that do not obey the debugger invariants but that is just fine.
+ */
+static bool
+CanUseDebugScopeMaps(JSContext *cx)
+{
+    return cx->compartment->debugMode();
+}
+
+DebugScopeObject *
+DebugScopes::hasDebugScope(JSContext *cx, ScopeObject &scope) const
+{
+    if (ObjectWeakMap::Ptr p = proxiedScopes.lookup(&scope)) {
+        JS_ASSERT(CanUseDebugScopeMaps(cx));
+        return &p->value->asDebugScope();
+    }
+    return NULL;
+}
+
+bool
+DebugScopes::addDebugScope(JSContext *cx, ScopeObject &scope, DebugScopeObject &debugScope)
+{
+    if (!CanUseDebugScopeMaps(cx))
+        return true;
+    JS_ASSERT(!proxiedScopes.has(&scope));
+    if (!proxiedScopes.put(&scope, &debugScope)) {
+        js_ReportOutOfMemory(cx);
+        return false;
+    }
+    return true;
+}
+
+DebugScopeObject *
+DebugScopes::hasDebugScope(JSContext *cx, ScopeIter si) const
+{
+    JS_ASSERT(!si.hasScopeObject());
+    if (MissingScopeMap::Ptr p = missingScopes.lookup(si)) {
+        JS_ASSERT(CanUseDebugScopeMaps(cx));
+        return p->value;
+    }
+    return NULL;
+}
+
+bool
+DebugScopes::addDebugScope(JSContext *cx, ScopeIter si, DebugScopeObject &debugScope)
+{
+    JS_ASSERT(!si.hasScopeObject());
+    if (!CanUseDebugScopeMaps(cx))
+        return true;
+    JS_ASSERT(!missingScopes.has(si));
+    if (!missingScopes.put(si, &debugScope)) {
+        js_ReportOutOfMemory(cx);
+        return false;
+    }
+    return true;
+}
+
+void
+DebugScopes::onPopCall(StackFrame *fp)
+{
+    if (fp->isYielding())
+        return;
+
+    if (!fp->fun()->isHeavyweight()) {
+        JS_ASSERT(!fp->hasCallObj());
+        if (MissingScopeMap::Ptr p = missingScopes.lookup(ScopeIter(fp))) {
+            js_PutCallObject(fp, p->value->scope().asCall());
+            missingScopes.remove(p);
+        }
+    }
+}
+
+void
+DebugScopes::onPopBlock(JSContext *cx, StackFrame *fp)
+{
+    StaticBlockObject &block = *fp->maybeBlockChain();
+    if (!block.needsClone()) {
+        JS_ASSERT(!fp->scopeChain()->isBlock() ||
+                  fp->scopeChain()->asClonedBlock().staticBlock() != block);
+        if (MissingScopeMap::Ptr p = missingScopes.lookup(ScopeIter(fp))) {
+            p->value->scope().asClonedBlock().put(fp);
+            missingScopes.remove(p);
+        }
+    }
+}
+
+void
+DebugScopes::onGeneratorFrameChange(StackFrame *from, StackFrame *to)
+{
+    for (ScopeIter toIter(to); !toIter.done(); toIter = toIter.enclosing()) {
+        if (!toIter.hasScopeObject()) {
+            if (MissingScopeMap::Ptr p = missingScopes.lookup(ScopeIter(toIter, from))) {
+                DebugScopeObject &debugScope = *p->value;
+                ScopeObject &scope = debugScope.scope();
+                if (scope.isCall()) {
+                    JS_ASSERT(scope.maybeStackFrame() == from);
+                    scope.setStackFrame(to);
+                    if (scope.enclosingScope().isDeclEnv()) {
+                        JS_ASSERT(scope.enclosingScope().asDeclEnv().maybeStackFrame() == from);
+                        scope.enclosingScope().asDeclEnv().setStackFrame(to);
+                    }
+                }
+                missingScopes.remove(p);
+                missingScopes.put(toIter, &debugScope);
+            }
+        }
+    }
+}
+
+void
+DebugScopes::onCompartmentLeaveDebugMode(JSCompartment *c)
+{
+    for (MissingScopeMap::Enum e(missingScopes); !e.empty(); e.popFront()) {
+        if (e.front().key.fp()->compartment() == c)
+            e.removeFront();
+    }
+}
+
+/*****************************************************************************/
+
+static JSObject *
+GetDebugScope(JSContext *cx, ScopeIter si);
+
+static DebugScopeObject *
+GetDebugScopeForScope(JSContext *cx, ScopeObject &scope, ScopeIter enclosing)
+{
+    DebugScopes &debugScopes = *cx->runtime->debugScopes;
+    if (DebugScopeObject *debugScope = debugScopes.hasDebugScope(cx, scope))
+        return debugScope;
+
+    JSObject *enclosingDebug = GetDebugScope(cx, enclosing);
+    if (!enclosingDebug)
+        return NULL;
+
+    JSObject &maybeDecl = scope.enclosingScope();
+    if (maybeDecl.isDeclEnv()) {
+        JS_ASSERT(CallObjectLambdaName(scope.asCall().getCalleeFunction()));
+        enclosingDebug = DebugScopeObject::create(cx, maybeDecl.asDeclEnv(), *enclosingDebug);
+        if (!enclosingDebug)
+            return NULL;
+    }
+
+    DebugScopeObject *debugScope = DebugScopeObject::create(cx, scope, *enclosingDebug);
+    if (!debugScope)
+        return NULL;
+
+    if (!debugScopes.addDebugScope(cx, scope, *debugScope))
+        return NULL;
+
+    return debugScope;
+}
+
+static DebugScopeObject *
+GetDebugScopeForMissing(JSContext *cx, ScopeIter si)
+{
+    DebugScopes &debugScopes = *cx->runtime->debugScopes;
+    if (DebugScopeObject *debugScope = debugScopes.hasDebugScope(cx, si))
+        return debugScope;
+
+    JSObject *enclosingDebug = GetDebugScope(cx, si.enclosing());
+    if (!enclosingDebug)
+        return NULL;
+
+    /*
+     * Create the missing scope object. This takes care of storing variable
+     * values after the StackFrame has been popped. To preserve scopeChain
+     * depth invariants, these lazily-reified scopes must not be put on the
+     * frame's scope chain; instead, they are maintained via DebugScopes hooks.
+     */
+    DebugScopeObject *debugScope = NULL;
+    switch (si.type()) {
+      case ScopeIter::Call: {
+        CallObject *callobj = CallObject::createForFunction(cx, si.fp());
+        if (!callobj)
+            return NULL;
+
+        JSObject &maybeDecl = callobj->enclosingScope();
+        if (maybeDecl.isDeclEnv()) {
+            JS_ASSERT(CallObjectLambdaName(callobj->getCalleeFunction()));
+            enclosingDebug = DebugScopeObject::create(cx, maybeDecl.asDeclEnv(), *enclosingDebug);
+            if (!enclosingDebug)
+                return NULL;
+        }
+
+        debugScope = DebugScopeObject::create(cx, *callobj, *enclosingDebug);
+        if (!debugScope)
+            return NULL;
+
+        if (!CanUseDebugScopeMaps(cx))
+            js_PutCallObject(si.fp(), *callobj);
+        break;
+      }
+      case ScopeIter::Block: {
+        RootedVar<StaticBlockObject *> staticBlock(cx, &si.staticBlock());
+        ClonedBlockObject *block = ClonedBlockObject::create(cx, staticBlock, si.fp());
+        if (!block)
+            return NULL;
+
+        debugScope = DebugScopeObject::create(cx, *block, *enclosingDebug);
+        if (!debugScope)
+            return NULL;
+
+        if (!CanUseDebugScopeMaps(cx))
+            block->put(si.fp());
+        break;
+      }
+      case ScopeIter::With:
+      case ScopeIter::StrictEvalScope:
+        JS_NOT_REACHED("should already have a scope");
+    }
+
+    if (!debugScopes.addDebugScope(cx, si, *debugScope))
+        return NULL;
+
+    return debugScope;
+}
+
+static JSObject *
+GetDebugScope(JSContext *cx, JSObject &obj)
+{
+    /*
+     * As an engine invariant (maintained internally and asserted by Execute),
+     * ScopeObjects and non-ScopeObjects cannot be interleaved on the scope
+     * chain; every scope chain must start with zero or more ScopeObjects and
+     * terminate with one or more non-ScopeObjects (viz., GlobalObject).
+     */
+    if (!obj.isScope()) {
+#ifdef DEBUG
+        JSObject *o = &obj;
+        while ((o = o->enclosingScope()))
+            JS_ASSERT(!o->isScope());
+#endif
+        return &obj;
+    }
+
+    /*
+     * If 'scope' is a 'with' block, then the chain is fully reified from that
+     * point outwards, and there's no point in bothering with a ScopeIter. If
+     * |scope| has an associated stack frame, we can get more detailed scope
+     * chain information from that.
+     * Note: all this frame hackery will be removed by bug 659577.
+     */
+    ScopeObject &scope = obj.asScope();
+    if (!scope.isWith() && scope.maybeStackFrame()) {
+        StackFrame *fp = scope.maybeStackFrame();
+        if (scope.isClonedBlock())
+            fp = js_LiveFrameIfGenerator(fp);
+        return GetDebugScope(cx, ScopeIter(fp, scope));
+    }
+    return GetDebugScopeForScope(cx, scope, ScopeIter(scope.enclosingScope()));
+}
+
+static JSObject *
+GetDebugScope(JSContext *cx, ScopeIter si)
+{
+    JS_CHECK_RECURSION(cx, return NULL);
+
+    if (si.done())
+        return GetDebugScope(cx, si.enclosingScope());
+
+    if (!si.hasScopeObject())
+        return GetDebugScopeForMissing(cx, si);
+
+    return GetDebugScopeForScope(cx, si.scope(), si.enclosing());
+}
+
+JSObject *
+js::GetDebugScopeForFunction(JSContext *cx, JSFunction *fun)
+{
+    assertSameCompartment(cx, fun);
+    JS_ASSERT(cx->compartment->debugMode());
+    return GetDebugScope(cx, *fun->environment());
+}
+
+JSObject *
+js::GetDebugScopeForFrame(JSContext *cx, StackFrame *fp)
+{
+    assertSameCompartment(cx, fp);
+    /* Unfortunately, we cannot JS_ASSERT(debugMode); see CanUseDebugScopeMaps. */
+    return GetDebugScope(cx, ScopeIter(fp));
+}
--- a/js/src/vm/ScopeObject.h
+++ b/js/src/vm/ScopeObject.h
@@ -39,19 +39,22 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef ScopeObject_h___
 #define ScopeObject_h___
 
 #include "jscntxt.h"
 #include "jsobj.h"
+#include "jsweakmap.h"
 
 namespace js {
 
+/*****************************************************************************/
+
 /*
  * A "scope coordinate" describes how to get from head of the scope chain to a
  * given lexically-enclosing variable. A scope coordinate has two dimensions:
  *  - hops: the number of scope objects on the scope chain to skip
  *  - binding: which binding on the scope object
  *
  * XXX: Until bug 659577 lands, this is all for show and all ScopeCoordinates
  * have hops fixed at 0 and 'binding' is just the js::Bindings binding for args
@@ -66,16 +69,18 @@ struct ScopeCoordinate
     uint16_t hops;
     uint16_t binding;
     inline ScopeCoordinate(jsbytecode *pc);
 };
 
 inline JSAtom *
 ScopeCoordinateAtom(JSScript *script, jsbytecode *pc);
 
+/*****************************************************************************/
+
 /*
  * Scope objects
  *
  * Scope objects are technically real JSObjects but only belong on the scope
  * chain (that is, fp->scopeChain() or fun->environment()). The hierarchy of
  * scope objects is:
  *
  *   JSObject                   Generic object
@@ -100,16 +105,18 @@ ScopeCoordinateAtom(JSScript *script, js
  * slots in base classes are fixed for all derived classes. Thus, for example,
  * ScopeObject::enclosingScope() can simply access a fixed slot without further
  * dynamic type information.
  *
  * NB: Static block objects are a special case: these objects are created at
  * compile time to hold the shape/binding information from which block objects
  * are cloned at runtime. These objects should never escape into the wild and
  * support a restricted set of ScopeObject operations.
+ *
+ * See also "Debug scope objects" below.
  */
 
 class ScopeObject : public JSObject
 {
     /* Use maybeStackFrame() instead. */
     void *getPrivate() const;
 
   protected:
@@ -121,17 +128,18 @@ class ScopeObject : public JSObject
      * does not derive ScopeObject (it has a completely different layout), the
      * enclosing scope of a ScopeObject is necessarily non-null.
      */
     inline JSObject &enclosingScope() const;
     inline bool setEnclosingScope(JSContext *cx, HandleObject obj);
 
     /*
      * The stack frame for this scope object, if the frame is still active.
-     * Note: these members may not be called for a StaticBlockObject.
+     * Note: these members may not be called for a StaticBlockObject or
+     * WithObject.
      */
     inline StackFrame *maybeStackFrame() const;
     inline void setStackFrame(StackFrame *frame);
 
     /* For jit access. */
     static inline size_t offsetOfEnclosingScope();
 };
 
@@ -205,27 +213,31 @@ class NestedScopeObject : public ScopeOb
 
   public:
     /* Return the abstract stack depth right before entering this nested scope. */
     uint32_t stackDepth() const;
 };
 
 class WithObject : public NestedScopeObject
 {
+    /* These ScopeObject operations are not valid on a with object. */
+    js::StackFrame *maybeStackFrame() const;
+    void setStackFrame(StackFrame *frame);
+
     static const unsigned THIS_SLOT = 2;
 
     /* Use WithObject::object() instead. */
     JSObject *getProto() const;
 
   public:
     static const unsigned RESERVED_SLOTS = 3;
     static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT4;
 
     static WithObject *
-    create(JSContext *cx, StackFrame *fp, HandleObject proto, HandleObject enclosing, uint32_t depth);
+    create(JSContext *cx, HandleObject proto, HandleObject enclosing, uint32_t depth);
 
     /* Return object for the 'this' class hook. */
     JSObject &withThis() const;
 
     /* Return the 'o' in 'with (o)'. */
     JSObject &object() const;
 };
 
@@ -267,43 +279,209 @@ class StaticBlockObject : public BlockOb
 
     /*
      * A let binding is aliased is accessed lexically by nested functions or
      * dynamically through dynamic name lookup (eval, with, function::, etc).
      */
     void setAliased(unsigned i, bool aliased);
     bool isAliased(unsigned i);
 
+    /*
+     * A static block object is cloned (when entering the block) iff some
+     * variable of the block isAliased.
+     */
+    bool needsClone() const;
+
     const Shape *addVar(JSContext *cx, jsid id, int index, bool *redeclared);
 };
 
 class ClonedBlockObject : public BlockObject
 {
   public:
-    static ClonedBlockObject *create(JSContext *cx, Handle<StaticBlockObject*> block, StackFrame *fp);
+    static ClonedBlockObject *create(JSContext *cx, Handle<StaticBlockObject *> block,
+                                     StackFrame *fp);
 
     /* The static block from which this block was cloned. */
     StaticBlockObject &staticBlock() const;
 
     /*
      * When this block's stack slots are about to be popped, 'put' must be
      * called to copy the slot values into this block's object slots.
      */
-    void put(JSContext *cx);
+    void put(StackFrame *fp);
 
     /* Assuming 'put' has been called, return the value of the ith let var. */
     const Value &closedSlot(unsigned i);
 
     /* Return whether this environment contains 'name' and, if so, its value. */
     bool containsVar(PropertyName *name, Value *vp, JSContext *cx);
 };
 
 template<XDRMode mode>
 bool
 XDRStaticBlockObject(XDRState<mode> *xdr, JSScript *script, StaticBlockObject **objp);
 
 extern JSObject *
 CloneStaticBlockObject(JSContext *cx, StaticBlockObject &srcBlock,
                        const AutoObjectVector &objects, JSScript *src);
 
-}  /* namespace js */
+/*****************************************************************************/
+
+/*
+ * A scope iterator describes the active scopes enclosing the current point of
+ * execution for a single frame, proceeding from inner to outer. Here, "frame"
+ * means a single activation of: a function, eval, or global code. By design,
+ * ScopeIter exposes *all* scopes, even those that have been optimized away
+ * (i.e., no ScopeObject was created when entering the scope and thus there is
+ * no ScopeObject on fp->scopeChain representing the scope).
+ *
+ * Note: ScopeIter iterates over all scopes *within* a frame which means that
+ * all scopes are ScopeObjects. In particular, the GlobalObject enclosing
+ * global code (and any random objects passed as scopes to Execute) will not
+ * be included.
+ */
+class ScopeIter
+{
+  public:
+    enum Type { Call, Block, With, StrictEvalScope };
+
+  private:
+    StackFrame *fp_;
+    JSObject *cur_;
+    StaticBlockObject *block_;
+    Type type_;
+    bool hasScopeObject_;
+
+    void settle();
+
+  public:
+    /* The default constructor leaves ScopeIter totally invalid */
+    explicit ScopeIter();
+
+    /* Constructing from StackFrame places ScopeIter on the innermost scope. */
+    explicit ScopeIter(StackFrame *fp);
+
+    /*
+     * Without a StackFrame, the resulting ScopeIter is done() with
+     * enclosingScope() as given.
+     */
+    explicit ScopeIter(JSObject &enclosingScope);
+
+    /*
+     * For the special case of generators, copy the given ScopeIter, with 'fp'
+     * as the StackFrame instead of si.fp(). Not for general use.
+     */
+    ScopeIter(ScopeIter si, StackFrame *fp);
+
+    /* Like ScopeIter(StackFrame *) except start at 'scope'. */
+    ScopeIter(StackFrame *fp, ScopeObject &scope);
+
+    bool done() const { return !fp_; }
+
+    /* If done(): */
+
+    JSObject &enclosingScope() const { JS_ASSERT(done()); return *cur_; }
+
+    /* If !done(): */
+
+    ScopeIter enclosing() const;
+
+    StackFrame *fp() const { JS_ASSERT(!done()); return fp_; }
+    Type type() const { JS_ASSERT(!done()); return type_; }
+    bool hasScopeObject() const { JS_ASSERT(!done()); return hasScopeObject_; }
+    ScopeObject &scope() const;
+
+    StaticBlockObject &staticBlock() const { JS_ASSERT(type() == Block); return *block_; }
+
+    /* For use as hash policy */
+    typedef ScopeIter Lookup;
+    static HashNumber hash(ScopeIter si);
+    static bool match(ScopeIter si1, ScopeIter si2);
+};
+
+/*****************************************************************************/
 
+/*
+ * Debug scope objects
+ *
+ * The debugger effectively turns every opcode into a potential direct eval.
+ * Naively, this would require creating a ScopeObject for every call/block
+ * scope and using JSOP_GETALIASEDVAR for every access. To optimize this, the
+ * engine assumes there is no debugger and optimizes scope access and creation
+ * accordingly. When the debugger wants to perform an unexpected eval-in-frame
+ * (or other, similar dynamic-scope-requiring operations), fp->scopeChain is
+ * now incomplete: it may not contain all, or any, of the ScopeObjects to
+ * represent the current scope.
+ *
+ * To resolve this, the debugger first calls GetDebugScopeFor(Function|Frame)
+ * to synthesize a "debug scope chain". A debug scope chain is just a chain of
+ * objects that fill in missing scopes and protect the engine from unexpected
+ * access. (The latter means that some debugger operations, like adding a new
+ * binding to a lexical scope, can fail when a true eval would succeed.) To do
+ * both of these things, GetDebugScopeFor* creates a new proxy DebugScopeObject
+ * to sit in front of every existing ScopeObject.
+ *
+ * GetDebugScopeFor* ensures the invariant that the same DebugScopeObject is
+ * always produced for the same underlying scope (optimized or not!). This is
+ * maintained by some bookkeeping information stored in DebugScopes.
+ */
+
+extern JSObject *
+GetDebugScopeForFunction(JSContext *cx, JSFunction *fun);
+
+extern JSObject *
+GetDebugScopeForFrame(JSContext *cx, StackFrame *fp);
+
+/* Provides debugger access to a scope. */
+class DebugScopeObject : public JSObject
+{
+    static const unsigned ENCLOSING_EXTRA = 0;
+
+  public:
+    static DebugScopeObject *create(JSContext *cx, ScopeObject &scope, JSObject &enclosing);
+
+    ScopeObject &scope() const;
+    JSObject &enclosingScope() const;
+
+    /* Currently, the 'declarative' scopes are Call and Block. */
+    bool isForDeclarative() const;
+};
+
+/* Maintains runtime-wide debug scope bookkeeping information. */
+class DebugScopes
+{
+    /* The map from (non-debug) scopes to debug scopes. */
+    typedef WeakMap<HeapPtrObject, HeapPtrObject> ObjectWeakMap;
+    ObjectWeakMap proxiedScopes;
+
+    /*
+     * The map from live frames which have optimized-away scopes to the
+     * corresponding debug scopes.
+     */
+    typedef HashMap<ScopeIter, DebugScopeObject *, ScopeIter, RuntimeAllocPolicy> MissingScopeMap;
+    MissingScopeMap missingScopes;
+
+  public:
+    DebugScopes(JSRuntime *rt);
+    ~DebugScopes();
+    bool init();
+
+    void mark(JSTracer *trc);
+    void sweep();
+
+    DebugScopeObject *hasDebugScope(JSContext *cx, ScopeObject &scope) const;
+    bool addDebugScope(JSContext *cx, ScopeObject &scope, DebugScopeObject &debugScope);
+
+    DebugScopeObject *hasDebugScope(JSContext *cx, ScopeIter si) const;
+    bool addDebugScope(JSContext *cx, ScopeIter si, DebugScopeObject &debugScope);
+
+    /*
+     * In debug-mode, these must be called whenever exiting a call/block or
+     * when activating/yielding a generator.
+     */
+    void onPopCall(StackFrame *fp);
+    void onPopBlock(JSContext *cx, StackFrame *fp);
+    void onGeneratorFrameChange(StackFrame *from, StackFrame *to);
+    void onCompartmentLeaveDebugMode(JSCompartment *c);
+};
+
+}  /* namespace js */
 #endif /* ScopeObject_h___ */
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -69,17 +69,17 @@ IsCacheableNonGlobalScope(JSObject *obj)
     return cacheable;
 }
 
 inline HandleObject
 StackFrame::scopeChain() const
 {
     JS_ASSERT_IF(!(flags_ & HAS_SCOPECHAIN), isFunctionFrame());
     if (!(flags_ & HAS_SCOPECHAIN)) {
-        scopeChain_ = callee().toFunction()->environment();
+        scopeChain_ = callee().environment();
         flags_ |= HAS_SCOPECHAIN;
     }
     return HandleObject::fromMarkedLocation(&scopeChain_);
 }
 
 inline GlobalObject &
 StackFrame::global() const
 {
@@ -306,38 +306,36 @@ StackFrame::actualArgsEnd() const
 {
     JS_ASSERT(hasArgs());
     if (JS_UNLIKELY(flags_ & OVERFLOW_ARGS))
         return formalArgs() - 2;
     return formalArgs() + numActualArgs();
 }
 
 inline void
-StackFrame::setScopeChainNoCallObj(JSObject &obj)
+StackFrame::setScopeChain(JSObject &obj)
 {
 #ifdef DEBUG
     JS_ASSERT(&obj != NULL);
-    if (&obj != sInvalidScopeChain) {
-        if (hasCallObj()) {
-            JSObject *pobj = &obj;
-            while (pobj && pobj->getPrivate() != this)
-                pobj = pobj->enclosingScope();
-            JS_ASSERT(pobj);
-        } else {
-            for (JSObject *pobj = &obj; pobj->isScope(); pobj = pobj->enclosingScope())
-                JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
-        }
+    if (hasCallObj()) {
+        JSObject *pobj = &obj;
+        while (pobj && !pobj->isWith() && pobj->asScope().maybeStackFrame() != this)
+            pobj = pobj->enclosingScope();
+        JS_ASSERT(pobj);
+    } else {
+        for (JSObject *pobj = &obj; pobj->isScope() && !pobj->isWith(); pobj = pobj->enclosingScope())
+            JS_ASSERT_IF(pobj->isCall(), pobj->asScope().maybeStackFrame() != this);
     }
 #endif
     scopeChain_ = &obj;
     flags_ |= HAS_SCOPECHAIN;
 }
 
 inline void
-StackFrame::setScopeChainWithOwnCallObj(CallObject &obj)
+StackFrame::initScopeChain(CallObject &obj)
 {
     JS_ASSERT(&obj != NULL);
     JS_ASSERT(!hasCallObj() && obj.maybeStackFrame() == this);
     scopeChain_ = &obj;
     flags_ |= HAS_SCOPECHAIN | HAS_CALL_OBJ;
 }
 
 inline CallObject &
@@ -363,39 +361,44 @@ StackFrame::maintainNestingState() const
 
 inline bool
 StackFrame::functionPrologue(JSContext *cx)
 {
     JS_ASSERT(isNonEvalFunctionFrame());
     JS_ASSERT(!isGeneratorFrame());
 
     if (fun()->isHeavyweight()) {
-        if (!CallObject::createForFunction(cx, this))
+        CallObject *callobj = CallObject::createForFunction(cx, this);
+        if (!callobj)
             return false;
+        initScopeChain(*callobj);
     } else {
         /* Force instantiation of the scope chain, for JIT frames. */
         scopeChain();
     }
 
     if (script()->nesting()) {
         JS_ASSERT(maintainNestingState());
         types::NestingPrologue(cx, this);
     }
 
     return true;
 }
 
 inline void
-StackFrame::functionEpilogue()
+StackFrame::functionEpilogue(JSContext *cx)
 {
     JS_ASSERT(isNonEvalFunctionFrame());
 
+    if (cx->compartment->debugMode())
+        cx->runtime->debugScopes->onPopCall(this);
+
     if (flags_ & (HAS_ARGS_OBJ | HAS_CALL_OBJ)) {
         if (hasCallObj())
-            js_PutCallObject(this);
+            js_PutCallObject(this, scopeChain_->asCall());
         if (hasArgsObj())
             js_PutArgsObject(this);
     }
 
     if (maintainNestingState())
         types::NestingEpilogue(this);
 }
 
@@ -409,17 +412,17 @@ StackFrame::updateEpilogueFlags()
             /*
              * For function frames, the call object may or may not have have an
              * enclosing DeclEnv object, so we use the callee's parent, since
              * it was the initial scope chain. For global (strict) eval frames,
              * there is no callee, but the call object's parent is the initial
              * scope chain.
              */
             scopeChain_ = isFunctionFrame()
-                          ? callee().toFunction()->environment()
+                          ? callee().environment()
                           : &scopeChain_->asScope().enclosingScope();
             flags_ &= ~HAS_CALL_OBJ;
         }
     }
 
     /*
      * For outer/inner function frames, undo the active frame balancing so that
      * when we redo it in the epilogue we get the right final value. The other
@@ -558,17 +561,17 @@ ContextStack::getFixupFrame(JSContext *c
 
 JS_ALWAYS_INLINE void
 ContextStack::popInlineFrame(FrameRegs &regs)
 {
     JS_ASSERT(onTop());
     JS_ASSERT(&regs == &seg_->regs());
 
     StackFrame *fp = regs.fp();
-    fp->functionEpilogue();
+    fp->functionEpilogue(cx_);
 
     Value *newsp = fp->actualArgs() - 1;
     JS_ASSERT(newsp >= fp->prev()->base());
 
     newsp[-1] = fp->returnValue();
     regs.popFrame(newsp);
 }
 
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -118,23 +118,23 @@ StackFrame::initExecuteFrame(JSScript *s
 
 void
 StackFrame::initDummyFrame(JSContext *cx, JSObject &chain)
 {
     PodZero(this);
     flags_ = DUMMY | HAS_PREVPC | HAS_SCOPECHAIN;
     initPrev(cx);
     JS_ASSERT(chain.isGlobal());
-    setScopeChainNoCallObj(chain);
+    setScopeChain(chain);
 }
 
 template <class T, class U, StackFrame::TriggerPostBarriers doPostBarrier>
 void
-StackFrame::stealFrameAndSlots(StackFrame *fp, T *vp, StackFrame *otherfp, U *othervp,
-                               Value *othersp)
+StackFrame::stealFrameAndSlots(JSContext *cx, StackFrame *fp, T *vp,
+                               StackFrame *otherfp, U *othervp, Value *othersp)
 {
     JS_ASSERT((U *)vp == (U *)this - ((U *)otherfp - othervp));
     JS_ASSERT((Value *)othervp == otherfp->actualArgs() - 2);
     JS_ASSERT(othersp >= otherfp->slots());
     JS_ASSERT(othersp <= otherfp->base() + otherfp->numSlots());
     JS_ASSERT((T *)fp - vp == (U *)otherfp - othervp);
 
     /* Copy args, StackFrame, and slots. */
@@ -170,24 +170,27 @@ StackFrame::stealFrameAndSlots(StackFram
     if (hasArgsObj()) {
         ArgumentsObject &argsobj = argsObj();
         if (argsobj.isNormalArguments())
             argsobj.setStackFrame(this);
         else
             JS_ASSERT(!argsobj.maybeStackFrame());
         otherfp->flags_ &= ~HAS_ARGS_OBJ;
     }
+
+    if (cx->compartment->debugMode())
+        cx->runtime->debugScopes->onGeneratorFrameChange(otherfp, this);
 }
 
 /* Note: explicit instantiation for js_NewGenerator located in jsiter.cpp. */
 template void StackFrame::stealFrameAndSlots<Value, HeapValue, StackFrame::NoPostBarrier>(
-                                             StackFrame *, Value *,
+                                             JSContext *, StackFrame *, Value *,
                                              StackFrame *, HeapValue *, Value *);
 template void StackFrame::stealFrameAndSlots<HeapValue, Value, StackFrame::DoPostBarrier>(
-                                             StackFrame *, HeapValue *,
+                                             JSContext *, StackFrame *, HeapValue *,
                                              StackFrame *, Value *, Value *);
 
 void
 StackFrame::writeBarrierPost()
 {
     /* This needs to follow the same rules as in js_TraceStackFrame. */
     if (scopeChain_)
         JSObject::writeBarrierPost(scopeChain_, (void *)&scopeChain_);
@@ -203,20 +206,16 @@ StackFrame::writeBarrierPost()
         } else {
             JSScript::writeBarrierPost(exec.script, (void *)&exec.script);
         }
     }
     if (hasReturnValue())
         HeapValue::writeBarrierPost(rval_, &rval_);
 }
 
-#ifdef DEBUG
-JSObject *const StackFrame::sInvalidScopeChain = (JSObject *)0xbeef;
-#endif
-
 jsbytecode *
 StackFrame::prevpcSlow(JSInlinedSite **pinlined)
 {
     JS_ASSERT(!(flags_ & HAS_PREVPC));
 #if defined(JS_METHODJIT) && defined(JS_MONOIC)
     StackFrame *p = prev();
     mjit::JITScript *jit = p->script()->getJIT(p->isConstructing(), p->compartment()->needsBarrier());
     prevpc_ = jit->nativeToPC(ncode_, &prevInline_);
@@ -248,16 +247,59 @@ StackFrame::pcQuadratic(const ContextSta
         return regs.pc;
     }
 
     if (!next)
         next = seg.computeNextFrame(this);
     return next->prevpc(pinlined);
 }
 
+bool
+StackFrame::pushBlock(JSContext *cx, StaticBlockObject &block)
+{
+    JS_ASSERT_IF(hasBlockChain(), blockChain_ == block.enclosingBlock());
+
+    if (block.needsClone()) {
+        RootedVar<StaticBlockObject *> blockHandle(cx, &block);
+        ClonedBlockObject *clone = ClonedBlockObject::create(cx, blockHandle, this);
+        if (!clone)
+            return false;
+
+        scopeChain_ = clone;
+    }
+
+    flags_ |= HAS_BLOCKCHAIN;
+    blockChain_ = &block;
+    return true;
+}
+
+void
+StackFrame::popBlock(JSContext *cx)
+{
+    JS_ASSERT(hasBlockChain());
+
+    if (cx->compartment->debugMode())
+        cx->runtime->debugScopes->onPopBlock(cx, this);
+
+    if (blockChain_->needsClone()) {
+        ClonedBlockObject &clone = scopeChain()->asClonedBlock();
+        JS_ASSERT(clone.staticBlock() == *blockChain_);
+        clone.put(cx->fp());
+        scopeChain_ = &clone.enclosingScope();
+    }
+
+    blockChain_ = blockChain_->enclosingBlock();
+}
+
+void
+StackFrame::popWith(JSContext *cx)
+{
+    setScopeChain(scopeChain()->asWith().enclosingScope());
+}
+
 void
 StackFrame::mark(JSTracer *trc)
 {
     /*
      * Normally we would use MarkRoot here, except that generators also take
      * this path. However, generators use a special write barrier when the stack
      * frame is copied to the floating frame. Therefore, no barrier is needed.
      */
@@ -878,17 +920,17 @@ void
 ContextStack::popFrame(const FrameGuard &fg)
 {
     JS_ASSERT(fg.pushed());
     JS_ASSERT(onTop());
     JS_ASSERT(space().firstUnused() == fg.regs_.sp);
     JS_ASSERT(&fg.regs_ == &seg_->regs());
 
     if (fg.regs_.fp()->isNonEvalFunctionFrame())
-        fg.regs_.fp()->functionEpilogue();
+        fg.regs_.fp()->functionEpilogue(cx_);
 
     seg_->popRegs(fg.prevRegs_);
     if (fg.pushedSeg_)
         popSegment();
 
     /*
      * NB: this code can call out and observe the stack (e.g., through GC), so
      * it should only be called from a consistent stack state.
@@ -924,17 +966,17 @@ ContextStack::pushGeneratorFrame(JSConte
      * object has a trace hook and cannot be nursery allocated.
      */
     JSObject *genobj = js_FloatingFrameToGenerator(genfp)->obj;
     JS_ASSERT(genobj->getClass()->trace);
     JSObject::writeBarrierPre(genobj);
 
     /* Copy from the generator's floating frame to the stack. */
     stackfp->stealFrameAndSlots<Value, HeapValue, StackFrame::NoPostBarrier>(
-                                stackfp, stackvp, genfp, genvp, gen->regs.sp);
+                                cx, stackfp, stackvp, genfp, genvp, gen->regs.sp);
     stackfp->resetGeneratorPrev(cx);
     stackfp->unsetFloatingGenerator();
     gfg->regs_.rebaseFromTo(gen->regs, *stackfp);
 
     gfg->prevRegs_ = seg_->pushRegs(gfg->regs_);
     JS_ASSERT(space().firstUnused() == gfg->regs_.sp);
     gfg->setPushed(*this);
     return true;
@@ -949,17 +991,17 @@ ContextStack::popGeneratorFrame(const Ge
 
     const FrameRegs &stackRegs = gfg.regs_;
     StackFrame *stackfp = stackRegs.fp();
     Value *stackvp = gfg.stackvp_;
 
     /* Copy from the stack to the generator's floating frame. */
     gen->regs.rebaseFromTo(stackRegs, *genfp);
     genfp->stealFrameAndSlots<HeapValue, Value, StackFrame::DoPostBarrier>(
-                              genfp, genvp, stackfp, stackvp, stackRegs.sp);
+                              cx_, genfp, genvp, stackfp, stackvp, stackRegs.sp);
     genfp->setFloatingGenerator();
 
     /* ~FrameGuard/popFrame will finish the popping. */
     JS_ASSERT(ImplicitCast<const FrameGuard>(gfg).pushed());
 }
 
 bool
 ContextStack::saveFrameChain()
@@ -1345,17 +1387,17 @@ StackIter::isConstructing() const
 JSFunction *
 StackIter::callee() const
 {
     switch (state_) {
       case DONE:
         break;
       case SCRIPTED:
         JS_ASSERT(isFunctionFrame());
-        return fp()->callee().toFunction();
+        return &fp()->callee();
       case NATIVE:
       case IMPLICIT_NATIVE:
         return nativeArgs().callee().toFunction();
     }
     JS_NOT_REACHED("Unexpected state");
     return NULL;
 }
 
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -431,18 +431,18 @@ class StackFrame
                           const Value &thisv, JSObject &scopeChain, ExecuteType type);
 
     /* Used when activating generators. */
     enum TriggerPostBarriers {
         DoPostBarrier = true,
         NoPostBarrier = false
     };
     template <class T, class U, TriggerPostBarriers doPostBarrier>
-    void stealFrameAndSlots(StackFrame *fp, T *vp, StackFrame *otherfp, U *othervp,
-                            Value *othersp);
+    void stealFrameAndSlots(JSContext *cx, StackFrame *fp, T *vp,
+                            StackFrame *otherfp, U *othervp, Value *othersp);
     void writeBarrierPost();
 
     /* Perhaps one fine day we will remove dummy frames. */
     void initDummyFrame(JSContext *cx, JSObject &chain);
 
     /*
      * Stack frame type
      *
@@ -500,16 +500,24 @@ class StackFrame
     inline bool isStrictEvalFrame() const {
         return isEvalFrame() && script()->strictModeCode;
     }
 
     bool isNonStrictEvalFrame() const {
         return isEvalFrame() && !script()->strictModeCode;
     }
 
+    bool isDirectEvalFrame() const {
+        return isEvalFrame() && script()->staticLevel > 0;
+    }
+
+    bool isNonStrictDirectEvalFrame() const {
+        return isNonStrictEvalFrame() && isDirectEvalFrame();
+    }
+
     /*
      * Previous frame
      *
      * A frame's 'prev' frame is either null or the previous frame pointed to
      * by cx->regs->fp when this frame was pushed. Often, given two prev-linked
      * frames, the next-frame is a function or eval that was called by the
      * prev-frame, but not always: the prev-frame may have called a native that
      * reentered the VM through JS_CallFunctionValue on the same context
@@ -797,19 +805,19 @@ class StackFrame
      * Callee
      *
      * Only function frames have a callee. An eval frame in a function has the
      * same callee as its containing function frame. maybeCalleev can be used
      * to return a value that is either the callee object (for function frames) or
      * null (for global frames).
      */
 
-    JSObject &callee() const {
+    JSFunction &callee() const {
         JS_ASSERT(isFunctionFrame());
-        return calleev().toObject();
+        return *calleev().toObject().toFunction();
     }
 
     const Value &calleev() const {
         JS_ASSERT(isFunctionFrame());
         return mutableCalleev();
     }
 
     const Value &maybeCalleev() const {
@@ -867,60 +875,18 @@ class StackFrame
 
     bool hasCallObj() const {
         bool ret = !!(flags_ & HAS_CALL_OBJ);
         JS_ASSERT_IF(ret, !isNonStrictEvalFrame());
         return ret;
     }
 
     inline CallObject &callObj() const;
-    inline void setScopeChainNoCallObj(JSObject &obj);
-    inline void setScopeChainWithOwnCallObj(CallObject &obj);
-
-    /* Block chain */
-
-    bool hasBlockChain() const {
-        return (flags_ & HAS_BLOCKCHAIN) && blockChain_;
-    }
-
-    StaticBlockObject *maybeBlockChain() {
-        return (flags_ & HAS_BLOCKCHAIN) ? blockChain_ : NULL;
-    }
-
-    StaticBlockObject &blockChain() const {
-        JS_ASSERT(hasBlockChain());
-        return *blockChain_;
-    }
-
-    void setBlockChain(StaticBlockObject *obj) {
-        flags_ |= HAS_BLOCKCHAIN;
-        blockChain_ = obj;
-    }
-
-    /*
-     * Prologue for function frames: make a call object for heavyweight
-     * functions, and maintain type nesting invariants.
-     */
-    inline bool functionPrologue(JSContext *cx);
-
-    /*
-     * Epilogue for function frames: put any args or call object for the frame
-     * which may still be live, and maintain type nesting invariants. Note:
-     * this does mark the epilogue as having been completed, since the frame is
-     * about to be popped. Use updateEpilogueFlags for this.
-     */
-    inline void functionEpilogue();
-
-    /*
-     * If callObj() or argsObj() have already been put, update our flags
-     * accordingly. This call must be followed by a later functionEpilogue.
-     */
-    inline void updateEpilogueFlags();
-
-    inline bool maintainNestingState() const;
+    inline void initScopeChain(CallObject &callobj);
+    inline void setScopeChain(JSObject &obj);
 
     /*
      * Variables object
      *
      * Given that a (non-dummy) StackFrame corresponds roughly to a ES5
      * Execution Context (ES5 10.3), StackFrame::varObj corresponds to the
      * VariableEnvironment component of a Exection Context. Intuitively, the
      * variables object is where new bindings (variables and functions) are
@@ -929,16 +895,60 @@ class StackFrame
      * the JSAPI allows calls of Execute to specify a variables object on the
      * scope chain other than the call/global object. This allows embeddings to
      * run multiple scripts under the same global, each time using a new
      * variables object to collect and discard the script's global variables.
      */
 
     inline JSObject &varObj();
 
+    /* Block chain */
+
+    bool hasBlockChain() const {
+        return (flags_ & HAS_BLOCKCHAIN) && blockChain_;
+    }
+
+    StaticBlockObject *maybeBlockChain() {
+        return (flags_ & HAS_BLOCKCHAIN) ? blockChain_ : NULL;
+    }
+
+    StaticBlockObject &blockChain() const {
+        JS_ASSERT(hasBlockChain());
+        return *blockChain_;
+    }
+
+    /* Enter/exit execution of a lexical block. */
+    bool pushBlock(JSContext *cx, StaticBlockObject &block);
+    void popBlock(JSContext *cx);
+
+    /* Exits (via execution or exception) a with block. */
+    void popWith(JSContext *cx);
+
+    /*
+     * Prologue for function frames: make a call object for heavyweight
+     * functions, and maintain type nesting invariants.
+     */
+    inline bool functionPrologue(JSContext *cx);
+
+    /*
+     * Epilogue for function frames: put any args or call object for the frame
+     * which may still be live, and maintain type nesting invariants. Note:
+     * this does mark the epilogue as having been completed, since the frame is
+     * about to be popped. Use updateEpilogueFlags for this.
+     */
+    inline void functionEpilogue(JSContext *cx);
+
+    /*
+     * If callObj() or argsObj() have already been put, update our flags
+     * accordingly. This call must be followed by a later functionEpilogue.
+     */
+    inline void updateEpilogueFlags();
+
+    inline bool maintainNestingState() const;
+
     /*
      * Frame compartment
      *
      * A stack frame's compartment is the frame's containing context's
      * compartment when the frame was pushed.
      */
 
     inline JSCompartment *compartment() const;
@@ -1125,21 +1135,16 @@ class StackFrame
     void setFinishedInInterpreter() {
         flags_ |= FINISHED_IN_INTERP;
     }
 
     bool finishedInInterpreter() const {
         return !!(flags_ & FINISHED_IN_INTERP);
     }
 
-#ifdef DEBUG
-    /* Poison scopeChain value set before a frame is flushed. */
-    static JSObject *const sInvalidScopeChain;
-#endif
-
   public:
     /* Public, but only for JIT use: */
 
     static size_t offsetOfFlags() {
         return offsetof(StackFrame, flags_);
     }
 
     static size_t offsetOfExec() {
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -449,22 +449,19 @@ mozJSComponentLoader::ReallyInit()
         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
     if (!secman)
         return NS_ERROR_FAILURE;
 
     rv = secman->GetSystemPrincipal(getter_AddRefs(mSystemPrincipal));
     if (NS_FAILED(rv) || !mSystemPrincipal)
         return NS_ERROR_FAILURE;
 
-    if (!mModules.Init(32))
-        return NS_ERROR_OUT_OF_MEMORY;
-    if (!mImports.Init(32))
-        return NS_ERROR_OUT_OF_MEMORY;
-    if (!mInProgressImports.Init(32))
-        return NS_ERROR_OUT_OF_MEMORY;
+    mModules.Init(32);
+    mImports.Init(32);
+    mInProgressImports.Init(32);
 
     nsCOMPtr<nsIObserverService> obsSvc =
         do_GetService(kObserverServiceContractID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = obsSvc->AddObserver(this, "xpcom-shutdown-loaders", false);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -602,18 +599,17 @@ mozJSComponentLoader::LoadModule(FileLoc
         /* XXX report error properly */
 #ifdef DEBUG
         fprintf(stderr, "mJCL: couldn't get nsIModule from jsval\n");
 #endif
         return NULL;
     }
 
     // Cache this module for later
-    if (!mModules.Put(spec, entry))
-        return NULL;
+    mModules.Put(spec, entry);
 
     // The hash owns the ModuleEntry now, forget about it
     return entry.forget();
 }
 
 // Some stack based classes for cleaning up on early return
 #ifdef HAVE_PR_MEMMAP
 class FileAutoCloser
@@ -1136,18 +1132,19 @@ mozJSComponentLoader::ImportInto(const n
     nsCAutoString key;
     rv = resolvedURI->GetSpec(key);
     NS_ENSURE_SUCCESS(rv, rv);
 
     ModuleEntry* mod;
     nsAutoPtr<ModuleEntry> newEntry;
     if (!mImports.Get(key, &mod) && !mInProgressImports.Get(key, &mod)) {
         newEntry = new ModuleEntry;
-        if (!newEntry || !mInProgressImports.Put(key, newEntry))
+        if (!newEntry)
             return NS_ERROR_OUT_OF_MEMORY;
+        mInProgressImports.Put(key, newEntry);
 
         JS::Anchor<jsval> exception(JSVAL_VOID);
         rv = GlobalForLocation(sourceLocalFile, resURI, &newEntry->global,
                                &newEntry->location, &exception.get());
 
         mInProgressImports.Remove(key);
 
         if (NS_FAILED(rv)) {
@@ -1251,18 +1248,17 @@ mozJSComponentLoader::ImportInto(const n
                      PromiseFlatCString(aLocation).get()));
             }
 #endif
         }
     }
 
     // Cache this module for later
     if (newEntry) {
-        if (!mImports.Put(key, newEntry))
-            return NS_ERROR_OUT_OF_MEMORY;
+        mImports.Put(key, newEntry);
         newEntry.forget();
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 mozJSComponentLoader::Unload(const nsACString & aLocation)
--- a/js/xpconnect/src/dombindings.cpp
+++ b/js/xpconnect/src/dombindings.cpp
@@ -435,18 +435,18 @@ ListBase<LC>::getPrototype(JSContext *cx
         scope->GetCachedDOMPrototypes();
 
     JSObject *interfacePrototype;
     if (cache.IsInitialized()) {
         if (cache.Get(sInterfaceClass.name, &interfacePrototype)) {
             xpc_UnmarkGrayObject(interfacePrototype);
             return interfacePrototype;
         }
-    } else if (!cache.Init()) {
-        return NULL;
+    } else {
+        cache.Init();
     }
 
     JSObject* proto = Base::getPrototype(cx, scope, receiver);
     if (!proto)
         return NULL;
 
     JSObject *global = scope->GetGlobalJSObject();
     interfacePrototype = JS_NewObject(cx, Jsvalify(&sInterfacePrototypeClass), proto, global);
@@ -486,17 +486,17 @@ ListBase<LC>::getPrototype(JSContext *cx
     if (!JS_DefineProperty(cx, receiver, sInterfaceClass.name, OBJECT_TO_JSVAL(interface), NULL,
                            NULL, 0))
         return NULL;
 
     // This needs to happen after we've set all our own properties on interfacePrototype, to
     // overwrite the value set by InvalidateProtoShape_add when we set our own properties.
     js::SetReservedSlot(interfacePrototype, 0, PrivateUint32Value(USE_CACHE));
 
-    if (!cache.Put(sInterfaceClass.name, interfacePrototype))
+    if (!cache.Put(sInterfaceClass.name, interfacePrototype, fallible_t()))
         return NULL;
 
     return interfacePrototype;
 }
 
 template<class LC>
 JSObject *
 ListBase<LC>::create(JSContext *cx, JSObject *scope, ListType *aList,
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -4375,41 +4375,41 @@ xpc_NewSystemInheritingJSObject(JSContex
 
 nsISupports *
 XPC_GetIdentityObject(JSContext *cx, JSObject *obj);
 
 namespace xpc {
 
 struct CompartmentPrivate
 {
+    typedef nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> ExpandoMap;
+    typedef nsTHashtable<nsPtrHashKey<JSObject> > DOMExpandoMap;
+
     CompartmentPrivate(bool wantXrays)
         : wantXrays(wantXrays)
     {
         MOZ_COUNT_CTOR(xpc::CompartmentPrivate);
     }
 
     ~CompartmentPrivate();
 
     bool wantXrays;
     nsAutoPtr<JSObject2JSObjectMap> waiverWrapperMap;
     // NB: we don't want this map to hold a strong reference to the wrapper.
-    nsAutoPtr<nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *> > expandoMap;
-    nsAutoPtr<nsTHashtable<nsPtrHashKey<JSObject> > > domExpandoMap;
+    nsAutoPtr<ExpandoMap> expandoMap;
+    nsAutoPtr<DOMExpandoMap> domExpandoMap;
     nsCString location;
 
     bool RegisterExpandoObject(XPCWrappedNative *wn, JSObject *expando) {
         if (!expandoMap) {
-            expandoMap = new nsDataHashtable<nsPtrHashKey<XPCWrappedNative>, JSObject *>();
-            if (!expandoMap->Init(8)) {
-                expandoMap = nsnull;
-                return false;
-            }
+            expandoMap = new ExpandoMap();
+            expandoMap->Init(8);
         }
         wn->SetHasExpandoObject();
-        return expandoMap->Put(wn, expando);
+        return expandoMap->Put(wn, expando, mozilla::fallible_t());
     }
 
     /**
      * This lookup does not change the color of the JSObject meaning that the
      * object returned is not guaranteed to be kept alive past the next CC.
      *
      * This should only be called if you are certain that the return value won't
      * be passed into a JS API function and that it won't be stored without
@@ -4425,23 +4425,20 @@ struct CompartmentPrivate
      */
     JSObject *LookupExpandoObject(XPCWrappedNative *wn) {
         JSObject *obj = LookupExpandoObjectPreserveColor(wn);
         return xpc_UnmarkGrayObject(obj);
     }
 
     bool RegisterDOMExpandoObject(JSObject *expando) {
         if (!domExpandoMap) {
-            domExpandoMap = new nsTHashtable<nsPtrHashKey<JSObject> >();
-            if (!domExpandoMap->Init(8)) {
-                domExpandoMap = nsnull;
-                return false;
-            }
+            domExpandoMap = new DOMExpandoMap();
+            domExpandoMap->Init(8);
         }
-        return domExpandoMap->PutEntry(expando);
+        return domExpandoMap->PutEntry(expando, mozilla::fallible_t());
     }
     void RemoveDOMExpandoObject(JSObject *expando) {
         if (domExpandoMap)
             domExpandoMap->RemoveEntry(expando);
     }
 };
 
 }
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -71,18 +71,18 @@ public:
                     "Shouldn't have both restyle flags set");
     NS_PRECONDITION((mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS) != 0,
                     "Must have root flag");
     NS_PRECONDITION((mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS) !=
                     (ELEMENT_ALL_RESTYLE_FLAGS & ~ELEMENT_PENDING_RESTYLE_FLAGS),
                     "Shouldn't have both root flags");
   }
 
-  bool Init() {
-    return mPendingRestyles.Init();
+  void Init() {
+    mPendingRestyles.Init();
   }
 
   PRUint32 Count() const {
     return mPendingRestyles.Count();
   }
 
   /**
    * Add a restyle for the given element to the tracker.  Returns true
--- a/layout/base/StackArena.h
+++ b/layout/base/StackArena.h
@@ -3,18 +3,18 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Assertions.h"
 #include "nsAlgorithm.h"
 #include "nsDebug.h"
 
 namespace mozilla {
 
-class StackBlock;
-class StackMark;
+struct StackBlock;
+struct StackMark;
 class AutoStackArena;
  
 /**
  * Private helper class for AutoStackArena.
  */
 class StackArena {
 private:
   friend class AutoStackArena;
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1390,19 +1390,18 @@ nsCSSFrameConstructor::nsCSSFrameConstru
   , mHoverGeneration(0)
   , mRebuildAllExtraHint(nsChangeHint(0))
   , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
                      ELEMENT_IS_POTENTIAL_RESTYLE_ROOT, this)
   , mPendingAnimationRestyles(ELEMENT_HAS_PENDING_ANIMATION_RESTYLE |
                               ELEMENT_IS_POTENTIAL_ANIMATION_RESTYLE_ROOT, this)
 {
   // XXXbz this should be in Init() or something!
-  if (!mPendingRestyles.Init() || !mPendingAnimationRestyles.Init()) {
-    // now what?
-  }
+  mPendingRestyles.Init();
+  mPendingAnimationRestyles.Init();
 
 #ifdef DEBUG
   static bool gFirstTime = true;
   if (gFirstTime) {
     gFirstTime = false;
     char* flags = PR_GetEnv("GECKO_FRAMECTOR_DEBUG_FLAGS");
     if (flags) {
       bool error = false;
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -4141,24 +4141,26 @@ nsImageRenderer::GetContainer()
   NS_ENSURE_SUCCESS(rv, nsnull);
   return container.forget();
 }
 
 #define MAX_BLUR_RADIUS 300
 #define MAX_SPREAD_RADIUS 50
 
 static inline gfxIntSize
-ComputeBlurRadius(nscoord aBlurRadius, PRInt32 aAppUnitsPerDevPixel)
+ComputeBlurRadius(nscoord aBlurRadius, PRInt32 aAppUnitsPerDevPixel, gfxFloat scale = 1.0)
 {
   // http://dev.w3.org/csswg/css3-background/#box-shadow says that the
   // standard deviation of the blur should be half the given blur value.
-  gfxFloat blurStdDev =
-    NS_MIN(gfxFloat(aBlurRadius) / gfxFloat(aAppUnitsPerDevPixel),
-           gfxFloat(MAX_BLUR_RADIUS))
-    / 2.0;
+  gfxFloat blurStdDev = gfxFloat(aBlurRadius) / gfxFloat(aAppUnitsPerDevPixel);
+
+  blurStdDev *= scale;
+
+  blurStdDev = NS_MIN(blurStdDev,
+                      gfxFloat(MAX_BLUR_RADIUS)) / 2.0;
   return
     gfxAlphaBoxBlur::CalculateBlurRadius(gfxPoint(blurStdDev, blurStdDev));
 }
 
 // -----
 // nsContextBoxBlur
 // -----
 gfxContext*
@@ -4170,17 +4172,31 @@ nsContextBoxBlur::Init(const nsRect& aRe
                        const gfxRect* aSkipRect,
                        PRUint32 aFlags)
 {
   if (aRect.IsEmpty()) {
     mContext = nsnull;
     return nsnull;
   }
 
-  gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel);
+  gfxFloat scale = 1;
+
+  // Do blurs in device space when possible
+  // If the scale is not uniform we fall back to transforming on paint.
+  // Chrome/Skia always does the blurs in device space
+  // and will sometimes get incorrect results (e.g. rotated blurs)
+  gfxMatrix transform = aDestinationCtx->CurrentMatrix();
+  if (transform.HasNonAxisAlignedTransform() || transform.xx != transform.yy) {
+    transform = gfxMatrix();
+  } else {
+    scale = transform.xx;
+  }
+
+  // compute a large or smaller blur radius
+  gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel, scale);
   PRInt32 spreadRadius = NS_MIN(PRInt32(aSpreadRadius / aAppUnitsPerDevPixel),
                                 PRInt32(MAX_SPREAD_RADIUS));
   mDestinationCtx = aDestinationCtx;
 
   // If not blurring, draw directly onto the destination device
   if (blurRadius.width <= 0 && blurRadius.height <= 0 && spreadRadius <= 0 &&
       !(aFlags & FORCE_MASK)) {
     mContext = aDestinationCtx;
@@ -4189,28 +4205,51 @@ nsContextBoxBlur::Init(const nsRect& aRe
 
   // Convert from app units to device pixels
   gfxRect rect = nsLayoutUtils::RectToGfxRect(aRect, aAppUnitsPerDevPixel);
 
   gfxRect dirtyRect =
     nsLayoutUtils::RectToGfxRect(aDirtyRect, aAppUnitsPerDevPixel);
   dirtyRect.RoundOut();
 
+  rect = transform.TransformBounds(rect);
+
+  mPreTransformed = !transform.IsIdentity();
+
   // Create the temporary surface for blurring
-  mContext = blur.Init(rect, gfxIntSize(spreadRadius, spreadRadius),
-                       blurRadius, &dirtyRect, aSkipRect);
+  dirtyRect = transform.TransformBounds(dirtyRect);
+  if (aSkipRect) {
+    gfxRect skipRect = transform.TransformBounds(*aSkipRect);
+    mContext = blur.Init(rect, gfxIntSize(spreadRadius, spreadRadius),
+                         blurRadius, &dirtyRect, &skipRect);
+  } else {
+    mContext = blur.Init(rect, gfxIntSize(spreadRadius, spreadRadius),
+                         blurRadius, &dirtyRect, NULL);
+  }
+
+  if (mContext) {
+    // we don't need to blur if skipRect is equal to rect
+    // and mContext will be NULL
+    mContext->SetMatrix(transform);
+  }
   return mContext;
 }
 
 void
 nsContextBoxBlur::DoPaint()
 {
   if (mContext == mDestinationCtx)
     return;
 
+  gfxContextMatrixAutoSaveRestore saveMatrix(mDestinationCtx);
+
+  if (mPreTransformed) {
+    mDestinationCtx->IdentityMatrix();
+  }
+
   blur.Paint(mDestinationCtx);
 }
 
 gfxContext*
 nsContextBoxBlur::GetContext()
 {
   return mContext;
 }
--- a/layout/base/nsCSSRendering.h
+++ b/layout/base/nsCSSRendering.h
@@ -610,12 +610,16 @@ public:
    */
   static nsMargin GetBlurRadiusMargin(nscoord aBlurRadius,
                                       PRInt32 aAppUnitsPerDevPixel);
 
 protected:
   gfxAlphaBoxBlur blur;
   nsRefPtr<gfxContext> mContext;
   gfxContext* mDestinationCtx;
-  
+
+  /* This is true if the blur already has it's content transformed
+   * by mDestinationCtx's transform */
+  bool mPreTransformed;
+
 };
 
 #endif /* nsCSSRendering_h___ */
--- a/layout/base/nsCounterManager.cpp
+++ b/layout/base/nsCounterManager.cpp
@@ -270,20 +270,17 @@ nsCounterManager::AddResetOrIncrement(ns
 nsCounterList*
 nsCounterManager::CounterListFor(const nsSubstring& aCounterName)
 {
     // XXX Why doesn't nsTHashtable provide an API that allows us to use
     // get/put in one hashtable lookup?
     nsCounterList *counterList;
     if (!mNames.Get(aCounterName, &counterList)) {
         counterList = new nsCounterList();
-        if (!mNames.Put(aCounterName, counterList)) {
-            delete counterList;
-            return nsnull;
-        }
+        mNames.Put(aCounterName, counterList);
     }
     return counterList;
 }
 
 static PLDHashOperator
 RecalcDirtyLists(const nsAString& aKey, nsCounterList* aList, void* aClosure)
 {
     if (aList->IsDirty())
--- a/layout/base/nsLayoutHistoryState.cpp
+++ b/layout/base/nsLayoutHistoryState.cpp
@@ -91,23 +91,25 @@ NS_NewLayoutHistoryState(nsILayoutHistor
 NS_IMPL_ISUPPORTS2(nsLayoutHistoryState,
                    nsILayoutHistoryState,
                    nsISupportsWeakReference)
 
 nsresult
 nsLayoutHistoryState::Init()
 {
   mScrollPositionOnly = false;
-  return mStates.Init() ? NS_OK : NS_ERROR_FAILURE;
+  mStates.Init();
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLayoutHistoryState::AddState(const nsCString& aStateKey, nsPresState* aState)
 {
-  return mStates.Put(aStateKey, aState) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+  mStates.Put(aStateKey, aState);
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsLayoutHistoryState::GetState(const nsCString& aKey, nsPresState** aState)
 {
   bool entryExists = mStates.Get(aKey, aState);
 
   if (entryExists && mScrollPositionOnly) {
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -138,21 +138,17 @@ typedef FrameMetrics::ViewID ViewID;
 
 static ViewID sScrollIdCounter = FrameMetrics::START_SCROLL_ID;
 
 typedef nsDataHashtable<nsUint64HashKey, nsIContent*> ContentMap;
 static ContentMap* sContentMap = NULL;
 static ContentMap& GetContentMap() {
   if (!sContentMap) {
     sContentMap = new ContentMap();
-#ifdef DEBUG
-    nsresult rv =
-#endif
     sContentMap->Init();
-    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Could not initialize map.");
   }
   return *sContentMap;
 }
 
 
 bool
 nsLayoutUtils::Are3DTransformsEnabled()
 {
--- a/layout/base/nsPresArena.cpp
+++ b/layout/base/nsPresArena.cpp
@@ -284,34 +284,32 @@ namespace {
 
 class FreeList : public PLDHashEntryHdr
 {
 public:
   typedef PRUint32 KeyType;
   nsTArray<void *> mEntries;
   size_t mEntrySize;
 
-protected:
   typedef const void* KeyTypePointer;
   KeyTypePointer mKey;
 
   FreeList(KeyTypePointer aKey) : mEntrySize(0), mKey(aKey) {}
   // Default copy constructor and destructor are ok.
 
   bool KeyEquals(KeyTypePointer const aKey) const
   { return mKey == aKey; }
 
   static KeyTypePointer KeyToPointer(KeyType aKey)
   { return NS_INT32_TO_PTR(aKey); }
 
   static PLDHashNumber HashKey(KeyTypePointer aKey)
   { return NS_PTR_TO_INT32(aKey); }
 
   enum { ALLOW_MEMMOVE = false };
-  friend class nsTHashtable<FreeList>;
 };
 
 }
 
 struct nsPresArena::State {
   nsTHashtable<FreeList> mFreeLists;
   PLArenaPool mPool;
 
@@ -332,19 +330,16 @@ struct nsPresArena::State {
     NS_ABORT_IF_FALSE(aSize > 0, "PresArena cannot allocate zero bytes");
 
     // We only hand out aligned sizes
     aSize = PL_ARENA_ALIGN(&mPool, aSize);
 
     // If there is no free-list entry for this type already, we have
     // to create one now, to record its size.
     FreeList* list = mFreeLists.PutEntry(aCode);
-    if (!list) {
-      return nsnull;
-    }
 
     nsTArray<void*>::index_type len = list->mEntries.Length();
     if (list->mEntrySize == 0) {
       NS_ABORT_IF_FALSE(len == 0, "list with entries but no recorded size");
       list->mEntrySize = aSize;
     } else {
       NS_ABORT_IF_FALSE(list->mEntrySize == aSize,
                         "different sizes for same object type code");
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -949,19 +949,19 @@ nsPresContext::Init(nsDeviceContext* aDe
 
   mDeviceContext = aDeviceContext;
   NS_ADDREF(mDeviceContext);
 
   if (mDeviceContext->SetPixelScale(mFullZoom))
     mDeviceContext->FlushFontCache();
   mCurAppUnitsPerDevPixel = AppUnitsPerDevPixel();
 
-  for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
-    if (!mImageLoaders[i].Init())
-      return NS_ERROR_OUT_OF_MEMORY;
+  for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i) {
+    mImageLoaders[i].Init();
+  }
 
   mEventManager = new nsEventStateManager();
   NS_ADDREF(mEventManager);
 
   mTransitionManager = new nsTransitionManager(this);
 
   mAnimationManager = new nsAnimationManager(this);
 
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -762,19 +762,17 @@ PresShell::Init(nsIDocument* aDocument,
       (nsnull == aViewManager)) {
     return NS_ERROR_NULL_POINTER;
   }
   if (mDocument) {
     NS_WARNING("PresShell double init'ed");
     return NS_ERROR_ALREADY_INITIALIZED;
   }
 
-  if (!mFramesToDirty.Init()) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
+  mFramesToDirty.Init();
 
   mDocument = aDocument;
   NS_ADDREF(mDocument);
   mViewManager = aViewManager;
 
   // Create our frame constructor.
   mFrameConstructor = new nsCSSFrameConstructor(mDocument, this);
 
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -341,36 +341,16 @@ GetMaxOptionHeight(nsIFrame* aContainer)
       optionHeight = option->GetSize().height;
     }
     if (result < optionHeight)
       result = optionHeight;
   }
   return result;
 }
 
-static PRUint32
-GetNumberOfOptionsRecursive(nsIContent* aContent)
-{
-  if (!aContent) {
-    return 0;
-  }
-
-  PRUint32 optionCount = 0;
-  for (nsIContent* cur = aContent->GetFirstChild();
-       cur;
-       cur = cur->GetNextSibling()) {
-    if (cur->IsHTML(nsGkAtoms::option)) {
-      ++optionCount;
-    } else if (cur->IsHTML(nsGkAtoms::optgroup)) {
-      optionCount += GetNumberOfOptionsRecursive(cur);
-    }
-  }
-  return optionCount;
-}
-
 //-----------------------------------------------------------------
 // Main Reflow for ListBox/Dropdown
 //-----------------------------------------------------------------
 
 nscoord
 nsListControlFrame::CalcHeightOfARow()
 {
   // Calculate the height of a single row in the listbox or dropdown list by
--- a/layout/generic/TextOverflow.cpp
+++ b/layout/generic/TextOverflow.cpp
@@ -582,19 +582,17 @@ TextOverflow::ProcessLine(const nsDispla
                mRight.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP,
                "TextOverflow with 'clip' for both sides");
   mLeft.Reset();
   mLeft.mActive = mLeft.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP;
   mRight.Reset();
   mRight.mActive = mRight.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP;
   
   FrameHashtable framesToHide;
-  if (!framesToHide.Init(100)) {
-    return;
-  }
+  framesToHide.Init(100);
   AlignmentEdges alignmentEdges;
   ExamineLineFrames(aLine, &framesToHide, &alignmentEdges);
   bool needLeft = mLeft.IsNeeded();
   bool needRight = mRight.IsNeeded();
   if (!needLeft && !needRight) {
     return;
   }
   NS_ASSERTION(mLeft.mStyle->mType != NS_STYLE_TEXT_OVERFLOW_CLIP ||
--- a/layout/inspector/src/nsFontFaceList.cpp
+++ b/layout/inspector/src/nsFontFaceList.cpp
@@ -123,16 +123,14 @@ nsFontFaceList::AddFontsFromTextRun(gfxT
       nsRefPtr<nsCSSFontFaceRule> rule;
       nsUserFontSet* fontSet =
         static_cast<nsUserFontSet*>(aFrame->PresContext()->GetUserFontSet());
       if (fontSet) {
         rule = fontSet->FindRuleForEntry(fe);
       }
       nsCOMPtr<nsFontFace> ff =
         new nsFontFace(fe, iter.GetGlyphRun()->mMatchType, rule);
-      if (!mFontFaces.Put(fe, ff)) {
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
+      mFontFaces.Put(fe, ff);
     }
   }
 
   return NS_OK;
 }
--- a/layout/mathml/nsMathMLmactionFrame.cpp
+++ b/layout/mathml/nsMathMLmactionFrame.cpp
@@ -66,16 +66,35 @@
 //
 
 #define NS_MATHML_ACTION_TYPE_NONE         0
 #define NS_MATHML_ACTION_TYPE_TOGGLE       1
 #define NS_MATHML_ACTION_TYPE_STATUSLINE   2
 #define NS_MATHML_ACTION_TYPE_TOOLTIP      3 // unsupported
 
 
+// helper function to parse actiontype attribute
+static PRInt32
+GetActionType(nsIContent* aContent)
+{
+  nsAutoString value;
+
+  if (aContent)
+    aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::actiontype_, value);
+
+  if (value.EqualsLiteral("toggle"))
+    return NS_MATHML_ACTION_TYPE_TOGGLE;
+  if (value.EqualsLiteral("statusline"))
+    return NS_MATHML_ACTION_TYPE_STATUSLINE;
+  if (value.EqualsLiteral("tooltip"))
+    return NS_MATHML_ACTION_TYPE_TOOLTIP;
+
+  return NS_MATHML_ACTION_TYPE_NONE;
+}
+
 nsIFrame*
 NS_NewMathMLmactionFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsMathMLmactionFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsMathMLmactionFrame)
 
@@ -93,44 +112,22 @@ nsMathMLmactionFrame::~nsMathMLmactionFr
   }
 }
 
 NS_IMETHODIMP
 nsMathMLmactionFrame::Init(nsIContent*      aContent,
                            nsIFrame*        aParent,
                            nsIFrame*        aPrevInFlow)
 {
-  nsAutoString value, prefix;
-
   // Init our local attributes
 
   mChildCount = -1; // these will be updated in GetSelectedFrame()
   mSelection = 0;
   mSelectedFrame = nsnull;
-  nsRefPtr<nsStyleContext> newStyleContext;
-
-  mActionType = NS_MATHML_ACTION_TYPE_NONE;
-  aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::actiontype_, value);
-  if (!value.IsEmpty()) {
-    if (value.EqualsLiteral("toggle"))
-      mActionType = NS_MATHML_ACTION_TYPE_TOGGLE;
-
-    // XXX use goto to jump out of these if?
-
-    if (NS_MATHML_ACTION_TYPE_NONE == mActionType) {
-      // expected tooltip prefix (8ch)...
-      if (8 < value.Length() && 0 == value.Find("tooltip#"))
-        mActionType = NS_MATHML_ACTION_TYPE_TOOLTIP;
-    }
-
-    if (NS_MATHML_ACTION_TYPE_NONE == mActionType) {
-      if (value.EqualsLiteral("statusline"))
-        mActionType = NS_MATHML_ACTION_TYPE_STATUSLINE;
-    }
-  }
+  mActionType = GetActionType(aContent);
 
   // Let the base class do the rest
   return nsMathMLContainerFrame::Init(aContent, aParent, aPrevInFlow);
 }
 
 NS_IMETHODIMP
 nsMathMLmactionFrame::TransmitAutomaticData() {
   // The REC defines the following element to be space-like:
@@ -242,16 +239,55 @@ nsMathMLmactionFrame::SetInitialChildLis
     mContent->AddSystemEventListener(NS_LITERAL_STRING("mouseover"), mListener,
                                      false, false);
     mContent->AddSystemEventListener(NS_LITERAL_STRING("mouseout"), mListener,
                                      false, false);
   }
   return rv;
 }
 
+NS_IMETHODIMP
+nsMathMLmactionFrame::AttributeChanged(PRInt32  aNameSpaceID,
+                                       nsIAtom* aAttribute,
+                                       PRInt32  aModType)
+{
+  bool needsReflow = false;
+
+  if (aAttribute == nsGkAtoms::actiontype_) {
+    // updating mActionType ...
+    PRInt32 oldActionType = mActionType;
+    mActionType = GetActionType(mContent);
+
+    // We have to initiate a reflow only when changing actiontype
+    // from toggle or to toggle.
+    if (oldActionType == NS_MATHML_ACTION_TYPE_TOGGLE || 
+          mActionType == NS_MATHML_ACTION_TYPE_TOGGLE) {
+      needsReflow = true;
+    }
+  } else if (aAttribute == nsGkAtoms::selection_) {
+    // When the selection attribute is changed we have to initiate a reflow
+    // only when actiontype is toggle.
+    if (NS_MATHML_ACTION_TYPE_TOGGLE == mActionType) {
+      needsReflow = true;
+    }
+  } else {
+    // let the base class handle other attribute changes
+    return 
+      nsMathMLContainerFrame::AttributeChanged(aNameSpaceID, 
+                                               aAttribute, aModType);
+  }
+
+  if (needsReflow) {
+    PresContext()->PresShell()->
+      FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
+  }
+
+  return NS_OK;
+}
+
 //  Only paint the selected child...
 NS_IMETHODIMP
 nsMathMLmactionFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                        const nsRect&           aDirtyRect,
                                        const nsDisplayListSet& aLists)
 {
   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/layout/mathml/nsMathMLmactionFrame.h
+++ b/layout/mathml/nsMathMLmactionFrame.h
@@ -78,16 +78,21 @@ public:
         nsHTMLReflowMetrics& aDesiredSize);
 
   NS_IMETHOD
   Reflow(nsPresContext*          aPresContext,
          nsHTMLReflowMetrics&     aDesiredSize,
          const nsHTMLReflowState& aReflowState,
          nsReflowStatus&          aStatus);
 
+  NS_IMETHOD
+  AttributeChanged(PRInt32  aNameSpaceID,
+                   nsIAtom* aAttribute,
+                   PRInt32  aModType);
+
 private:
   void MouseClick();
   void MouseOver();
   void MouseOut();
 
   class MouseListener : public nsIDOMEventListener
   {
     NS_DECL_ISUPPORTS
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/maction-dynamic-1-ref.html
@@ -0,0 +1,57 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dynamic maction 1</title>
+</head>
+
+<body>
+
+<p>
+<math>
+  <mtext>__2__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__1__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__1__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mn>1</mn>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__2__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__3__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__3__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__3__</mtext>
+</math>
+</p>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/maction-dynamic-1.html
@@ -0,0 +1,106 @@
+<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
+<head>
+<title>dynamic maction 1</title>
+</head>
+
+<body>
+
+<p>
+<math>
+  <maction id="m1" actiontype="toggle">
+    <mtext>__1__</mtext>
+    <mtext>__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m2" actiontype="toggle" selection="2">
+    <mtext>__1__</mtext>
+    <mtext>__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m3" actiontype="toggle" selection="2">
+    <mtext>__1__</mtext>
+    <mtext>__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m4" actiontype="toggle">
+    <mn>1</mn>
+    <mn>2</mn>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m5" actiontype="toggle">
+    <mtext id="m51">__1__</mtext>
+    <mtext id="m52">__2__</mtext>
+    <mtext id="m53">__3__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m6" actiontype="toggle" selection="3">
+    <mtext>__1__</mtext>
+    <mtext>__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m7" actiontype="toggle">
+    <mtext id="m71">__1__</mtext>
+    <mtext id="m72">__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m8" actiontype="toggle">
+    <mtext id="m81">__1__</mtext>
+    <mtext id="m82">__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<script>
+function doTest() {
+  document.getElementById("m1").setAttribute("selection", "2");
+  document.getElementById("m2").removeAttribute("selection");
+  document.getElementById("m3").setAttribute("actiontype", "statusline");
+  document.getElementById("m4").setAttribute("actiontype", "statusline");
+
+  var child51 = document.getElementById("m51");
+  document.getElementById("m5").removeChild(child51);
+
+  var child53 = document.getElementById("m53");
+  document.getElementById("m6").appendChild(child53.cloneNode(true));
+
+  var child71 = document.getElementById("m71");
+  document.getElementById("m7").insertBefore(child53.cloneNode(true), child71);
+
+  var child81 = document.getElementById("m81");
+  document.getElementById("m8").replaceChild(child53.cloneNode(true), child81);
+
+  document.documentElement.removeAttribute('class');
+}
+window.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/maction-dynamic-2-ref.html
@@ -0,0 +1,51 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>dynamic maction 2</title>
+</head>
+
+<body>
+
+<p>
+<math>
+  <mtext>__1__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__1__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__2__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__2__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__1__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__3__</mtext>
+</math>
+</p>
+
+<p>
+<math>
+  <mtext>__3__</mtext>
+</math>
+</p>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/mathml/maction-dynamic-2.html
@@ -0,0 +1,95 @@
+<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
+<head>
+<title>dynamic maction 2</title>
+</head>
+
+<body>
+
+<p>
+<math>
+  <maction id="m1" actiontype="statusline">
+    <mtext>__1__</mtext>
+    <mtext>__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m2" actiontype="statusline" selection="2">
+    <mtext>__1__</mtext>
+    <mtext>__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m3" actiontype="statusline" selection="2">
+    <mtext>__1__</mtext>
+    <mtext>__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m4" actiontype="statusline">
+    <mtext id="m41">__1__</mtext>
+    <mtext id="m42">__2__</mtext>
+    <mtext id="m43">__3__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m5" actiontype="statusline">
+    <mtext>__1__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m6" actiontype="statusline">
+    <mtext id="m61">__1__</mtext>
+    <mtext id="m62">__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<p>
+<math>
+  <maction id="m7" actiontype="statusline">
+    <mtext id="m71">__1__</mtext>
+    <mtext id="m72">__2__</mtext>
+  </maction>
+</math>
+</p>
+
+<script>
+function doTest() {
+  document.getElementById("m1").setAttribute("selection", "2");
+  document.getElementById("m2").removeAttribute("selection");
+  document.getElementById("m3").setAttribute("actiontype", "toggle");
+
+  var child41 = document.getElementById("m41");
+  document.getElementById("m4").removeChild(child41);
+
+  var child43 = document.getElementById("m43");
+  document.getElementById("m5").appendChild(child43.cloneNode(true));
+
+  var child61 = document.getElementById("m61");
+  document.getElementById("m6").insertBefore(child43.cloneNode(true), child61);
+
+  var child71 = document.getElementById("m71");
+  document.getElementById("m7").replaceChild(child43.cloneNode(true), child71);
+
+  document.documentElement.removeAttribute('class');
+}
+window.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+
+</body>
+</html>
--- a/layout/reftests/mathml/reftest.list
+++ b/layout/reftests/mathml/reftest.list
@@ -94,8 +94,10 @@ fails == mstyle-5.xhtml mstyle-5-ref.xht
 == mfrac-linethickness-1.xhtml mfrac-linethickness-1-ref.xhtml
 == mathml-negativespace.html mathml-negativespace-ref.html
 != link-1.xhtml link-ref.xhtml
 == munderover-empty-scripts.html munderover-empty-scripts-ref.html
 == positive-namedspace.html positive-namedspace-ref.html
 == mtable-width.html mtable-width-ref.html
 == maction-selection.html maction-selection-ref.html
 == maction-dynamic-embellished-op.html maction-dynamic-embellished-op-ref.html
+== maction-dynamic-1.html maction-dynamic-1-ref.html
+== maction-dynamic-2.html maction-dynamic-2-ref.html
--- a/layout/reftests/text/reftest.list
+++ b/layout/reftests/text/reftest.list
@@ -104,27 +104,29 @@ HTTP(..) != synthetic-bold-metrics-01.ht
 == wordbreak-2.html wordbreak-2-ref.html
 == wordbreak-3.html wordbreak-3-ref.html
 == wordbreak-4a.html wordbreak-4a-ref.html
 == wordbreak-4b.html wordbreak-4b-ref.html
 == wordbreak-5.html wordbreak-5-ref.html
 == wordbreak-6.html wordbreak-6-ref.html
 HTTP(..) == wordbreak-7a.html wordbreak-7a-ref.html
 fails HTTP(..) == wordbreak-7b.html wordbreak-7b-ref.html # bug 479829
+== wordbreak-8.html wordbreak-8-ref.html
 == wordwrap-01.html wordwrap-01-ref.html
 HTTP(..) == wordwrap-02.html wordwrap-02-ref.html
 HTTP(..) == wordwrap-03.html wordwrap-03-ref.html
 == wordwrap-04.html wordwrap-04-ref.html
 == wordwrap-05.html wordwrap-05-ref.html
 == wordwrap-06.html wordwrap-06-ref.html
 == wordwrap-07.html wordwrap-07-ref.html
 != wordwrap-08.html wordwrap-01-ref.html
 == wordwrap-08.html wordwrap-08-ref.html
 != wordwrap-09.html wordwrap-01-ref.html
 == wordwrap-09.html wordwrap-09-ref.html
+== wordwrap-10.html wordwrap-10-ref.html # bug 752459
 == word-spacing-01.html word-spacing-01-ref.html
 # the following will fail when rendering with Core Text (see bug 389074) due to what appears to be
 # an Apple bug: the presence of ZWNJ disturbs the positioning of an adjacent glyph. rdar://6427865
 random-if(cocoaWidget) HTTP(..) == zwnj-01.xhtml zwnj-01-ref.xhtml
 HTTP(..) == zwnj-02.xhtml zwnj-02-ref.xhtml # HTTP(..) for ../filters.svg
 != zwnj-01.html zwnj-01-notref.html
 == cgj-01.html cgj-01-ref.html
 == 444656.html 444656-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordbreak-8-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <style type="text/css">
+    .lc { text-transform: lowercase; }
+    .uc { text-transform: uppercase; }
+  </style>
+  <title>Test - word-break:break-all with text-transform and clusters</title>
+  </head>
+  <body>
+    <div class="lc">f<br>o<br>x<br>f<br>o&#x0325;<br>x&#x0307;</div><br>
+    <div class="lc">fox<br>fo&#x0325;x&#x0307;</div><br>
+    <div class="uc">f<br>o<br>x<br>f<br>o&#x0325;<br>x&#x0307;</div><br>
+    <div class="uc">fox<br>fo&#x0325;x&#x0307;</div><br>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordbreak-8.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <style type="text/css">
+    .breakall { width: 0px; word-break: break-all; }
+    .keepall { width: 0px; word-break: keep-all;  }
+    .lc { text-transform: lowercase; }
+    .uc { text-transform: uppercase; }
+  </style>
+  <title>Test - word-break:break-all with text-transform and clusters</title>
+  </head>
+  <body>
+    <div class="breakall lc">fox fo&#x0325;x&#x0307;</div><br>
+    <div class="keepall lc">fox fo&#x0325;x&#x0307;</div><br>
+    <div class="breakall uc">fox fo&#x0325;x&#x0307;</div><br>
+    <div class="keepall uc">fox fo&#x0325;x&#x0307;</div><br>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-10-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Test - word-wrap: break-word should respect clusters</title>
+  </head>
+  <body>
+    <div>
+      a<br>b<br>c<br>
+      d&#x0325;<br>e&#x0315;<br>f&#x0323;<br>
+      &#x10400;<br>&#x10401;<br>&#x10402;
+    </div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/wordwrap-10.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Test - word-wrap: break-word should respect clusters</title>
+  </head>
+  <body>
+    <div style="width:0px; word-wrap:break-word">
+      abc
+      d&#x0325;e&#x0315;f&#x0323;
+      &#x10400;&#x10401;&#x10402;
+    </div>
+  </body>
+</html>
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1097,20 +1097,25 @@ Loader::CreateSheet(nsIURI* aURI,
                     const nsAString& aTitle,                       
                     StyleSheetState& aSheetState,
                     bool *aIsAlternate,
                     nsCSSStyleSheet** aSheet)
 {
   LOG(("css::Loader::CreateSheet"));
   NS_PRECONDITION(aSheet, "Null out param!");
 
-  NS_ENSURE_TRUE((mCompleteSheets.IsInitialized() || mCompleteSheets.Init()) &&
-                   (mLoadingDatas.IsInitialized() || mLoadingDatas.Init()) &&
-                   (mPendingDatas.IsInitialized() || mPendingDatas.Init()),
-                 NS_ERROR_OUT_OF_MEMORY);
+  if (!mCompleteSheets.IsInitialized()) {
+    mCompleteSheets.Init();
+  }
+  if (!mLoadingDatas.IsInitialized()) {
+    mLoadingDatas.Init();
+  }
+  if (!mPendingDatas.IsInitialized()) {
+    mPendingDatas.Init();
+  }
 
   nsresult rv = NS_OK;
   *aSheet = nsnull;
   aSheetState = eSheetStateUnknown;
 
   // Check the alternate state before doing anything else, because it
   // can mess with our hashtables.
   *aIsAlternate = IsAlternate(aTitle, aHasAlternateRel);
@@ -1592,24 +1597,17 @@ Loader::LoadSheet(SheetLoadData* aLoadDa
 #endif
 
   if (NS_FAILED(rv)) {
     LOG_ERROR(("  Failed to create stream loader"));
     SheetComplete(aLoadData, rv);
     return rv;
   }
 
-  if (!mLoadingDatas.Put(&key, aLoadData)) {
-    LOG_ERROR(("  Failed to put data in loading table"));
-    aLoadData->mIsCancelled = true;
-    channel->Cancel(NS_ERROR_OUT_OF_MEMORY);
-    SheetComplete(aLoadData, NS_ERROR_OUT_OF_MEMORY);
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
+  mLoadingDatas.Put(&key, aLoadData);
   aLoadData->mIsLoading = true;
 
   return NS_OK;
 }
 
 /**
  * ParseSheet handles parsing the data stream.  The main idea here is
  * to push the current load data onto the parse stack before letting
@@ -1946,19 +1944,17 @@ Loader::LoadStyleLink(nsIContent* aEleme
                                           aObserver, principal);
   NS_ADDREF(data);
 
   // If we have to parse and it's an alternate non-inline, defer it
   if (aURL && state == eSheetNeedsParser && mLoadingDatas.Count() != 0 &&
       *aIsAlternate) {
     LOG(("  Deferring alternate sheet load"));
     URIAndPrincipalHashKey key(data->mURI, data->mLoaderPrincipal);
-    if (!mPendingDatas.Put(&key, data)) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
+    mPendingDatas.Put(&key, data);
 
     data->mMustNotify = true;
     return NS_OK;
   }
 
   // Load completion will free the data
   rv = LoadSheet(data, state);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1314,34 +1314,34 @@ nsComputedDOMStyle::DoGetFontVariant()
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(GetStyleFont()->mFont.variant,
                                    nsCSSProps::kFontVariantKTable));
   return val;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetMozFontFeatureSettings()
+nsComputedDOMStyle::DoGetFontFeatureSettings()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
 
   const nsStyleFont* font = GetStyleFont();
   if (font->mFont.fontFeatureSettings.IsEmpty()) {
     val->SetIdent(eCSSKeyword_normal);
   } else {
     nsAutoString result;
     nsStyleUtil::AppendFontFeatureSettings(font->mFont.fontFeatureSettings,
                                            result);
     val->SetString(result);
   }
   return val;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetMozFontLanguageOverride()
+nsComputedDOMStyle::DoGetFontLanguageOverride()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
 
   const nsStyleFont* font = GetStyleFont();
   if (font->mFont.languageOverride.IsEmpty()) {
     val->SetIdent(eCSSKeyword_normal);
   } else {
     nsString str;
@@ -1763,17 +1763,17 @@ nsComputedDOMStyle::DoGetBackgroundRepea
                                           nsCSSProps::kBackgroundRepeatKTable));
     }
   }
 
   return valueList;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetMozBackgroundSize()
+nsComputedDOMStyle::DoGetBackgroundSize()
 {
   const nsStyleBackground* bg = GetStyleBackground();
 
   nsDOMCSSValueList *valueList = GetROCSSValueList(true);
 
   for (PRUint32 i = 0, i_end = bg->mSizeCount; i < i_end; ++i) {
     const nsStyleBackground::Size &size = bg->mLayers[i].mSize;
 
@@ -1844,23 +1844,16 @@ nsComputedDOMStyle::DoGetMozBackgroundSi
       }
     }
   }
 
   return valueList;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetPadding()
-{
-  // return null per spec.
-  return nsnull;
-}
-
-nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetPaddingTop()
 {
   return GetPaddingWidthFor(NS_SIDE_TOP);
 }
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetPaddingBottom()
 {
@@ -1933,23 +1926,16 @@ nsComputedDOMStyle::DoGetTableLayout()
   nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(GetStyleTable()->mLayoutStrategy,
                                    nsCSSProps::kTableLayoutKTable));
   return val;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetBorderStyle()
-{
-  // return null per spec.
-  return nsnull;
-}
-
-nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetBorderTopStyle()
 {
   return GetBorderStyleFor(NS_SIDE_TOP);
 }
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetBorderBottomStyle()
 {
@@ -2017,23 +2003,16 @@ nsComputedDOMStyle::DoGetBorderTopLeftRa
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetBorderTopRightRadius()
 {
   return GetEllipseRadii(GetStyleBorder()->mBorderRadius,
                          NS_CORNER_TOP_RIGHT, true);
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetBorderWidth()
-{
-  // return null per spec.
-  return nsnull;
-}
-
-nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetBorderTopWidth()
 {
   return GetBorderWidthFor(NS_SIDE_TOP);
 }
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetBorderBottomWidth()
 {
@@ -2072,23 +2051,16 @@ nsComputedDOMStyle::DoGetBorderLeftColor
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetBorderRightColor()
 {
   return GetBorderColorFor(NS_SIDE_RIGHT);
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetMarginWidth()
-{
-  // return null per spec.
-  return nsnull;
-}
-
-nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetMarginTopWidth()
 {
   return GetMarginWidthFor(NS_SIDE_TOP);
 }
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetMarginBottomWidth()
 {
@@ -2121,23 +2093,16 @@ nsComputedDOMStyle::DoGetOrient()
   nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(GetStyleDisplay()->mOrient,
                                    nsCSSProps::kOrientKTable));
   return val;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetOutline()
-{
-  // return null per spec.
-  return nsnull;
-}
-
-nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetOutlineWidth()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
 
   const nsStyleOutline* outline = GetStyleOutline();
 
   nscoord width;
   if (outline->GetOutlineStyle() == NS_STYLE_BORDER_STYLE_NONE) {
@@ -2535,34 +2500,34 @@ nsComputedDOMStyle::DoGetTextDecoration(
     }
     val->SetString(str);
   }
 
   return val;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetMozTextDecorationColor()
+nsComputedDOMStyle::DoGetTextDecorationColor()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
 
   nscolor color;
   bool isForeground;
   GetStyleTextReset()->GetDecorationColor(color, isForeground);
   if (isForeground) {
     color = GetStyleColor()->mColor;
   }
 
   SetToRGBAColor(val, color);
 
   return val;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetMozTextDecorationLine()
+nsComputedDOMStyle::DoGetTextDecorationLine()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
 
   PRInt32 intValue = GetStyleTextReset()->mTextDecorationLine;
 
   if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
     val->SetIdent(eCSSKeyword_none);
   } else {
@@ -2576,17 +2541,17 @@ nsComputedDOMStyle::DoGetMozTextDecorati
       NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, decorationLineString);
     val->SetString(decorationLineString);
   }
 
   return val;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetMozTextDecorationStyle()
+nsComputedDOMStyle::DoGetTextDecorationStyle()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
 
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(GetStyleTextReset()->GetDecorationStyle(),
                                    nsCSSProps::kTextDecorationStyleKTable));
 
   return val;
@@ -2651,17 +2616,17 @@ nsComputedDOMStyle::DoGetTextTransform()
   nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
   val->SetIdent(
     nsCSSProps::ValueToKeywordEnum(GetStyleText()->mTextTransform,
                                    nsCSSProps::kTextTransformKTable));
   return val;
 }
 
 nsIDOMCSSValue*
-nsComputedDOMStyle::DoGetMozTabSize()
+nsComputedDOMStyle::DoGetTabSize()
 {
   nsROCSSPrimitiveValue* val = GetROCSSPrimitiveValue();
   val->SetNumber(GetStyleText()->mTabSize);
   return val;
 }
 
 nsIDOMCSSValue*
 nsComputedDOMStyle::DoGetLetterSpacing()
@@ -4560,17 +4525,17 @@ nsComputedDOMStyle::GetQueryableProperty
     //// COMPUTED_STYLE_MAP_ENTRY(background,               Background),
     COMPUTED_STYLE_MAP_ENTRY(background_attachment,         BackgroundAttachment),
     COMPUTED_STYLE_MAP_ENTRY(background_clip,               BackgroundClip),
     COMPUTED_STYLE_MAP_ENTRY(background_color,              BackgroundColor),
     COMPUTED_STYLE_MAP_ENTRY(background_image,              BackgroundImage),
     COMPUTED_STYLE_MAP_ENTRY(background_origin,             BackgroundOrigin),
     COMPUTED_STYLE_MAP_ENTRY(background_position,           BackgroundPosition),
     COMPUTED_STYLE_MAP_ENTRY(background_repeat,             BackgroundRepeat),
-    COMPUTED_STYLE_MAP_ENTRY(background_size,               MozBackgroundSize),
+    COMPUTED_STYLE_MAP_ENTRY(background_size,               BackgroundSize),
     //// COMPUTED_STYLE_MAP_ENTRY(border,                   Border),
     //// COMPUTED_STYLE_MAP_ENTRY(border_bottom,            BorderBottom),
     COMPUTED_STYLE_MAP_ENTRY(border_bottom_color,           BorderBottomColor),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(border_bottom_left_radius, BorderBottomLeftRadius),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(border_bottom_right_radius,BorderBottomRightRadius),
     COMPUTED_STYLE_MAP_ENTRY(border_bottom_style,           BorderBottomStyle),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(border_bottom_width,    BorderBottomWidth),
     COMPUTED_STYLE_MAP_ENTRY(border_collapse,               BorderCollapse),
@@ -4715,35 +4680,35 @@ nsComputedDOMStyle::GetQueryableProperty
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_fill,              ColumnFill),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_gap,               ColumnGap),
     //// COMPUTED_STYLE_MAP_ENTRY(_moz_column_rule,         ColumnRule),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_rule_color,        ColumnRuleColor),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_rule_style,        ColumnRuleStyle),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_rule_width,        ColumnRuleWidth),
     COMPUTED_STYLE_MAP_ENTRY(_moz_column_width,             ColumnWidth),
     COMPUTED_STYLE_MAP_ENTRY(float_edge,                    FloatEdge),
-    COMPUTED_STYLE_MAP_ENTRY(font_feature_settings,         MozFontFeatureSettings),
-    COMPUTED_STYLE_MAP_ENTRY(font_language_override,        MozFontLanguageOverride),
+    COMPUTED_STYLE_MAP_ENTRY(font_feature_settings,         FontFeatureSettings),
+    COMPUTED_STYLE_MAP_ENTRY(font_language_override,        FontLanguageOverride),
     COMPUTED_STYLE_MAP_ENTRY(force_broken_image_icon,       ForceBrokenImageIcon),
     COMPUTED_STYLE_MAP_ENTRY(hyphens,                       Hyphens),
     COMPUTED_STYLE_MAP_ENTRY(image_region,                  ImageRegion),
     COMPUTED_STYLE_MAP_ENTRY(orient,                        Orient),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_bottomLeft, OutlineRadiusBottomLeft),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_bottomRight,OutlineRadiusBottomRight),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_topLeft,    OutlineRadiusTopLeft),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(_moz_outline_radius_topRight,   OutlineRadiusTopRight),
     COMPUTED_STYLE_MAP_ENTRY(perspective,                   Perspective),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(perspective_origin,     PerspectiveOrigin),
     COMPUTED_STYLE_MAP_ENTRY(stack_sizing,                  StackSizing),
-    COMPUTED_STYLE_MAP_ENTRY(_moz_tab_size,                 MozTabSize),
+    COMPUTED_STYLE_MAP_ENTRY(_moz_tab_size,                 TabSize),
     COMPUTED_STYLE_MAP_ENTRY(text_align_last,               TextAlignLast),
     COMPUTED_STYLE_MAP_ENTRY(text_blink,                    MozTextBlink),
-    COMPUTED_STYLE_MAP_ENTRY(text_decoration_color,         MozTextDecorationColor),
-    COMPUTED_STYLE_MAP_ENTRY(text_decoration_line,          MozTextDecorationLine),
-    COMPUTED_STYLE_MAP_ENTRY(text_decoration_style,         MozTextDecorationStyle),
+    COMPUTED_STYLE_MAP_ENTRY(text_decoration_color,         TextDecorationColor),
+    COMPUTED_STYLE_MAP_ENTRY(text_decoration_line,          TextDecorationLine),
+    COMPUTED_STYLE_MAP_ENTRY(text_decoration_style,         TextDecorationStyle),
     COMPUTED_STYLE_MAP_ENTRY(text_size_adjust,              TextSizeAdjust),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(transform,              Transform),
     COMPUTED_STYLE_MAP_ENTRY_LAYOUT(transform_origin,       TransformOrigin),
     COMPUTED_STYLE_MAP_ENTRY(transform_style,               TransformStyle),
     COMPUTED_STYLE_MAP_ENTRY(transition_delay,              TransitionDelay),
     COMPUTED_STYLE_MAP_ENTRY(transition_duration,           TransitionDuration),
     COMPUTED_STYLE_MAP_ENTRY(transition_property,           TransitionProperty),
     COMPUTED_STYLE_MAP_ENTRY(transition_timing_function,    TransitionTimingFunction),
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -196,54 +196,51 @@ private:
   nsIDOMCSSValue* DoGetTop();
   nsIDOMCSSValue* DoGetRight();
   nsIDOMCSSValue* DoGetBottom();
   nsIDOMCSSValue* DoGetStackSizing();
 
   /* Font properties */
   nsIDOMCSSValue* DoGetColor();
   nsIDOMCSSValue* DoGetFontFamily();
-  nsIDOMCSSValue* DoGetMozFontFeatureSettings();
-  nsIDOMCSSValue* DoGetMozFontLanguageOverride();
+  nsIDOMCSSValue* DoGetFontFeatureSettings();
+  nsIDOMCSSValue* DoGetFontLanguageOverride();
   nsIDOMCSSValue* DoGetFontSize();
   nsIDOMCSSValue* DoGetFontSizeAdjust();
   nsIDOMCSSValue* DoGetFontStretch();
   nsIDOMCSSValue* DoGetFontStyle();
   nsIDOMCSSValue* DoGetFontWeight();
   nsIDOMCSSValue* DoGetFontVariant();
 
   /* Background properties */
   nsIDOMCSSValue* DoGetBackgroundAttachment();
   nsIDOMCSSValue* DoGetBackgroundColor();
   nsIDOMCSSValue* DoGetBackgroundImage();
   nsIDOMCSSValue* DoGetBackgroundPosition();
   nsIDOMCSSValue* DoGetBackgroundRepeat();
   nsIDOMCSSValue* DoGetBackgroundClip();
   nsIDOMCSSValue* DoGetBackgroundInlinePolicy();
   nsIDOMCSSValue* DoGetBackgroundOrigin();
-  nsIDOMCSSValue* DoGetMozBackgroundSize();
+  nsIDOMCSSValue* DoGetBackgroundSize();
 
   /* Padding properties */
-  nsIDOMCSSValue* DoGetPadding();
   nsIDOMCSSValue* DoGetPaddingTop();
   nsIDOMCSSValue* DoGetPaddingBottom();
   nsIDOMCSSValue* DoGetPaddingLeft();
   nsIDOMCSSValue* DoGetPaddingRight();
 
   /* Table Properties */
   nsIDOMCSSValue* DoGetBorderCollapse();
   nsIDOMCSSValue* DoGetBorderSpacing();
   nsIDOMCSSValue* DoGetCaptionSide();
   nsIDOMCSSValue* DoGetEmptyCells();
   nsIDOMCSSValue* DoGetTableLayout();
   nsIDOMCSSValue* DoGetVerticalAlign();
 
   /* Border Properties */
-  nsIDOMCSSValue* DoGetBorderStyle();
-  nsIDOMCSSValue* DoGetBorderWidth();
   nsIDOMCSSValue* DoGetBorderTopStyle();
   nsIDOMCSSValue* DoGetBorderBottomStyle();
   nsIDOMCSSValue* DoGetBorderLeftStyle();
   nsIDOMCSSValue* DoGetBorderRightStyle();
   nsIDOMCSSValue* DoGetBorderTopWidth();
   nsIDOMCSSValue* DoGetBorderBottomWidth();
   nsIDOMCSSValue* DoGetBorderLeftWidth();
   nsIDOMCSSValue* DoGetBorderRightWidth();
@@ -270,24 +267,22 @@ private:
 
   /* Box Shadow */
   nsIDOMCSSValue* DoGetBoxShadow();
 
   /* Window Shadow */
   nsIDOMCSSValue* DoGetWindowShadow();
 
   /* Margin Properties */
-  nsIDOMCSSValue* DoGetMarginWidth();
   nsIDOMCSSValue* DoGetMarginTopWidth();
   nsIDOMCSSValue* DoGetMarginBottomWidth();
   nsIDOMCSSValue* DoGetMarginLeftWidth();
   nsIDOMCSSValue* DoGetMarginRightWidth();
 
   /* Outline Properties */
-  nsIDOMCSSValue* DoGetOutline();
   nsIDOMCSSValue* DoGetOutlineWidth();
   nsIDOMCSSValue* DoGetOutlineStyle();
   nsIDOMCSSValue* DoGetOutlineColor();
   nsIDOMCSSValue* DoGetOutlineOffset();
   nsIDOMCSSValue* DoGetOutlineRadiusBottomLeft();
   nsIDOMCSSValue* DoGetOutlineRadiusBottomRight();
   nsIDOMCSSValue* DoGetOutlineRadiusTopLeft();
   nsIDOMCSSValue* DoGetOutlineRadiusTopRight();
@@ -311,30 +306,30 @@ private:
   nsIDOMCSSValue* DoGetImageRegion();
 
   /* Text Properties */
   nsIDOMCSSValue* DoGetLineHeight();
   nsIDOMCSSValue* DoGetTextAlign();
   nsIDOMCSSValue* DoGetTextAlignLast();
   nsIDOMCSSValue* DoGetMozTextBlink();
   nsIDOMCSSValue* DoGetTextDecoration();
-  nsIDOMCSSValue* DoGetMozTextDecorationColor();
-  nsIDOMCSSValue* DoGetMozTextDecorationLine();
-  nsIDOMCSSValue* DoGetMozTextDecorationStyle();
+  nsIDOMCSSValue* DoGetTextDecorationColor();
+  nsIDOMCSSValue* DoGetTextDecorationLine();
+  nsIDOMCSSValue* DoGetTextDecorationStyle();
   nsIDOMCSSValue* DoGetTextIndent();
   nsIDOMCSSValue* DoGetTextOverflow();
   nsIDOMCSSValue* DoGetTextTransform();
   nsIDOMCSSValue* DoGetTextShadow();
   nsIDOMCSSValue* DoGetLetterSpacing();
   nsIDOMCSSValue* DoGetWordSpacing();
   nsIDOMCSSValue* DoGetWhiteSpace();
   nsIDOMCSSValue* DoGetWordBreak();
   nsIDOMCSSValue* DoGetWordWrap();
   nsIDOMCSSValue* DoGetHyphens();
-  nsIDOMCSSValue* DoGetMozTabSize();
+  nsIDOMCSSValue* DoGetTabSize();
   nsIDOMCSSValue* DoGetTextSizeAdjust();
 
   /* Visibility properties */
   nsIDOMCSSValue* DoGetOpacity();
   nsIDOMCSSValue* DoGetPointerEvents();
   nsIDOMCSSValue* DoGetVisibility();
 
   /* Direction properties */
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -495,20 +495,17 @@ void nsTableFrame::ResetRowIndices(const
 {
   // Iterate over the row groups and adjust the row indices of all rows
   // omit the rowgroups that will be inserted later
   RowGroupArray rowGroups;
   OrderRowGroups(rowGroups);
 
   PRInt32 rowIndex = 0;
   nsTHashtable<nsPtrHashKey<nsTableRowGroupFrame> > excludeRowGroups;
-  if (!excludeRowGroups.Init()) {
-    NS_ERROR("Failed to initialize excludeRowGroups hash.");
-    return;
-  }
+  excludeRowGroups.Init();
   nsFrameList::Enumerator excludeRowGroupsEnumerator(aRowGroupsToExclude);
   while (!excludeRowGroupsEnumerator.AtEnd()) {
     excludeRowGroups.PutEntry(static_cast<nsTableRowGroupFrame*>(excludeRowGroupsEnumerator.get()));
     excludeRowGroupsEnumerator.Next();
   }
 
   for (PRUint32 rgX = 0; rgX < rowGroups.Length(); rgX++) {
     nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
--- a/layout/xul/base/src/nsBoxObject.cpp
+++ b/layout/xul/base/src/nsBoxObject.cpp
@@ -338,25 +338,21 @@ nsBoxObject::GetPropertyAsSupports(const
 NS_IMETHODIMP
 nsBoxObject::SetPropertyAsSupports(const PRUnichar* aPropertyName, nsISupports* aValue)
 {
   NS_ENSURE_ARG(aPropertyName && *aPropertyName);
   
   if (!mPropertyTable) {  
     mPropertyTable = new nsInterfaceHashtable<nsStringHashKey,nsISupports>;  
     if (!mPropertyTable) return NS_ERROR_OUT_OF_MEMORY;
-    if (!mPropertyTable->Init(8)) {
-       mPropertyTable = nsnull;
-       return NS_ERROR_FAILURE;
-    }
+    mPropertyTable->Init(8);
   }
 
   nsDependentString propertyName(aPropertyName);
-  if (!mPropertyTable->Put(propertyName, aValue))
-    return NS_ERROR_OUT_OF_MEMORY;
+  mPropertyTable->Put(propertyName, aValue);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsBoxObject::GetProperty(const PRUnichar* aPropertyName, PRUnichar** aResult)
 {
   nsCOMPtr<nsISupports> data;
   nsresult rv = GetPropertyAsSupports(aPropertyName,getter_AddRefs(data));
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -204,19 +204,19 @@ nsTreeBodyFrame::Init(nsIContent*     aC
                       nsIFrame*       aPrevInFlow)
 {
   nsresult rv = nsLeafBoxFrame::Init(aContent, aParent, aPrevInFlow);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mIndentation = GetIndentation();
   mRowHeight = GetRowHeight();
 
-  NS_ENSURE_TRUE(mCreatedListeners.Init(), NS_ERROR_OUT_OF_MEMORY);
-
-  NS_ENSURE_TRUE(mImageCache.Init(16), NS_ERROR_OUT_OF_MEMORY);
+  mCreatedListeners.Init();
+
+  mImageCache.Init(16);
   EnsureBoxObject();
 
   return rv;
 }
 
 nsSize
 nsTreeBodyFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
 {
new file mode 100644
--- /dev/null
+++ b/mfbt/ThreadLocal.h
@@ -0,0 +1,128 @@
+/* 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/. */
+
+// Cross-platform lightweight thread local data wrappers
+
+#ifndef mozilla_TLS_h_
+#define mozilla_TLS_h_
+
+#if defined(XP_WIN)
+// This file will get included in any file that wants to add a profiler mark.
+// In order to not bring <windows.h> together we could include windef.h and
+// winbase.h which are sufficient to get the prototypes for the Tls* functions.
+// # include <windef.h>
+// # include <winbase.h>
+// Unfortunately, even including these headers causes us to add a bunch of ugly
+// stuff to our namespace e.g #define CreateEvent CreateEventW
+extern "C" {
+__declspec(dllimport) void * __stdcall TlsGetValue(unsigned long);
+__declspec(dllimport) int __stdcall TlsSetValue(unsigned long, void *);
+__declspec(dllimport) unsigned long __stdcall TlsAlloc();
+}
+#else
+#  include <pthread.h>
+#  include <signal.h>
+#endif
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+
+namespace mozilla {
+
+// sig_safe_t denotes an atomic type which can be read or stored in a single
+// instruction.  This means that data of this type is safe to be manipulated
+// from a signal handler, or other similar asynchronous execution contexts.
+#if defined(XP_WIN)
+typedef unsigned long sig_safe_t;
+#else
+typedef sig_atomic_t sig_safe_t;
+#endif
+
+/*
+ * Thread Local Storage helpers.
+ *
+ * Usage:
+ *
+ * Only static-storage-duration (e.g. global variables, or static class members)
+ * objects of this class should be instantiated. This class relies on
+ * zero-initialization, which is implicit for static-storage-duration objects.
+ * It doesn't have a custom default constructor, to avoid static initializers.
+ *
+ * API usage:
+ *
+ * // Create a TLS item
+ * mozilla::ThreadLocal<int> tlsKey;
+ * if (!tlsKey.init()) {
+ *   // deal with the error
+ * }
+ *
+ * // Set the TLS value
+ * tlsKey.set(123);
+ *
+ * // Get the TLS value
+ * int value = tlsKey.get();
+ */
+template <typename T>
+class ThreadLocal
+{
+#if defined(XP_WIN)
+    typedef unsigned long key_t;
+#else
+    typedef pthread_key_t key_t;
+#endif
+
+  public:
+    MOZ_WARN_UNUSED_RESULT inline bool init();
+
+    inline T* get() const;
+
+    inline bool set(const T* value);
+
+    bool initialized() const {
+      return inited;
+    }
+
+  private:
+    key_t key;
+    bool inited;
+};
+
+template <typename T>
+inline bool
+ThreadLocal<T>::init() {
+  MOZ_ASSERT(!initialized());
+#ifdef XP_WIN
+  key = TlsAlloc();
+  inited = key != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
+#else
+  inited = !pthread_key_create(&key, NULL);
+#endif
+  return inited;
+}
+
+template <typename T>
+inline T*
+ThreadLocal<T>::get() const {
+  MOZ_ASSERT(initialized());
+#ifdef XP_WIN
+  return reinterpret_cast<T*>(TlsGetValue(key));
+#else
+  return reinterpret_cast<T*>(pthread_getspecific(key));
+#endif
+}
+
+template <typename T>
+inline bool
+ThreadLocal<T>::set(const T* value) {
+  MOZ_ASSERT(initialized());
+#ifdef XP_WIN
+  return TlsSetValue(key, const_cast<T*>(value));
+#else
+  return !pthread_setspecific(key, value);
+#endif
+}
+
+} // namespace mozilla
+
+#endif // mozilla_TLS_h_
--- a/mfbt/exported_headers.mk
+++ b/mfbt/exported_headers.mk
@@ -51,11 +51,12 @@ EXPORTS_mozilla += \
   HashFunctions.h \
   Likely.h \
   LinkedList.h \
   MSStdInt.h \
   RangedPtr.h \
   RefPtr.h \
   Scoped.h \
   StandardInteger.h \
+  ThreadLocal.h \
   Types.h \
   Util.h \
   $(NULL)
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -755,12 +755,12 @@ pref("ui.scrolling.overscroll_snap_limit
 // The minimum amount of space that must be present for an axis to be considered scrollable,
 // in 1/1000ths of pixels.
 pref("ui.scrolling.min_scrollable_distance", -1);
 // A comma-separated list of float values in the range [0.0, 1.0) that are used as
 // interpolation frames for zoom animations.
 pref("ui.zooming.animation_frames", "");
 
 // Enable accessibility mode if platform accessibility is enabled.
-pref("accessibility.accessfu", 2);
+pref("accessibility.accessfu.activate", 2);
 
 // Mobile manages state by autodetection
 pref("network.manage-offline-status", true);
--- a/mobile/android/base/gfx/GLController.java
+++ b/mobile/android/base/gfx/GLController.java
@@ -130,32 +130,29 @@ public class GLController {
     public synchronized int getWidth() {
         return mWidth;
     }