Merge the last good pgo-green cset on mozilla-inbound to mozilla-central.
authorKyle Huey <khuey@kylehuey.com>
Wed, 28 Mar 2012 07:40:52 -0700
changeset 93815 c3fd0768d46abdb77d0e51d4bcb52d5adf4d0445
parent 93713 fb23c30e3d6091acb6babb5b871a44c602b3ca3a (current diff)
parent 93814 6e232128a8ca37d57bda0fb4e9f50d83781fdb65 (diff)
child 93816 183eed448b9d7b09a3ecd98db69066e9863eedbf
child 93852 76024a05af986dd30ee3869890873cd93678f64a
child 112356 ab92bf1f7deadc2e04077a80505b687f589cc68e
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone14.0a1
first release with
nightly linux32
c3fd0768d46a / 14.0a1 / 20120328115454 / files
nightly linux64
c3fd0768d46a / 14.0a1 / 20120328115511 / files
nightly mac
c3fd0768d46a / 14.0a1 / 20120328120915 / files
nightly win32
c3fd0768d46a / 14.0a1 / 20120328115525 / files
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
Merge the last good pgo-green cset on mozilla-inbound to mozilla-central.
browser/base/content/browser.js
browser/themes/winstripe/browser.css
dom/indexedDB/IDBKeyRange.cpp
dom/indexedDB/IDBKeyRange.h
editor/libeditor/text/tests/test_bug717147.html
js/src/jit-test/tests/basic/testInitDictionary.js
mobile/android/base/sync/repositories/android/PasswordColumns.java
mobile/android/locales/en-US/chrome/webapps.dtd
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -94,12 +94,14 @@ CXXFLAGS	+= $(MOZ_GTK2_CFLAGS)
 
 ifdef MOZ_ENABLE_DBUS
 CXXFLAGS += $(MOZ_DBUS_CFLAGS)
 endif
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
+  -I$(srcdir)/../xpcom \
   -I$(srcdir)/../xul \
   -I$(topsrcdir)/other-licenses/atk-1.0 \
   $(NULL)
--- a/accessible/src/atk/nsMaiInterfaceTable.cpp
+++ b/accessible/src/atk/nsMaiInterfaceTable.cpp
@@ -37,22 +37,24 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "InterfaceInitFuncs.h"
 
 #include "nsAccessibleWrap.h"
 #include "nsAccUtils.h"
 #include "nsIAccessibleTable.h"
+#include "TableAccessible.h"
 #include "nsMai.h"
 
 #include "nsArrayUtils.h"
 
+using namespace mozilla::a11y;
+
 extern "C" {
-
 static AtkObject*
 refAtCB(AtkTable *aTable, gint aRow, gint aColumn)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
     if (!accWrap)
         return nsnull;
 
     nsCOMPtr<nsIAccessibleTable> accTable;
@@ -203,33 +205,27 @@ getRowExtentAtCB(AtkTable *aTable,
     PRInt32 extent;
     nsresult rv = accTable->GetRowExtentAt(aRow, aColumn, &extent);
     NS_ENSURE_SUCCESS(rv, -1);
 
     return static_cast<gint>(extent);
 }
 
 static AtkObject*
-getCaptionCB(AtkTable *aTable)
+getCaptionCB(AtkTable* aTable)
 {
-    nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-    if (!accWrap)
-        return nsnull;
+  nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (!accWrap)
+    return nsnull;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, nsnull);
+  TableAccessible* table = accWrap->AsTable();
+  NS_ENSURE_TRUE(table, nsnull);
 
-    nsCOMPtr<nsIAccessible> caption;
-    nsresult rv = accTable->GetCaption(getter_AddRefs(caption));
-    if (NS_FAILED(rv) || !caption)
-        return nsnull;
-
-    return nsAccessibleWrap::GetAtkObject(caption);
+  nsAccessible* caption = table->Caption();
+  return caption ? nsAccessibleWrap::GetAtkObject(caption) : nsnull;
 }
 
 static const gchar*
 getColumnDescriptionCB(AtkTable *aTable, gint aColumn)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
     if (!accWrap)
         return nsnull;
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -39,19 +39,16 @@
 
 #include "AccEvent.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsApplicationAccessibleWrap.h"
 #include "nsDocAccessible.h"
 #include "nsIAccessibleText.h"
-#ifdef MOZ_XUL
-#include "nsXULTreeAccessible.h"
-#endif
 #include "nsAccEvent.h"
 #include "States.h"
 
 #include "nsIDOMDocument.h"
 #include "nsEventStateManager.h"
 #include "nsIServiceManager.h"
 #ifdef MOZ_XUL
 #include "nsIDOMXULMultSelectCntrlEl.h"
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -99,18 +99,19 @@ EXPORTS_mozilla/a11y = \
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
+  -I$(srcdir)/../generic \
+  -I$(srcdir)/../html \
   -I$(srcdir)/../xpcom \
-  -I$(srcdir)/../html \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/style \
   -I$(srcdir)/../../../layout/xul/base/src \
   -I$(srcdir)/../xforms \
   $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
--- a/accessible/src/base/nsARIAGridAccessible.cpp
+++ b/accessible/src/base/nsARIAGridAccessible.cpp
@@ -53,42 +53,39 @@ using namespace mozilla::a11y;
 ////////////////////////////////////////////////////////////////////////////////
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor
 
 nsARIAGridAccessible::
   nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  nsAccessibleWrap(aContent, aDoc)
+  nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible,
                              nsAccessible,
                              nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibleTable
+//nsAccessNode
 
-NS_IMETHODIMP
-nsARIAGridAccessible::GetCaption(nsIAccessible **aCaption)
+void
+nsARIAGridAccessible::Shutdown()
 {
-  NS_ENSURE_ARG_POINTER(aCaption);
-  *aCaption = nsnull;
+  mTable = nsnull;
+  nsAccessibleWrap::Shutdown();
+}
 
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  // XXX: should be pointed by aria-labelledby on grid?
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleTable
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetSummary(nsAString &aSummary)
 {
   aSummary.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
@@ -705,25 +702,16 @@ nsARIAGridAccessible::UnselectColumn(PRI
       nsresult rv = SetARIASelected(cell, false);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsARIAGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
-{
-  NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
-  *aIsProbablyForLayout = false;
-
-  return NS_OK;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Protected
 
 bool
 nsARIAGridAccessible::IsValidRow(PRInt32 aRow)
 {
   if (aRow < 0)
     return false;
--- a/accessible/src/base/nsARIAGridAccessible.h
+++ b/accessible/src/base/nsARIAGridAccessible.h
@@ -37,31 +37,41 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsARIAGridAccessible_h_
 #define nsARIAGridAccessible_h_
 
 #include "nsIAccessibleTable.h"
 
 #include "nsHyperTextAccessibleWrap.h"
+#include "TableAccessible.h"
+#include "xpcAccessibleTable.h"
 
 /**
  * Accessible for ARIA grid and treegrid.
  */
 class nsARIAGridAccessible : public nsAccessibleWrap,
-                             public nsIAccessibleTable
+                             public xpcAccessibleTable,
+                             public nsIAccessibleTable,
+                             public mozilla::a11y::TableAccessible
 {
 public:
   nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessibleTable
-  NS_DECL_NSIACCESSIBLETABLE
+  NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
+
+  // nsAccessible
+  virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
+
+  // nsAccessNode
+  virtual void Shutdown();
 
 protected:
   /**
    * Return true if the given row index is valid.
    */
   bool IsValidRow(PRInt32 aRow);
 
   /**
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -42,19 +42,17 @@
 #include "nsIAccessibleTypes.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsAccessibilityService.h"
 #include "nsARIAMap.h"
 #include "nsDocAccessible.h"
 #include "nsHyperTextAccessible.h"
-#include "nsHTMLTableAccessible.h"
 #include "nsTextAccessible.h"
-#include "nsXULTreeGridAccessible.h"
 
 #include "nsIDOMXULContainerElement.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsComponentManagerUtils.h"
 
 namespace dom = mozilla::dom;
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -61,16 +61,21 @@ class EmbeddedObjCollector;
 class KeyBinding;
 class nsAccessible;
 class nsHyperTextAccessible;
 class nsHTMLImageAccessible;
 class nsHTMLImageMapAccessible;
 class nsHTMLLIAccessible;
 struct nsRoleMapEntry;
 class Relation;
+namespace mozilla {
+namespace a11y {
+class TableAccessible;
+}
+}
 class nsTextAccessible;
 
 struct nsRect;
 class nsIContent;
 class nsIFrame;
 class nsIAtom;
 class nsIView;
 
@@ -466,16 +471,18 @@ public:
 
   inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
 
   inline bool IsMenuPopup() const { return mFlags & eMenuPopupAccessible; }
 
   inline bool IsRoot() const { return mFlags & eRootAccessible; }
   nsRootAccessible* AsRoot();
 
+  virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; }
+
   inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
   nsTextAccessible* AsTextLeaf();
 
   //////////////////////////////////////////////////////////////////////////////
   // ActionAccessible
 
   /**
    * Return the number of actions that can be performed on this accessible.
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -36,25 +36,23 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsRootAccessible_H_
 #define _nsRootAccessible_H_
 
 #include "nsCaretAccessible.h"
 #include "nsDocAccessibleWrap.h"
 
-#ifdef MOZ_XUL
-#include "nsXULTreeAccessible.h"
-#endif
 
 #include "nsHashtable.h"
 #include "nsCaretAccessible.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
 
+class nsXULTreeAccessible;
 class Relation;
 
 #define NS_ROOTACCESSIBLE_IMPL_CID                      \
 {  /* eaba2cf0-21b1-4e2b-b711-d3a89dcd5e1a */           \
   0xeaba2cf0,                                           \
   0x21b1,                                               \
   0x4e2b,                                               \
   { 0xb7, 0x11, 0xd3, 0xa8, 0x9d, 0xcd, 0x5e, 0x1a }    \
new file mode 100644
--- /dev/null
+++ b/accessible/src/generic/TableAccessible.h
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TABLE_ACCESSIBLE_H
+#define TABLE_ACCESSIBLE_H
+
+#include "nsString.h"
+#include "nsTArray.h"
+#include "prtypes.h"
+
+class nsAccessible;
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * Accessible table interface.
+ */
+class TableAccessible
+{
+public:
+
+  /**
+   * Return the caption accessible if any for this table.
+   */
+  virtual nsAccessible* Caption() { return nsnull; }
+
+  /**
+   * Get the summary for this table.
+   */
+  virtual void Summary(nsString& aSummary) { aSummary.Truncate(); }
+
+  /**
+   * Return the number of columns in the table.
+   */
+  virtual PRUint32 ColCount() { return 0; }
+
+  /**
+   * Return the number of rows in the table.
+   */
+  virtual PRUint32 RowCount() { return 0; }
+
+  /**
+   * Return the accessible for the cell at the given row and column indices.
+   */
+  virtual nsAccessible* CellAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return nsnull; }
+
+  /**
+   * Return the index of the cell at the given row and column.
+   */
+  virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; }
+
+  /**
+   * Return the column index of the cell with the given index.
+   */
+  virtual PRInt32 ColIndexAt(PRUint32 aCellIdx) { return -1; }
+
+  /**
+   * Return the row index of the cell with the given index.
+   */
+  virtual PRInt32 RowIndexAt(PRUint32 aCellIdx) { return -1; }
+
+  /**
+   * Get the row and column indices for the cell at the given index.
+   */
+  virtual void RowAndColIndicesAt(PRUint32 aCellIdx, PRInt32* aRowIdx,
+                                  PRInt32* aColIdx) {}
+
+  /**
+   * Return the number of columns occupied by the cell at the given row and
+   * column indices.
+   */
+  virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
+
+  /**
+   * Return the number of rows occupied by the cell at the given row and column
+   * indices.
+   */
+  virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
+
+  /**
+   * Get the description of the given column.
+   */
+  virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription)
+    { aDescription.Truncate(); }
+
+  /**
+   * Get the description for the given row.
+   */
+  virtual void RowDescription(PRUint32 aRowIdx, nsString& aDescription)
+    { aDescription.Truncate(); }
+
+  /**
+   * Return true if the given column is selected.
+   */
+  virtual bool IsColSelected(PRUint32 aColIdx) { return false; }
+
+  /**
+   * Return true if the given row is selected.
+   */
+  virtual bool IsRowSelected(PRUint32 aRowIdx) { return false; }
+
+  /**
+   * Return true if the given cell is selected.
+   */
+  virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx) { return false; }
+
+  /**
+   * Return the number of selected cells.
+   */
+  virtual PRUint32 SelectedCellCount() { return 0; }
+
+  /**
+   * Return the number of selected columns.
+   */
+  virtual PRUint32 SelectedColCount() { return 0; }
+
+  /**
+   * Return the number of selected rows.
+   */
+  virtual PRUint32 SelectedRowCount() { return 0; }
+
+  /**
+   * Get the set of selected cells.
+   */
+  virtual void SelectedCells(nsTArray<nsAccessible*>* aCells) {}
+
+  /**
+   * Get the set of selected column indices.
+   */
+  virtual void SelectedColIndices(nsTArray<PRUint32>* aCols) {}
+
+  /**
+   * Get the set of selected row indices.
+   */
+  virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows) {}
+
+  /**
+   * Select the given column unselecting any other selected columns.
+   */
+  virtual void SelectCol(PRUint32 aColIdx) {}
+
+  /**
+   * Select the given row unselecting all other previously selected rows.
+   */
+  virtual void SelectRow(PRUint32 aRowIdx) {}
+
+  /**
+   * Unselect the given column leaving other selected columns selected.
+   */
+  virtual void UnselectCol(PRUint32 aColIdx) {}
+
+  /**
+   * Unselect the given row leaving other selected rows selected.
+   */
+  virtual void UnselectRow(PRUint32 aRowIdx) {}
+
+  /**
+   * Return true if the table is probably for layout.
+   */
+  virtual bool IsProbablyLayoutTable() { return false; }
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/accessible/src/html/Makefile.in
+++ b/accessible/src/html/Makefile.in
@@ -68,11 +68,13 @@ EXPORTS = \
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
+  -I$(srcdir)/../xpcom \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -431,26 +431,36 @@ nsHTMLTableHeaderCellAccessible::NativeR
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLTableAccessible::
   nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  nsAccessibleWrap(aContent, aDoc)
+  nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsISupports implementation
 
 NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible,
                              nsHTMLTableAccessible, nsIAccessibleTable)
 
+////////////////////////////////////////////////////////////////////////////////
+//nsAccessNode
+
+void
+nsHTMLTableAccessible::Shutdown()
+{
+  mTable = nsnull;
+  nsAccessibleWrap::Shutdown();
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsAccessible implementation
 
 void
 nsHTMLTableAccessible::CacheChildren()
 {
   // Move caption accessible so that it's the first child. Check for the first
@@ -506,19 +516,17 @@ nsHTMLTableAccessible::GetNameInternal(n
 }
 
 nsresult
 nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  bool isProbablyForLayout;
-  IsProbablyForLayout(&isProbablyForLayout);
-  if (isProbablyForLayout) {
+  if (IsProbablyLayoutTable()) {
     nsAutoString oldValueUnused;
     aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
                                    NS_LITERAL_STRING("true"), oldValueUnused);
   }
   
   return NS_OK;
 }
 
@@ -533,23 +541,21 @@ nsHTMLTableAccessible::RelationByType(PR
     rel.AppendTarget(Caption());
 
   return rel;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsIAccessibleTable implementation
 
-NS_IMETHODIMP
-nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
+nsAccessible*
+nsHTMLTableAccessible::Caption()
 {
-  NS_ENSURE_ARG_POINTER(aCaption);
-
-  NS_IF_ADDREF(*aCaption = Caption());
-  return NS_OK;
+  nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
+  return child && child->Role() == roles::CAPTION ? child : nsnull;
 }
 
 NS_IMETHODIMP
 nsHTMLTableAccessible::GetSummary(nsAString &aSummary)
 {
   nsCOMPtr<nsIDOMHTMLTableElement> table(do_QueryInterface(mContent));
   NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
 
@@ -1302,18 +1308,17 @@ nsHTMLTableAccessible::Description(nsStr
         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary,
                           aDescription);
       }
     }
   }
 
 #ifdef SHOW_LAYOUT_HEURISTIC
   if (aDescription.IsEmpty()) {
-    bool isProbablyForLayout;
-    IsProbablyForLayout(&isProbablyForLayout);
+    bool isProbablyForLayout = IsProbablyLayoutTable();
     aDescription = mLayoutHeuristic;
   }
 #ifdef DEBUG_A11Y
   printf("\nTABLE: %s\n", NS_ConvertUTF16toUTF8(mLayoutHeuristic).get());
 #endif
 #endif
 }
 
@@ -1352,41 +1357,39 @@ nsHTMLTableAccessible::HasDescendant(con
   // performance problems only. Note, currently 'aAllowEmpty' flag is used for
   // caption element only. On another hand we create accessible object for
   // the first entry of caption element (see
   // nsHTMLTableAccessible::CacheChildren).
   nodeList->Item(1, getter_AddRefs(foundItem));
   return !!foundItem;
 }
 
-NS_IMETHODIMP
-nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
+bool
+nsHTMLTableAccessible::IsProbablyLayoutTable()
 {
   // Implement a heuristic to determine if table is most likely used for layout
   // XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells
   // at the beginning or end of a row/col, and especially when they occur at the edge of a table?
   // XXX expose this info via object attributes to AT-SPI
 
   // XXX For now debugging descriptions are always on via SHOW_LAYOUT_HEURISTIC
   // This will allow release trunk builds to be used by testers to refine the algorithm
   // Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release
 #ifdef SHOW_LAYOUT_HEURISTIC
 #define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \
-  { *aIsProbablyForLayout = isLayout; \
-    mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \
-    mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; }
+  { \
+    mLayoutHeuristic = isLayout ? \
+      NS_LITERAL_STRING("layout table: " heuristic) : \
+      NS_LITERAL_STRING("data table: " heuristic); \
+    return isLayout; \
+  }
 #else
-#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; }
+#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { return isLayout; }
 #endif
 
-  *aIsProbablyForLayout = false;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
   nsDocAccessible* docAccessible = Document();
   if (docAccessible) {
     PRUint64 docState = docAccessible->State();
     if (docState & states::EDITABLE) {  // Need to see all elements while document is being edited
       RETURN_LAYOUT_ANSWER(false, "In editable document");
     }
   }
 
--- a/accessible/src/html/nsHTMLTableAccessible.h
+++ b/accessible/src/html/nsHTMLTableAccessible.h
@@ -36,16 +36,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsHTMLTableAccessible_H_
 #define _nsHTMLTableAccessible_H_
 
 #include "nsHyperTextAccessibleWrap.h"
 #include "nsIAccessibleTable.h"
+#include "TableAccessible.h"
+#include "xpcAccessibleTable.h"
 
 class nsITableLayout;
 class nsITableCellLayout;
 
 /**
  * HTML table cell accessible (html:td).
  */
 class nsHTMLTableCellAccessible : public nsHyperTextAccessibleWrap,
@@ -116,40 +118,45 @@ public:
 {  /* 8d6d9c40-74bd-47ac-88dc-4a23516aa23d */           \
   0x8d6d9c40,                                           \
   0x74bd,                                               \
   0x47ac,                                               \
   { 0x88, 0xdc, 0x4a, 0x23, 0x51, 0x6a, 0xa2, 0x3d }    \
 }
 
 class nsHTMLTableAccessible : public nsAccessibleWrap,
-                              public nsIAccessibleTable
+                              public xpcAccessibleTable,
+                              public nsIAccessibleTable,
+                              public mozilla::a11y::TableAccessible
 {
 public:
   nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
 
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIACCESSIBLETABLE
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID)
 
+  // nsIAccessible Table
+  NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
+
+  // TableAccessible
+  virtual nsAccessible* Caption();
+  virtual bool IsProbablyLayoutTable();
+
+  // nsAccessNode
+  virtual void Shutdown();
+
   // nsAccessible
+  virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
   virtual void Description(nsString& aDescription);
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual Relation RelationByType(PRUint32 aRelationType);
 
-  // TableAccessible
-  inline nsAccessible* Caption() const
-  {
-    nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
-    return child && child->Role() == mozilla::a11y::roles::CAPTION ? child : nsnull;
-  }
-
   // nsHTMLTableAccessible
 
   /**
    * Retun cell element at the given row and column index.
    */
   nsresult GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex,
                      nsIDOMElement* &aCell);
 
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -127,17 +127,17 @@ role
 nsHyperTextAccessible::NativeRole()
 {
   nsIAtom *tag = mContent->Tag();
 
   if (tag == nsGkAtoms::form)
     return roles::FORM;
 
   if (tag == nsGkAtoms::blockquote || tag == nsGkAtoms::div ||
-      tag == nsGkAtoms::nav)
+      tag == nsGkAtoms::section || tag == nsGkAtoms::nav)
     return roles::SECTION;
 
   if (tag == nsGkAtoms::h1 || tag == nsGkAtoms::h2 ||
       tag == nsGkAtoms::h3 || tag == nsGkAtoms::h4 ||
       tag == nsGkAtoms::h5 || tag == nsGkAtoms::h6)
     return roles::HEADING;
 
   if (tag == nsGkAtoms::article)
@@ -1234,16 +1234,19 @@ nsHyperTextAccessible::GetAttributesInte
 
   // For the html landmark elements we expose them like we do aria landmarks to
   // make AT navigation schemes "just work". Note html:header is redundant as
   // a landmark since it usually contains headings. We're not yet sure how the
   // web will use html:footer but our best bet right now is as contentinfo.
   if (mContent->Tag() == nsGkAtoms::nav)
     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("navigation"));
+  else if (mContent->Tag() == nsGkAtoms::section) 
+    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
+                           NS_LITERAL_STRING("region"));
   else if (mContent->Tag() == nsGkAtoms::footer) 
     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("contentinfo"));
   else if (mContent->Tag() == nsGkAtoms::aside) 
     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("complementary"));
 
   return  NS_OK;
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -109,13 +109,15 @@ FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
+  -I$(srcdir)/../xpcom \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../content/base/src \
   -I$(srcdir)/../../../content/events/src \
   $(NULL)
--- a/accessible/src/xpcom/Makefile.in
+++ b/accessible/src/xpcom/Makefile.in
@@ -45,18 +45,20 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_xpcom_s
 LIBXUL_LIBRARY = 1
 
 CPPSRCS = \
   nsAccEvent.cpp \
   nsAccessibleRelation.cpp \
+  xpcAccessibleTable.cpp \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/accessible/src/xpcom/xpcAccessibleTable.cpp
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xpcAccessibleTable.h"
+
+#include "nsAccessible.h"
+#include "TableAccessible.h"
+
+nsresult
+xpcAccessibleTable::GetCaption(nsIAccessible** aCaption)
+{
+  NS_ENSURE_ARG_POINTER(aCaption);
+  *aCaption = nsnull;
+  if (!mTable)
+    return NS_ERROR_FAILURE;
+
+  NS_IF_ADDREF(*aCaption = mTable->Caption());
+  return NS_OK;
+}
+
+nsresult
+xpcAccessibleTable::IsProbablyForLayout(bool* aResult)
+{
+  NS_ENSURE_ARG_POINTER(aResult);
+  *aResult = false;
+  if (!mTable)
+    return NS_ERROR_FAILURE;
+
+  *aResult = mTable->IsProbablyLayoutTable();
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/xpcom/xpcAccessibleTable.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
+#define MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
+
+#include "nscore.h"
+
+class nsIAccessible;
+namespace mozilla {
+namespace a11y {
+class TableAccessible;
+}
+}
+
+class xpcAccessibleTable
+{
+public:
+  xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { }
+
+  nsresult GetCaption(nsIAccessible** aCaption);
+  nsresult IsProbablyForLayout(bool* aIsForLayout);
+
+protected:
+  mozilla::a11y::TableAccessible* mTable;
+};
+
+#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \
+  NS_IMETHOD GetCaption(nsIAccessible** aCaption) \
+    { return xpcAccessibleTable::GetCaption(aCaption); } \
+  NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary); \
+  NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32 *aRowCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString & _retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString & _retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIndex, bool *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIndex, PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32 *aSelectedCellCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32 *cellsArraySize NS_OUTPARAM, PRInt32 **cellsArray NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 rowIndex); \
+  NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 columnIndex); \
+  NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 columnIndex); \
+  NS_IMETHOD UnselectRow(PRInt32 aRowIdx); \
+  NS_IMETHOD IsProbablyForLayout(bool* aResult) \
+  { return xpcAccessibleTable::IsProbablyForLayout(aResult); } \
+
+#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
--- a/accessible/src/xul/Makefile.in
+++ b/accessible/src/xul/Makefile.in
@@ -67,12 +67,14 @@ CPPSRCS = \
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
   -I$(srcdir) \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
+  -I$(srcdir)/../xpcom \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -129,17 +129,17 @@ nsXULColumnItemAccessible::DoAction(PRUi
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULListboxAccessible::
   nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  XULSelectControlAccessible(aContent, aDoc)
+  XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
 {
   nsIContent* parentContent = mContent->GetParent();
   if (parentContent) {
     nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
       do_QueryInterface(parentContent);
     if (autoCompletePopupElm)
       mFlags |= eAutoCompletePopupAccessible;
   }
@@ -159,16 +159,26 @@ nsXULListboxAccessible::QueryInterface(R
     *aInstancePtr = static_cast<nsIAccessibleTable*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
   }
 
   return NS_ERROR_NO_INTERFACE;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//nsAccessNode
+
+void
+nsXULListboxAccessible::Shutdown()
+{
+  mTable = nsnull;
+  XULSelectControlAccessible::Shutdown();
+}
+
 bool
 nsXULListboxAccessible::IsMulticolumn()
 {
   PRInt32 numColumns = 0;
   nsresult rv = GetColumnCount(&numColumns);
   if (NS_FAILED(rv))
     return false;
 
@@ -225,25 +235,16 @@ nsXULListboxAccessible::NativeRole()
 
   return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListboxAccessible. nsIAccessibleTable
 
 NS_IMETHODIMP
-nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption)
-{
-  NS_ENSURE_ARG_POINTER(aCaption);
-  *aCaption = nsnull;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsXULListboxAccessible::GetSummary(nsAString &aSummary)
 {
   aSummary.Truncate();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -815,25 +816,16 @@ nsXULListboxAccessible::UnselectRow(PRIn
 
 NS_IMETHODIMP
 nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn)
 {
   // xul:listbox and xul:richlistbox support row selection only.
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULListboxAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
-{
-  NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
-  *aIsProbablyForLayout = false;
-
-  return NS_OK;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListboxAccessible: Widgets
 
 bool
 nsXULListboxAccessible::IsWidget() const
 {
   return true;
 }
--- a/accessible/src/xul/nsXULListboxAccessible.h
+++ b/accessible/src/xul/nsXULListboxAccessible.h
@@ -35,21 +35,22 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef __nsXULListboxAccessible_h__
 #define __nsXULListboxAccessible_h__
 
-#include "nsIAccessibleTable.h"
-
 #include "nsCOMPtr.h"
 #include "nsXULMenuAccessible.h"
 #include "nsBaseWidgetAccessible.h"
+#include "nsIAccessibleTable.h"
+#include "TableAccessible.h"
+#include "xpcAccessibleTable.h"
 #include "XULSelectControlAccessible.h"
 
 class nsIWeakReference;
 
 /**
  * nsXULColumnsAccessible are accessible for list and tree columns elements
  * (xul:treecols and xul:listcols).
  */
@@ -85,29 +86,37 @@ public:
 
   enum { eAction_Click = 0 };
 };
 
 /*
  * A class the represents the XUL Listbox widget.
  */
 class nsXULListboxAccessible : public XULSelectControlAccessible,
-                               public nsIAccessibleTable
+                               public xpcAccessibleTable,
+                               public nsIAccessibleTable,
+                               public mozilla::a11y::TableAccessible
 {
 public:
   nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
   virtual ~nsXULListboxAccessible() {}
 
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIACCESSIBLETABLE
+
+  // nsIAccessibleTable
+  NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString& aValue);
 
+  // nsAccessNode
+  virtual void Shutdown();
+
   // nsAccessible
+  virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
 
   // Widgets
   virtual bool IsWidget() const;
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
 
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -53,40 +53,31 @@
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTreeGridAccessible::
   nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  nsXULTreeAccessible(aContent, aDoc)
+  nsXULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible: nsISupports implementation
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible,
                              nsXULTreeAccessible,
                              nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible: nsIAccessibleTable implementation
 
 NS_IMETHODIMP
-nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption)
-{
-  NS_ENSURE_ARG_POINTER(aCaption);
-  *aCaption = nsnull;
-
-  return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
-}
-
-NS_IMETHODIMP
 nsXULTreeGridAccessible::GetSummary(nsAString &aSummary)
 {
   aSummary.Truncate();
   return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeGridAccessible::GetColumnCount(PRInt32 *aColumnCount)
@@ -565,23 +556,24 @@ nsXULTreeGridAccessible::UnselectRow(PRI
 }
 
 NS_IMETHODIMP
 nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex)
 {
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULTreeGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridAccessible: nsAccessNode implementation
+
+void
+nsXULTreeGridAccessible::Shutdown()
 {
-  NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
-  *aIsProbablyForLayout = false;
-
-  return NS_OK;
+  mTable = nsnull;
+  nsXULTreeAccessible::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible: nsAccessible implementation
 
 role
 nsXULTreeGridAccessible::NativeRole()
 {
--- a/accessible/src/xul/nsXULTreeGridAccessible.h
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -34,36 +34,42 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __nsXULTreeGridAccessible_h__
 #define __nsXULTreeGridAccessible_h__
 
-#include "nsIAccessibleTable.h"
-
 #include "nsXULTreeAccessible.h"
+#include "TableAccessible.h"
+#include "xpcAccessibleTable.h"
 
 /**
  * Represents accessible for XUL tree in the case when it has multiple columns.
  */
 class nsXULTreeGridAccessible : public nsXULTreeAccessible,
-                                public nsIAccessibleTable
+                                public xpcAccessibleTable,
+                                public nsIAccessibleTable,
+                                public mozilla::a11y::TableAccessible
 {
 public:
   nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessibleTable
-  NS_DECL_NSIACCESSIBLETABLE
+  NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
+
+  // nsAccessNode
+  virtual void Shutdown();
 
   // nsAccessible
+  virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
   virtual mozilla::a11y::role NativeRole();
 
 protected:
 
   // nsXULTreeAccessible
   virtual already_AddRefed<nsAccessible> CreateTreeItemAccessible(PRInt32 aRow);
 };
 
--- a/accessible/tests/mochitest/elm/test_landmarks.html
+++ b/accessible/tests/mochitest/elm/test_landmarks.html
@@ -19,33 +19,36 @@
 
     function doTest()
     {
       testRole("nav", ROLE_SECTION);
       testRole("header", ROLE_HEADER);
       testRole("footer", ROLE_FOOTER);
       testRole("article", ROLE_DOCUMENT);
       testRole("aside", ROLE_NOTE);
+      testRole("section", ROLE_SECTION); // XXX bug 739612: not a landmark
 
       testRole("main", ROLE_DOCUMENT);
       testRole("form", ROLE_FORM);
 
       // Some AT may look for this
       testAttrs("nav", {"xml-roles" : "navigation"}, true);
       testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
       testAttrs("aside", {"xml-roles" : "complementary"}, true);
+      testAttrs("section", {"xml-roles" : "region"}, true);
       testAttrs("main", {"xml-roles" : "main"}, true); // // ARIA override
       testAttrs("form", {"xml-roles" : "form"}, true);
 
       // And some AT may look for this
       testAttrs("nav", {"tag" : "nav"}, true);
       testAttrs("header", {"tag" : "header"}, true);
       testAttrs("footer", {"tag" : "footer"}, true);
       testAttrs("article", {"tag" : "article"}, true);
       testAttrs("aside", {"tag" : "aside"}, true);
+      testAttrs("section", {"tag" : "section"}, true);
       testAttrs("main", {"tag" : "article"}, true);
       testAttrs("form", {"tag" : "article"}, true);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
@@ -64,28 +67,34 @@
     Bug 613502
   </a>
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=610650"
      title="Change implementation of HTML5 landmark elements to conform">
     Bug 610650
   </a>
   <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=614310"
+     title="Map section to pane (like role=region)">
+    Mozilla Bug 614310
+  </a>
+  <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=734982"
      title="Map ARIA role FORM">
     Bug 734982
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <nav id="nav">a nav</nav>
   <header id="header">a header</header>
   <footer id="footer">a footer</footer>
   <aside id="aside">by the way I am an aside</aside>
+  <section id="section">a section</section>
 
   <article id="article">an article</article>
   <article id="main" role="main">a main area</article>
   <article id="form" role="form">a form area</article>
 
 </body>
 </html>
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -48,16 +48,17 @@ const ROLE_PAGETABLIST = nsIAccessibleRo
 const ROLE_PANE = nsIAccessibleRole.ROLE_PANE;
 const ROLE_PARAGRAPH = nsIAccessibleRole.ROLE_PARAGRAPH;
 const ROLE_PARENT_MENUITEM = nsIAccessibleRole.ROLE_PARENT_MENUITEM;
 const ROLE_PASSWORD_TEXT = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
 const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
 const ROLE_PROPERTYPAGE = nsIAccessibleRole.ROLE_PROPERTYPAGE;
 const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
 const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
+const ROLE_RICH_OPTION = nsIAccessibleRole.ROLE_RICH_OPTION;
 const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
 const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
 const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;
 const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
 const ROLE_SEPARATOR = nsIAccessibleRole.ROLE_SEPARATOR;
 const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
 const ROLE_STATICTEXT = nsIAccessibleRole.ROLE_STATICTEXT;
 const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -52,16 +52,17 @@ include $(topsrcdir)/config/rules.mk
 		test_cssoverflow.html \
 		test_contextmenu.xul \
 		test_doc.html \
 		test_gencontent.html \
 		test_hidden.html \
 		test_imagemap.html \
 		test_list_editabledoc.html \
 		test_list.html \
+		test_listbox.xul \
 		test_menu.xul \
 		test_menubutton.xul \
 		test_recreation.html \
 		test_select.html \
 		test_textleaf.html \
 		test_visibility.html \
 		test_whitespace.html \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_listbox.xul
@@ -0,0 +1,180 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible XUL listbox hierarchy tests">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    function insertListitem(aListboxID)
+    {
+      this.listboxNode = getNode(aListboxID);
+
+      this.listitemNode = document.createElement("listitem");
+      this.listitemNode.setAttribute("label", "item1");
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, this.listitemNode),
+        new invokerChecker(EVENT_REORDER, this.listboxNode)
+      ];
+
+      this.invoke = function insertListitem_invoke()
+      {
+        this.listboxNode.insertBefore(this.listitemNode,
+                                      this.listboxNode.firstChild);
+      }
+
+      this.finalCheck = function insertListitem_finalCheck()
+      {
+        var tree =
+          { LISTBOX: [
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item1"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item2"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item3"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item4"
+            }
+          ] };
+        testAccessibleTree(this.listboxNode, tree);
+      }
+
+      this.getID = function insertListitem_getID()
+      {
+        return "insert listitem ";
+      }
+    }
+
+    function removeListitem(aListboxID)
+    {
+      this.listboxNode = getNode(aListboxID);
+      this.listitemNode = null;
+      this.listitem;
+
+      function getListitem(aThisObj)
+      {
+        return aThisObj.listitem;
+      }
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getListitem, this),
+        new invokerChecker(EVENT_REORDER, this.listboxNode)
+      ];
+
+      this.invoke = function removeListitem_invoke()
+      {
+        this.listitemNode = this.listboxNode.firstChild;
+        this.listitem = getAccessible(this.listitemNode);
+
+        this.listboxNode.removeChild(this.listitemNode);
+      }
+
+      this.finalCheck = function removeListitem_finalCheck()
+      {
+        var tree =
+          { LISTBOX: [
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item2"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item3"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item4"
+            }
+          ] };
+        testAccessibleTree(this.listboxNode, tree);
+      }
+
+      this.getID = function removeListitem_getID()
+      {
+        return "remove listitem ";
+      }
+    }
+
+    //gA11yEventDumpToConsole = true; // debug stuff
+
+    var gQueue = null;
+    function doTest()
+    {
+      var tree =
+        { LISTBOX: [
+          {
+            role: ROLE_RICH_OPTION,
+            name: "item2"
+          },
+          {
+            role: ROLE_RICH_OPTION,
+            name: "item3"
+          },
+          {
+            role: ROLE_RICH_OPTION,
+            name: "item4"
+          }
+        ] };
+      testAccessibleTree("listbox", tree);
+
+      gQueue = new eventQueue();
+      gQueue.push(new insertListitem("listbox"));
+      gQueue.push(new removeListitem("listbox"));
+      gQueue.invoke(); // Will call SimpleTest.finish()
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=656225"
+         title="XUL listbox accessible tree doesn't get updated">
+        Mozilla Bug 656225
+      </a>
+      <br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <listbox id="listbox" rows="2">
+        <listitem label="item2"/>
+        <listitem label="item3"/>
+        <listitem label="item4"/>
+      </listbox>
+    </vbox>
+  </hbox>
+
+</window>
+
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -64,8 +64,9 @@ if test "$LIBXUL_SDK"; then
 MOZ_XULRUNNER=1
 else
 MOZ_XULRUNNER=
 MOZ_PLACES=1
 fi
 
 MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 MOZ_EXTENSION_MANAGER=1
+ENABLE_MARIONETTE=1
--- a/browser/Makefile.in
+++ b/browser/Makefile.in
@@ -51,23 +51,24 @@ PARALLEL_DIRS = \
   themes \
   $(NULL)
 
 DIRS = \
   devtools \
   app \
   $(NULL)
 
-ifeq ($(OS_ARCH),WINNT)
+ifdef MAKENSISU
 DIRS += installer/windows
 endif
 
 include $(topsrcdir)/config/rules.mk
 
-ifeq ($(OS_ARCH),WINNT)
+ifdef MAKENSISU
+
 # For Windows build the uninstaller during the application build since the
 # uninstaller is included with the application for mar file generation.
 libs::
 	$(MAKE) -C installer/windows uninstaller
 ifdef MOZ_MAINTENANCE_SERVICE
 	$(MAKE) -C installer/windows maintenanceservice_installer
 endif
 endif
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -8658,16 +8658,41 @@ let gPrivateBrowsingUI = {
         return;
 
     this._privateBrowsingService.privateBrowsingEnabled =
       !this.privateBrowsingEnabled;
   },
 
   get privateBrowsingEnabled() {
     return this._privateBrowsingService.privateBrowsingEnabled;
+  },
+
+  /**
+   * These accessors are used to support per-window Private Browsing mode.
+   * For now the getter returns nsIPrivateBrowsingService.privateBrowsingEnabled,
+   * and the setter should only be used in tests.
+   */
+  get privateWindow() {
+    return window.getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsIDocShellTreeItem)
+                 .treeOwner
+                 .QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIXULWindow)
+                 .docShell.QueryInterface(Ci.nsILoadContext)
+                 .usePrivateBrowsing;
+  },
+
+  set privateWindow(val) {
+    return window.getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsIDocShellTreeItem)
+                 .treeOwner
+                 .QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIXULWindow)
+                 .docShell.QueryInterface(Ci.nsILoadContext)
+                 .usePrivateBrowsing = val;
   }
 };
 
 var LightWeightThemeWebInstaller = {
   handleEvent: function (event) {
     switch (event.type) {
       case "InstallBrowserTheme":
       case "PreviewBrowserTheme":
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -188,19 +188,19 @@ PrivateBrowsingService.prototype = {
           }
         }
         win.close();
       }
 
       if (!this._quitting && this._saveSession) {
         let browserWindow = this._getBrowserWindow();
 
-	// if there are open browser windows, load a dummy session to get a distinct 
+        // if there are open browser windows, load a dummy session to get a distinct 
         // separation between private and non-private sessions
-	if (browserWindow) {
+        if (browserWindow) {
           // set an empty session to transition from/to pb mode, see bug 476463
           ss.setBrowserState(blankState);
 
           // just in case the only remaining window after setBrowserState is different.
           // it probably shouldn't be with the current sessionstore impl, but we shouldn't
           // rely on behaviour the API doesn't guarantee
           browserWindow = this._getBrowserWindow();
           let browser = browserWindow.gBrowser;
@@ -212,17 +212,19 @@ PrivateBrowsingService.prototype = {
           browser.removeTab(browser.tabContainer.firstChild);
           browserWindow.getInterface(Ci.nsIWebNavigation)
                        .QueryInterface(Ci.nsIDocShellTreeItem)
                        .treeOwner
                        .QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIXULWindow)
                        .docShell.contentViewer.resetCloseWindow();
         }
+      }
 
+      if (!this._quitting) {
         var windowsEnum = Services.wm.getEnumerator("navigator:browser");
         while (windowsEnum.hasMoreElements()) {
           var window = windowsEnum.getNext();
           window.getInterface(Ci.nsIWebNavigation)
                 .QueryInterface(Ci.nsIDocShellTreeItem)
                 .treeOwner
                 .QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIXULWindow)
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
@@ -53,31 +53,41 @@ function test() {
   // add a new blank tab to ensure the title can be meaningfully compared later
   gBrowser.selectedTab = gBrowser.addTab();
   let originalTitle = document.title;
 
   // test the gPrivateBrowsingUI object
   ok(gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
   is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started initially");
   is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
+  is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
   ok(pbMenuItem, "The Private Browsing menu item exists");
   is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
   gPrivateBrowsingUI.toggleMode();
   is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started");
   is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status");
+  is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
   // check to see if the Private Browsing mode was activated successfully
   is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object");
   is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\"");
   gPrivateBrowsingUI.toggleMode()
   is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started");
   is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
+  is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
   // check to see if the Private Browsing mode was deactivated successfully
   is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object");
   is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
 
+  // These are tests for the privateWindow setter.  Note that the setter should
+  // not be used anywhere else for now!
+  gPrivateBrowsingUI.privateWindow = true;
+  is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
+  gPrivateBrowsingUI.privateWindow = false;
+  is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
+
   // now, test using the <command> object
   let cmd = document.getElementById("Tools:PrivateBrowsing");
   isnot(cmd, null, "XUL command object for the private browsing service exists");
   var func = new Function("", cmd.getAttribute("oncommand"));
   func.call(cmd);
   // check to see if the Private Browsing mode was activated successfully
   is(observerData, "enter", "Private Browsing mode was activated using the command object");
   // check to see that the window title has been changed correctly
--- a/browser/makefiles.sh
+++ b/browser/makefiles.sh
@@ -97,17 +97,17 @@ security/manager/locales/Makefile
 "
 
 if [ "$MOZ_SAFE_BROWSING" ]; then
   add_makefiles "
     browser/components/safebrowsing/Makefile
   "
 fi
 
-if [ "$MOZ_WIDGET_TOOLKIT" = "windows" ]; then
+if [ "$MAKENSISU" ]; then
   add_makefiles "
     browser/installer/windows/Makefile
   "
 fi
 
 if [ "$MOZ_WIDGET_TOOLKIT" = "gtk2" -o "$MOZ_WIDGET_TOOLKIT" = "qt" ]; then
   add_makefiles "
     browser/themes/gnomestripe/Makefile
--- a/build/mobile/robocop/Assert.java.in
+++ b/build/mobile/robocop/Assert.java.in
@@ -36,16 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package @ANDROID_PACKAGE_NAME@;
 
 public interface Assert {
     void dumpLog(String message);
+    void dumpLog(String message, Throwable t);
     void setLogFile(String filename);
     void setTestName(String testName);
 
     void finalize();
     void ok(boolean condition, String name, String diag);
     void is(Object a, Object b, String name);
     void isnot(Object a, Object b, String name);
     void todo(boolean condition, String name, String diag);
--- a/build/mobile/robocop/FennecMochitestAssert.java.in
+++ b/build/mobile/robocop/FennecMochitestAssert.java.in
@@ -61,16 +61,21 @@ public class FennecMochitestAssert imple
     public FennecMochitestAssert() {
     }
 
     /** Write information to a logfile and logcat */
     public void dumpLog(String message) {
         FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
     }
 
+    /** Write information to a logfile and logcat */
+    public void dumpLog(String message, Throwable t) {
+        FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
+    }
+
     /** Set the filename used for dumpLog. */
     public void setLogFile(String filename) {
         FennecNativeDriver.setLogFile(filename);
 
         String message;
         if (!mLogStarted) {
             dumpLog(Integer.toString(mLineNumber++) + " INFO SimpleTest START");
             mLogStarted = true;
--- a/build/mobile/robocop/FennecNativeDriver.java.in
+++ b/build/mobile/robocop/FennecNativeDriver.java.in
@@ -36,24 +36,24 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package @ANDROID_PACKAGE_NAME@;
 
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
-import java.io.BufferedWriter;
 import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.nio.IntBuffer;
 import java.util.HashMap;
 import java.util.List;
 
 import java.lang.Class;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
@@ -454,46 +454,53 @@ public class FennecNativeDriver implemen
         }
     }
 
     public static void setLogLevel(LogLevel level) {
         mLogLevel = level;
     }
 
     public static void log(LogLevel level, String message) {
+        log(level, message, null);
+    }
+
+    public static void log(LogLevel level, Throwable t) {
+        log(level, null, t);
+    }
+
+    public static void log(LogLevel level, String message, Throwable t) {
         if (mLogFile == null) {
             assert(false);
         }
 
         if (level.isEnabled(mLogLevel)) {
-            File file = new File(mLogFile);
-            BufferedWriter bw = null;
-
+            PrintWriter pw = null;
             try {
-                bw = new BufferedWriter(new FileWriter(mLogFile, true));
-                bw.write(message);
-                bw.newLine();
-            } catch(IOException e) {
+                pw = new PrintWriter(new FileWriter(mLogFile, true));
+                if (message != null) {
+                    pw.println(message);
+                }
+                if (t != null) {
+                    t.printStackTrace(pw);
+                }
+            } catch (IOException ioe) {
                 Log.e("Robocop", "exception with file writer on: " + mLogFile);
             } finally {
-                try {
-                    if (bw != null) {
-                        bw.flush();
-                        bw.close();
-                    }
-                } catch (IOException ex) {
-                    ex.printStackTrace();
-                }
+                pw.close();
+            }
+            // PrintWriter doesn't throw IOE but sets an error flag instead,
+            // so check for that
+            if (pw.checkError()) {
+                Log.e("Robocop", "exception with file writer on: " + mLogFile);
             }
         }
 
         if (level == LogLevel.LOG_LEVEL_INFO) {
-            Log.i("Robocop", message);
+            Log.i("Robocop", message, t);
         } else if (level == LogLevel.LOG_LEVEL_DEBUG) {
-            Log.d("Robocop", message);
+            Log.d("Robocop", message, t);
         } else if (level == LogLevel.LOG_LEVEL_WARN) {
-            Log.w("Robocop", message);
+            Log.w("Robocop", message, t);
         } else if (level == LogLevel.LOG_LEVEL_ERROR) {
-            Log.e("Robocop", message);
+            Log.e("Robocop", message, t);
         }
     }
-
 }
--- a/build/mobile/robocop/FennecTalosAssert.java.in
+++ b/build/mobile/robocop/FennecTalosAssert.java.in
@@ -44,16 +44,21 @@ public class FennecTalosAssert implement
 
     /**
      *  Write information to a logfile and logcat
      */
     public void dumpLog(String message) {
         FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
     }
 
+    /** Write information to a logfile and logcat */
+    public void dumpLog(String message, Throwable t) {
+        FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
+    }
+
     /**
      *  Set the filename used for dumpLog.
      */
     public void setLogFile(String filename) {
         FennecNativeDriver.setLogFile(filename);
     }
 
     public void setTestName(String testName) { }
--- a/build/mobile/robocop/Makefile.in
+++ b/build/mobile/robocop/Makefile.in
@@ -122,18 +122,18 @@ tools:: robocop.apk
 classes.dex: robocop.ap_
 classes.dex: $(_ROBOCOP_TOOLS)
 classes.dex: $(_JAVA_HARNESS)
 classes.dex: $(_JAVA_TESTS)
 	$(NSINSTALL) -D classes
 	$(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(addprefix $(DEPTH)/mobile/android/base/tests/,$(_JAVA_TESTS))
 	$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH)
 
-robocop.ap_: AndroidManifest.xml
-	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -F $@ -J ./
+robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
+	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./
 
 robocop.apk: robocop.ap_ classes.dex
 	cp $(TESTPATH)/robocop.ini robocop.ini
 	cp $(srcdir)/parse_ids.py parse_ids.py
 
 export::
 	$(NSINSTALL) -D res
 	@(cd $(srcdir)/res && tar $(TAR_CREATE_FLAGS) - *) | (cd $(DEPTH)/build/mobile/robocop/res && tar -xf -)
--- a/build/unix/build-toolchain/build-gcc.py
+++ b/build/unix/build-toolchain/build-gcc.py
@@ -260,16 +260,16 @@ os.makedirs(build_dir)
 
 build_aux_tools(build_dir)
 
 stage1_dir = build_dir + '/stage1'
 build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
 
 stage1_tool_inst_dir = stage1_dir + '/inst'
 stage2_dir = build_dir + '/stage2'
-build_one_stage({"CC"     : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline",
-                 "CXX"    : stage1_tool_inst_dir + "/bin/g++",
-                 "AR"     : stage1_tool_inst_dir + "/bin/ar",
+build_one_stage({"PATH"   : stage1_tool_inst_dir + "/bin:/bin:/usr/bin",
+                 "CC"     : "gcc -fgnu89-inline",
+                 "CXX"    : "g++",
                  "RANLIB" : "true" },
                 stage2_dir, False)
 
 build_tar_package(aux_inst_dir + "/bin/tar",
                   "toolchain.tar", stage2_dir, "inst")
--- a/configure.in
+++ b/configure.in
@@ -6314,39 +6314,48 @@ if test -n "$MOZ_TREE_FREETYPE"; then
    AC_DEFINE(HAVE_FT_LOAD_SFNT_TABLE)
    AC_SUBST(CAIRO_FT_CFLAGS)
 fi
 
 dnl ========================================================
 dnl Installer
 dnl ========================================================
 dnl Abort Windows build if the required major version and
-dnl minimum minor version of Unicode NSIS isn't in the path.
+dnl minimum minor version of Unicode NSIS isn't in the path
+dnl (unless in case of cross compiling, for which Unicode
+dnl is not yet sufficient).
 if test "$OS_ARCH" = "WINNT"; then
     REQ_NSIS_MAJOR_VER=2
     MIN_NSIS_MINOR_VER=33
     MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
-    if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
-        AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
-    fi
-    changequote(,)
-    MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
-    changequote([,])
-    if test ! "$MAKENSISU_VER" = ""; then
-        MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
-        MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
-    fi
-    AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
-    if test "$MAKENSISU_VER" = "" ||
-       test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
-            ! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
-        AC_MSG_RESULT([no])
-        AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
-    fi
-    AC_MSG_RESULT([yes])
+    if test -n "$MAKENSISU" -a "$MAKENSISU" != ":"; then
+      AC_MSG_RESULT([yes])
+      changequote(,)
+      MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
+      changequote([,])
+      if test ! "$MAKENSISU_VER" = ""; then
+          MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
+          MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
+      fi
+      AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
+      if test "$MAKENSISU_VER" = "" || \
+         test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
+              ! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
+          AC_MSG_RESULT([no])
+          if test -z "$CROSS_COMPILE"; then
+            AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
+          else
+            MAKENSISU=
+          fi
+      fi
+    elif test -z "$CROSS_COMPILE"; then
+      AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
+    else
+      MAKENSISU=
+    fi
 fi
 
 AC_MSG_CHECKING([for tar archiver])
 AC_CHECK_PROGS(TAR, gnutar gtar tar, "")
 if test -z "$TAR"; then
     AC_MSG_ERROR([no tar archiver found in \$PATH])
 fi
 AC_MSG_RESULT([$TAR])
@@ -6454,24 +6463,16 @@ dnl ====================================
 dnl build the tests by default
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(tests,
 [  --disable-tests         Do not build test libraries & programs],
     ENABLE_TESTS=,
     ENABLE_TESTS=1 )
 
 dnl ========================================================
-dnl Marionette
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(marionette,
-[  --enable-marionette     Enable Marionette for remote testing and control],
-    ENABLE_MARIONETTE=1,
-    ENABLE_MARIONETTE)
-
-dnl ========================================================
 dnl parental controls (for Windows Vista)
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(parental-controls,
 [  --disable-parental-controls
                           Do not build parental controls],
    MOZ_DISABLE_PARENTAL_CONTROLS=1,
    MOZ_DISABLE_PARENTAL_CONTROLS=)
 if test -n "$MOZ_DISABLE_PARENTAL_CONTROLS"; then
--- a/content/base/src/contentSecurityPolicy.js
+++ b/content/base/src/contentSecurityPolicy.js
@@ -14,16 +14,17 @@
  * The Original Code is the ContentSecurityPolicy module.
  *
  * The Initial Developer of the Original Code is
  *   Mozilla Corporation
  *
  * Contributor(s):
  *   Sid Stamm <sid@mozilla.com>
  *   Brandon Sterne <bsterne@mozilla.com>
+ *   Ian Melven <imelven@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -296,28 +297,32 @@ ContentSecurityPolicy.prototype = {
       // should be taken care of in CSPRep.fromString (where it converts any
       // relative URIs into absolute ones based on "self").
       for (let i in uris) {
         if (uris[i] === "")
           continue;
 
         var failure = function(aEvt) {  
           if (req.readyState == 4 && req.status != 200) {
-            CSPError("Failed to send report to " + reportURI);
+            CSPError("Failed to send report to " + uris[i]);
           }  
         };  
         var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]  
                     .createInstance(Ci.nsIXMLHttpRequest);  
 
         try {
           req.open("POST", uris[i], true);
           req.setRequestHeader('Content-Type', 'application/json');
           req.upload.addEventListener("error", failure, false);
           req.upload.addEventListener("abort", failure, false);
 
+          // we need to set an nsIChannelEventSink on the XHR object
+          // so we can tell it to not follow redirects when posting the reports
+          req.channel.notificationCallbacks = new CSPReportRedirectSink();
+
           req.send(JSON.stringify(report));
           CSPdebug("Sent violation report to " + uris[i]);
         } catch(e) {
           // it's possible that the URI was invalid, just log a
           // warning and skip over that.
           CSPWarning("Tried to send report to invalid URI: \"" + uris[i] + "\"");
         }
       }
@@ -489,9 +494,59 @@ ContentSecurityPolicy.prototype = {
                                      CSP_VIOLATION_TOPIC,
                                      violatedDirective);
         reportSender.sendReports(blockedContentSource, violatedDirective,
                                  aSourceFile, aScriptSample, aLineNum);
       }, Ci.nsIThread.DISPATCH_NORMAL);
   },
 };
 
+// The POST of the violation report (if it happens) should not follow
+// redirects, per the spec. hence, we implement an nsIChannelEventSink
+// with an object so we can tell XHR to abort if a redirect happens.
+function CSPReportRedirectSink() {
+}
+
+CSPReportRedirectSink.prototype = {
+  QueryInterface: function requestor_qi(iid) {
+    if (iid.equals(Ci.nsISupports) ||
+        iid.equals(Ci.nsIInterfaceRequestor) ||
+        iid.equals(Ci.nsIChannelEventSink))
+      return this;
+    throw Cr.NS_ERROR_NO_INTERFACE;
+  },
+
+  // nsIInterfaceRequestor
+  getInterface: function requestor_gi(iid) {
+    if (iid.equals(Ci.nsIChannelEventSink))
+      return this;
+
+    throw Components.results.NS_ERROR_NO_INTERFACE;
+  },
+
+  // nsIChannelEventSink
+  asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel,
+                                                    flags, callback) {
+    CSPWarning("Post of violation report to " + oldChannel.URI.asciiSpec +
+               " failed, as a redirect occurred");
+
+    // cancel the old channel so XHR failure callback happens
+    oldChannel.cancel(Cr.NS_ERROR_ABORT);
+
+    // notify an observer that we have blocked the report POST due to a redirect,
+    // used in testing, do this async since we're in an async call now to begin with
+    Services.tm.mainThread.dispatch(
+      function() {
+        observerSubject = Cc["@mozilla.org/supports-cstring;1"]
+                             .createInstance(Ci.nsISupportsCString);
+        observerSubject.data = oldChannel.URI.asciiSpec;
+
+        Services.obs.notifyObservers(observerSubject,
+                                     CSP_VIOLATION_TOPIC,
+                                     "denied redirect while sending violation report");
+      }, Ci.nsIThread.DISPATCH_NORMAL);
+
+    // throw to stop the redirect happening
+    throw Cr.NS_BINDING_REDIRECTED;
+  }
+};
+
 var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentSecurityPolicy]);
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -373,8 +373,34 @@ nsCCUncollectableMarker::Observe(nsISupp
   if (xulCache) {
     xulCache->MarkInCCGeneration(sGeneration);
   }
 #endif
 
   return NS_OK;
 }
 
+static PLDHashOperator
+TraceActiveWindowGlobal(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
+{
+  if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
+    if (JSObject* global = aWindow->FastGetGlobalJSObject()) {
+      JSTracer* trc = static_cast<JSTracer *>(aClosure);
+      JS_CALL_OBJECT_TRACER(trc, global, "active window global");
+    }
+  }
+  return PL_DHASH_NEXT;
+}
+
+void
+mozilla::dom::TraceBlackJS(JSTracer* aTrc)
+{
+  if (!nsCCUncollectableMarker::sGeneration) {
+    return;
+  }
+
+  // Mark globals of active windows black.
+  nsGlobalWindow::WindowByIdTable* windowsById =
+    nsGlobalWindow::GetWindowsTable();
+  if (windowsById) {
+    windowsById->Enumerate(TraceActiveWindowGlobal, aTrc);
+  }
+}
--- a/content/base/src/nsCCUncollectableMarker.h
+++ b/content/base/src/nsCCUncollectableMarker.h
@@ -33,16 +33,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIObserver.h"
 #include "nsCycleCollectionParticipant.h"
 
+struct JSTracer;
+
 class nsCCUncollectableMarker : public nsIObserver
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   /**
    * Inits a global nsCCUncollectableMarker. Should only be called once.
    */
@@ -51,20 +53,26 @@ class nsCCUncollectableMarker : public n
   /**
    * Checks if we're collecting during a given generation
    */
   static bool InGeneration(PRUint32 aGeneration)
   {
     return aGeneration && aGeneration == sGeneration;
   }
 
-  static bool InGeneration(nsCycleCollectionTraversalCallback &cb,
+  static bool InGeneration(nsCycleCollectionTraversalCallback& aCb,
                            PRUint32 aGeneration)
   {
-    return InGeneration(aGeneration) && !cb.WantAllTraces();
+    return InGeneration(aGeneration) && !aCb.WantAllTraces();
   }
 
   static PRUint32 sGeneration;
 
 private:
   nsCCUncollectableMarker() {}
 
 };
+
+namespace mozilla {
+namespace dom {
+void TraceBlackJS(JSTracer* aTrc);
+}
+}
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2542,16 +2542,17 @@ nsDocument::InitCSP()
 #endif
   return NS_OK;
 }
 
 void
 nsDocument::StopDocumentLoad()
 {
   if (mParser) {
+    mParserAborted = true;
     mParser->Terminate();
   }
 }
 
 void
 nsDocument::SetDocumentURI(nsIURI* aURI)
 {
   nsCOMPtr<nsIURI> oldBase = GetDocBaseURI();
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1183,16 +1183,20 @@ protected:
 
   // Whether we are currently in full-screen mode, as per the DOM API.
   bool mIsFullScreen:1;
 
   // Whether we're currently under a FlushPendingNotifications call to
   // our presshell.  This is used to handle flush reentry correctly.
   bool mInFlush:1;
 
+  // Parser aborted. True if the parser of this document was forcibly
+  // terminated instead of letting it finish at its own pace.
+  bool mParserAborted:1;
+
   PRUint8 mXMLDeclarationBits;
 
   nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject> *mBoxObjectTable;
 
   // The channel that got passed to StartDocumentLoad(), if any
   nsCOMPtr<nsIChannel> mChannel;
   nsRefPtr<nsHTMLCSSStyleSheet> mStyleAttrStyleSheet;
   nsRefPtr<nsXMLEventsManager> mXMLEventsManager;
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1930,17 +1930,18 @@ GK_ATOM(Stop, "Stop")
 GK_ATOM(Search, "Search")
 GK_ATOM(Bookmarks, "Bookmarks")
 GK_ATOM(Home, "Home")
 GK_ATOM(Clear, "Clear")
 GK_ATOM(VolumeUp, "VolumeUp")
 GK_ATOM(VolumeDown, "VolumeDown")
 GK_ATOM(Menu, "Menu")
 
-// Smooth scroll profiles
+// Smooth scroll events origins
+GK_ATOM(mouseWheel, "mouseWheel")  // For discrete wheel events (e.g. not OSX magic mouse)
 GK_ATOM(pixels,     "pixels")
 GK_ATOM(lines,      "lines")
 GK_ATOM(pages,      "pages")
 GK_ATOM(scrollbars, "scrollbars")
 GK_ATOM(other,      "other")
 
 #ifdef ACCESSIBILITY
 GK_ATOM(anonid, "anonid")
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -309,52 +309,42 @@ nsImageLoadingContent::OnStopDecode(imgI
   if (mCurrentRequestNeedsResetAnimation) {
     nsCOMPtr<imgIContainer> container;
     mCurrentRequest->GetImage(getter_AddRefs(container));
     if (container)
       container->ResetAnimation();
     mCurrentRequestNeedsResetAnimation = false;
   }
 
-  // We just loaded all the data we're going to get. If we haven't done an
-  // initial paint, we want to make sure the image starts decoding for 2
-  // reasons:
+  // We just loaded all the data we're going to get. If we're visible and
+  // haven't done an initial paint (*), we want to make sure the image starts
+  // decoding immediately, for two reasons:
   //
   // 1) This image is sitting idle but might need to be decoded as soon as we
   // start painting, in which case we've wasted time.
   //
   // 2) We want to block onload until all visible images are decoded. We do this
-  // by blocking onload until all in progress decodes get at least one frame
+  // by blocking onload until all in-progress decodes get at least one frame
   // decoded. However, if all the data comes in while painting is suppressed
   // (ie, before the initial paint delay is finished), we fire onload without
   // doing a paint first. This means that decode-on-draw images don't start
   // decoding, so we can't wait for them to finish. See bug 512435.
+  //
+  // (*) IsPaintingSuppressed returns false if we haven't gotten the initial
+  // reflow yet, so we have to test !DidInitialReflow || IsPaintingSuppressed.
+  // It's possible for painting to be suppressed for reasons other than the
+  // initial paint delay (for example, being in the bfcache), but we probably
+  // aren't loading images in those situations.
 
-  // We can only do this if we have a presshell
   nsIDocument* doc = GetOurDocument();
   nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
-  if (shell) {
-    // We need to figure out whether to kick off decoding
-    bool doRequestDecode = false;
-
-    // If we haven't got the initial reflow yet, IsPaintingSuppressed actually
-    // returns false
-    if (!shell->DidInitialReflow())
-      doRequestDecode = true;
+  if (shell && shell->IsVisible() &&
+      (!shell->DidInitialReflow() || shell->IsPaintingSuppressed())) {
 
-    // Figure out if painting is suppressed. Note that it's possible for painting
-    // to be suppressed for reasons other than the initial paint delay (for
-    // example - being in the bfcache), but we probably aren't loading images in
-    // those situations.
-    if (shell->IsPaintingSuppressed())
-      doRequestDecode = true;
-
-    // If we're requesting a decode, do it
-    if (doRequestDecode)
-      mCurrentRequest->RequestDecode();
+    mCurrentRequest->RequestDecode();
   }
 
   // Fire the appropriate DOM event.
   if (NS_SUCCEEDED(aStatus)) {
     FireEvent(NS_LITERAL_STRING("load"));
   } else {
     FireEvent(NS_LITERAL_STRING("error"));
   }
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -2763,20 +2763,23 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
 
   // Hook us up to listen to redirects and the like
   mChannel->GetNotificationCallbacks(getter_AddRefs(mNotificationCallbacks));
   mChannel->SetNotificationCallbacks(this);
 
   // Create our listener
   nsCOMPtr<nsIStreamListener> listener = this;
   if (mState & XML_HTTP_REQUEST_MULTIPART) {
+    Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 1);
     listener = new nsMultipartProxyListener(listener);
     if (!listener) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
+  } else {
+    Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 0);
   }
 
   // Blocking gets are common enough out of XHR that we should mark
   // the channel slow by default for pipeline purposes
   AddLoadFlags(mChannel, nsIRequest::INHIBIT_PIPELINE);
 
   if (!IsSystemXHR()) {
     // Always create a nsCORSListenerProxy here even if it's
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -567,16 +567,22 @@ include $(topsrcdir)/config/rules.mk
 		test_bug696301-2.html \
 		bug696301-script-1.js \
 		bug696301-script-1.js^headers^ \
 		bug696301-script-2.js \
 		test_bug737565.html \
 		test_bug737612.html \
 		test_bug738108.html \
 		test_bug366944.html \
+		test_bug650386_redirect_301.html \
+		test_bug650386_redirect_302.html \
+		test_bug650386_redirect_303.html \
+		test_bug650386_redirect_307.html \
+		file_bug650386_content.sjs \
+		file_bug650386_report.sjs \
 		$(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/file_bug650386_content.sjs
@@ -0,0 +1,37 @@
+// SJS file for tests for bug650386, serves file_bug650386_content.html
+// with a CSP that will trigger a violation and that will report it
+// to file_bug650386_report.sjs
+//
+// This handles 301, 302, 303 and 307 redirects. The HTTP status code
+// returned/type of redirect to do comes from the query string
+// parameter passed in from the test_bug650386_* files and then also
+// uses that value in the report-uri parameter of the CSP
+function handleRequest(request, response) {
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  // this gets used in the CSP as part of the report URI.
+  var redirect = request.queryString;
+
+  if (redirect < 301 || (redirect > 303 && redirect <= 306) || redirect > 307) {
+    // if we somehow got some bogus redirect code here,
+    // do a 302 redirect to the same URL as the report URI
+    // redirects to - this will fail the test.
+    var loc = "http://example.com/some/fake/path";
+    response.setStatusLine("1.1", 302, "Found");
+    response.setHeader("Location", loc, false);
+    return;
+  }
+
+  var csp = "default-src \'self\';report-uri http://mochi.test:8888/tests/content/base/test/file_bug650386_report.sjs?" + redirect;
+
+  response.setHeader("X-Content-Security-Policy", csp, false);
+
+  // the actual file content.
+  // this image load will (intentionally) fail due to the CSP policy of default-src: 'self'
+  // specified by the CSP string above.
+  var content = "<!DOCTYPE HTML><html><body><img src = \"http://some.other.domain.example.com\"></body></html>";
+
+  response.write(content);
+
+  return;
+}
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug650386_report.sjs
@@ -0,0 +1,16 @@
+// SJS file for tests for bug650386, this serves as CSP violation report target
+// and issues a redirect, to make sure the browser does not post to the target
+// of the redirect, per CSP spec.
+// This handles 301, 302, 303 and 307 redirects. The HTTP status code
+// returned/type of redirect to do comes from the query string
+// parameter
+function handleRequest(request, response) {
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  var redirect = request.queryString;
+
+  var loc = "http://example.com/some/fake/path";
+  response.setStatusLine("1.1", redirect, "Found");
+  response.setHeader("Location", loc, false);
+  return;
+}
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug650386_redirect_301.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+Test that CSP violation reports are not sent when a 301 redirect is encountered
+-->
+<head>
+  <title>Test for Bug 650386</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id = "content_iframe"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650386 **/
+
+// This is used to watch the redirect of the report POST get blocked
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+}
+
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    // subject should be an nsURI
+    if(!SpecialPowers.can_QI(subject))
+       return;
+
+    if (topic === "http-on-modify-request") {
+      // this is used to fail the test - if we see the POST to the target of the redirect
+      // we know this is a fail
+      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
+
+      if (asciiSpec == "http://example.com/some/fake/path")
+        window.done(false);
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      // something was blocked, but we are looking specifically for the redirect being blocked
+      if (data == "denied redirect while sending violation report")
+        window.done(true);
+    }
+  },
+
+  // must eventually call this to remove the listener,
+  // or mochitests might get borked.
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+// result == true if we saw the redirect blocked notify, false if we saw the post
+// to the redirect target go out
+window.done = function(result) {
+  ok(result, "a 301 redirect when posting violation report should be blocked");
+
+  // clean up observers and finish the test
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?301';
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug650386_redirect_302.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+Test that CSP violation reports are not sent when a 302 redirect is encountered
+-->
+<head>
+  <title>Test for Bug 650386</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id = "content_iframe"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650386 **/
+
+// This is used to watch the redirect of the report POST get blocked
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+}
+
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    // subject should be an nsURI
+    if(!SpecialPowers.can_QI(subject))
+       return;
+
+    if (topic === "http-on-modify-request") {
+      // this is used to fail the test - if we see the POST to the target of the redirect
+      // we know this is a fail
+      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
+
+      if (asciiSpec == "http://example.com/some/fake/path")
+        window.done(false);
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      // something was blocked, but we are looking specifically for the redirect being blocked
+      if (data == "denied redirect while sending violation report")
+        window.done(true);
+    }
+  },
+
+  // must eventually call this to remove the listener,
+  // or mochitests might get borked.
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+// result == true if we saw the redirect blocked notify, false if we saw the post
+// to the redirect target go out
+window.done = function(result) {
+  ok(result, "a 302 redirect when posting violation report should be blocked");
+
+  // clean up observers and finish the test
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?302';
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug650386_redirect_303.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+Test that CSP violation reports are not sent when a 303 redirect is encountered
+-->
+<head>
+  <title>Test for Bug 650386</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id = "content_iframe"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650386 **/
+
+// This is used to watch the redirect of the report POST get blocked
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+}
+
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    // subject should be an nsURI
+    if(!SpecialPowers.can_QI(subject))
+       return;
+
+    if (topic === "http-on-modify-request") {
+      // this is used to fail the test - if we see the POST to the target of the redirect
+      // we know this is a fail
+      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
+
+      if (asciiSpec == "http://example.com/some/fake/path")
+        window.done(false);
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      // something was blocked, but we are looking specifically for the redirect being blocked
+      if (data == "denied redirect while sending violation report")
+        window.done(true);
+    }
+  },
+
+  // must eventually call this to remove the listener,
+  // or mochitests might get borked.
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+// result == true if we saw the redirect blocked notify, false if we saw the post
+// to the redirect target go out
+window.done = function(result) {
+  ok(result, "a 303 redirect when posting violation report should be blocked");
+
+  // clean up observers and finish the test
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?303';
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug650386_redirect_307.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+Test that CSP violation reports are not sent when a 307 redirect is encountered
+-->
+<head>
+  <title>Test for Bug 650386</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id = "content_iframe"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650386 **/
+
+// This is used to watch the redirect of the report POST get blocked
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+}
+
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    // subject should be an nsURI
+    if(!SpecialPowers.can_QI(subject))
+       return;
+
+    if (topic === "http-on-modify-request") {
+      // this is used to fail the test - if we see the POST to the target of the redirect
+      // we know this is a fail
+      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
+
+      if (asciiSpec == "http://example.com/some/fake/path")
+        window.done(false);
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      // something was blocked, but we are looking specifically for the redirect being blocked
+      if (data == "denied redirect while sending violation report")
+        window.done(true);
+    }
+  },
+
+  // must eventually call this to remove the listener,
+  // or mochitests might get borked.
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+// result == true if we saw the redirect blocked notify, false if we saw the post
+// to the redirect target go out
+window.done = function(result) {
+  ok(result, "a 307 redirect when posting violation report should be blocked");
+
+  // clean up observers and finish the test
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?307';
+</script>
+</pre>
+</body>
+</html>
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -2690,17 +2690,18 @@ nsEventStateManager::UseSystemScrollSett
   return Preferences::GetBool(prefName.get());
 }
 
 nsresult
 nsEventStateManager::DoScrollText(nsIFrame* aTargetFrame,
                                   nsMouseScrollEvent* aMouseEvent,
                                   nsIScrollableFrame::ScrollUnit aScrollQuantity,
                                   bool aAllowScrollSpeedOverride,
-                                  nsQueryContentEvent* aQueryEvent)
+                                  nsQueryContentEvent* aQueryEvent,
+                                  nsIAtom *aOrigin)
 {
   nsIScrollableFrame* frameToScroll = nsnull;
   nsIFrame* scrollFrame = aTargetFrame;
   PRInt32 numLines = aMouseEvent->delta;
   bool isHorizontal = aMouseEvent->scrollFlags & nsMouseScrollEvent::kIsHorizontal;
   aMouseEvent->scrollOverflow = 0;
 
   // If the user recently scrolled with the mousewheel, then they probably want
@@ -2852,27 +2853,27 @@ nsEventStateManager::DoScrollText(nsIFra
     } else {
       mode = nsIScrollableFrame::NORMAL;
     }
 
     // XXX Why don't we limit the pixel scroll amount to less one page??
 
     nsIntPoint overflow;
     frameToScroll->ScrollBy(nsIntPoint(scrollX, scrollY), aScrollQuantity,
-                            mode, &overflow);
+                            mode, &overflow, aOrigin);
     aMouseEvent->scrollOverflow = isHorizontal ? overflow.x : overflow.y;
     return NS_OK;
   }
   
   if (passToParent) {
     nsIFrame* newFrame = nsLayoutUtils::GetCrossDocParentFrame(
         aTargetFrame->PresContext()->FrameManager()->GetRootFrame());
     if (newFrame)
       return DoScrollText(newFrame, aMouseEvent, aScrollQuantity,
-                          aAllowScrollSpeedOverride, aQueryEvent);
+                          aAllowScrollSpeedOverride, aQueryEvent, aOrigin);
   }
 
   aMouseEvent->scrollOverflow = numLines;
 
   return NS_OK;
 }
 
 void
@@ -3208,27 +3209,30 @@ nsEventStateManager::PostHandleEvent(nsP
 
       if (*aStatus != nsEventStatus_eConsumeNoDefault) {
         bool useSysNumLines = UseSystemScrollSettingFor(msEvent);
         PRInt32 action = ComputeWheelActionFor(msEvent, useSysNumLines);
 
         switch (action) {
         case MOUSE_SCROLL_N_LINES:
           DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::LINES,
-                       useSysNumLines);
+                       useSysNumLines, nsnull, nsGkAtoms::mouseWheel);
           break;
 
         case MOUSE_SCROLL_PAGE:
           DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::PAGES,
                        false);
           break;
 
         case MOUSE_SCROLL_PIXELS:
-          DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::DEVICE_PIXELS,
-                       false);
+          {
+            bool fromLines = msEvent->scrollFlags & nsMouseScrollEvent::kFromLines;
+            DoScrollText(aTargetFrame, msEvent, nsIScrollableFrame::DEVICE_PIXELS,
+                         false, nsnull, (fromLines ? nsGkAtoms::mouseWheel : nsnull));
+          }
           break;
 
         case MOUSE_SCROLL_HISTORY:
           DoScrollHistory(msEvent->delta);
           break;
 
         case MOUSE_SCROLL_ZOOM:
           DoScrollZoom(aTargetFrame, msEvent->delta);
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -348,17 +348,18 @@ protected:
    *                    And then, this method does NOT scroll any scrollable
    *                    elements.  I.e., you can just query the scroll target
    *                    information.
    */
   nsresult DoScrollText(nsIFrame* aTargetFrame,
                         nsMouseScrollEvent* aMouseEvent,
                         nsIScrollableFrame::ScrollUnit aScrollQuantity,
                         bool aAllowScrollSpeedOverride,
-                        nsQueryContentEvent* aQueryEvent = nsnull);
+                        nsQueryContentEvent* aQueryEvent = nsnull,
+                        nsIAtom *aOrigin = nsnull);
   void DoScrollHistory(PRInt32 direction);
   void DoScrollZoom(nsIFrame *aTargetFrame, PRInt32 adjustment);
   nsresult GetMarkupDocumentViewer(nsIMarkupDocumentViewer** aMv);
   nsresult ChangeTextSize(PRInt32 change);
   nsresult ChangeFullZoom(PRInt32 change);
   /**
    * Computes actual delta value used for scrolling.  If user customized the
    * scrolling speed and/or direction, this would return the customized value.
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -129,16 +129,17 @@
 #include "nsCCUncollectableMarker.h"
 #include "nsHtml5Module.h"
 #include "prprf.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Preferences.h"
 #include "nsMimeTypes.h"
 #include "nsIRequest.h"
 #include "nsHtml5TreeOpExecutor.h"
+#include "nsHtml5Parser.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 #define NS_MAX_DOCUMENT_WRITE_DEPTH 20
 
 #include "prmem.h"
 #include "prtime.h"
@@ -1553,16 +1554,17 @@ nsHTMLDocument::Open(const nsAString& aC
   if (baseURI) {
     mDocumentBaseURI = baseURI;
   }
 
   // Store the security info of the caller now that we're done
   // resetting the document.
   mSecurityInfo = securityInfo;
 
+  mParserAborted = false;
   bool loadAsHtml5 = nsHtml5Module::sEnabled;
   if (loadAsHtml5) {
     mParser = nsHtml5Module::NewHtml5Parser();
     rv = NS_OK;
   } else {
     mParser = do_CreateInstance(kCParserCID, &rv);  
   }
 
@@ -1639,18 +1641,18 @@ nsHTMLDocument::Close()
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   if (!mParser || !mParser->IsScriptCreated()) {
     return NS_OK;
   }
 
   ++mWriteLevel;
-  nsresult rv = mParser->Parse(EmptyString(), nsnull,
-                               GetContentTypeInternal(), true);
+  nsresult rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
+    EmptyString(), nsnull, GetContentTypeInternal(), true);
   --mWriteLevel;
 
   // XXX Make sure that all the document.written content is
   // reflowed.  We should remove this call once we change
   // nsHTMLDocument::OpenCommon() so that it completely destroys the
   // earlier document's content and frame hierarchy.  Right now, it
   // re-uses the earlier document's root content object and
   // corresponding frame objects.  These re-used frame objects think
@@ -1696,16 +1698,23 @@ nsHTMLDocument::WriteCommon(JSContext *c
   NS_ENSURE_STATE(!mTooDeepWriteRecursion);
 
   if (!IsHTML() || mDisableDocWrite) {
     // No calling document.write*() on XHTML!
 
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
+  if (mParserAborted) {
+    // Hixie says aborting the parser doesn't undefine the insertion point.
+    // However, since we null out mParser in that case, we track the
+    // theoretically defined insertion point using mParserAborted.
+    return NS_OK;
+  }
+
   nsresult rv = NS_OK;
 
   void *key = GenerateParserKey();
   if (mParser && !mParser->IsInsertionPointDefined()) {
     if (mExternalScriptsBeingEvaluated) {
       // Instead of implying a call to document.open(), ignore the call.
       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                       "DOM Events", this,
@@ -1759,23 +1768,21 @@ nsHTMLDocument::WriteCommon(JSContext *c
 
   ++mWriteLevel;
 
   // This could be done with less code, but for performance reasons it
   // makes sense to have the code for two separate Parse() calls here
   // since the concatenation of strings costs more than we like. And
   // why pay that price when we don't need to?
   if (aNewlineTerminate) {
-    rv = mParser->Parse(aText + new_line,
-                        key, GetContentTypeInternal(),
-                        false);
+    rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
+      aText + new_line, key, GetContentTypeInternal(), false);
   } else {
-    rv = mParser->Parse(aText,
-                        key, GetContentTypeInternal(),
-                        false);
+    rv = (static_cast<nsHtml5Parser*>(mParser.get()))->Parse(
+      aText, key, GetContentTypeInternal(), false);
   }
 
   --mWriteLevel;
 
   mTooDeepWriteRecursion = (mWriteLevel != 0 && mTooDeepWriteRecursion);
 
   return rv;
 }
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -8343,23 +8343,16 @@ nsDocShell::InternalLoad(nsIURI * aURI,
         // that history.go(0) and the like trigger full refreshes, rather than
         // short-circuited loads.
         bool doShortCircuitedLoad =
           (historyNavBetweenSameDoc && mOSHE != aSHEntry) ||
           (!aSHEntry && aPostData == nsnull &&
            sameExceptHashes && !newHash.IsEmpty());
 
         if (doShortCircuitedLoad) {
-            // If our load group contains a LOAD_DOCUMENT_URI request with a
-            // channel which doesn't match our document's channel, cancel it.
-            //
-            // That is, a short-circuited load will cancel a non-short-circuited
-            // load of a different document.
-            StopOutstandingOtherDocumentLoad();
-
             // Save the current URI; we need it if we fire a hashchange later.
             nsCOMPtr<nsIURI> oldURI = mCurrentURI;
 
             // Save the position of the scrollers.
             nscoord cx = 0, cy = 0;
             GetCurScrollPos(ScrollOrientation_X, &cx);
             GetCurScrollPos(ScrollOrientation_Y, &cy);
 
@@ -8649,57 +8642,16 @@ nsDocShell::InternalLoad(nsIURI * aURI,
     if (NS_FAILED(rv)) {
         nsCOMPtr<nsIChannel> chan(do_QueryInterface(req));
         DisplayLoadError(rv, aURI, nsnull, chan);
     }
 
     return rv;
 }
 
-// If our load group contains a LOAD_DOCUMENT_URI channel that's not our
-// document's channel, cancel it.
-void
-nsDocShell::StopOutstandingOtherDocumentLoad()
-{
-    nsCOMPtr<nsIChannel> docChannel = GetCurrentDocChannel();
-    if (!docChannel || !mLoadGroup) {
-        return;
-    }
-
-    nsCOMPtr<nsISimpleEnumerator> requests;
-    mLoadGroup->GetRequests(getter_AddRefs(requests));
-    if (!requests) {
-        return;
-    }
-
-    while (true) {
-        bool hasMoreElements = false;
-        requests->HasMoreElements(&hasMoreElements);
-        if (!hasMoreElements) {
-            break;
-        }
-
-        nsCOMPtr<nsISupports> next;
-        requests->GetNext(getter_AddRefs(next));
-
-        nsCOMPtr<nsIChannel> channel = do_QueryInterface(next);
-        if (!channel) {
-            continue;
-        }
-
-        nsLoadFlags flags;
-        channel->GetLoadFlags(&flags);
-
-        // As promised, cancel the channel if it's loading a different document.
-        if ((flags & nsIChannel::LOAD_DOCUMENT_URI) && channel != docChannel) {
-            channel->Cancel(NS_BINDING_ABORTED);
-        }
-    }
-}
-
 nsIPrincipal*
 nsDocShell::GetInheritedPrincipal(bool aConsiderCurrentDocument)
 {
     nsCOMPtr<nsIDocument> document;
     bool inheritedFromCurrent = false;
 
     if (aConsiderCurrentDocument && mContentViewer) {
         document = mContentViewer->GetDocument();
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -667,21 +667,16 @@ protected:
     // helpers for executing commands
     nsresult GetControllerForCommand(const char *inCommand,
                                      nsIController** outController);
     nsresult IsCommandEnabled(const char * inCommand, bool* outEnabled);
     nsresult DoCommand(const char * inCommand);
     nsresult EnsureCommandHandler();
 
     nsIChannel* GetCurrentDocChannel();
-
-    // If our load group contains a LOAD_DOCUMENT_URI channel that's not our
-    // document's channel, cancel it.
-    void StopOutstandingOtherDocumentLoad();
-
 protected:
     // Override the parent setter from nsDocLoader
     virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader);
 
     void ClearFrameHistory(nsISHEntry* aEntry);
 
     nsresult MaybeInitTiming();
 
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1148,17 +1148,17 @@ NS_IMETHODIMP
 Navigator::GetMozBluetooth(nsIDOMBluetoothAdapter** aBluetooth)
 {
   nsCOMPtr<nsIDOMBluetoothAdapter> bluetooth = mBluetooth;
 
   if (!bluetooth) {
     nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
     NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
-    mBluetooth = new bluetooth::BluetoothAdapter();
+    mBluetooth = new bluetooth::BluetoothAdapter(window);
 
     bluetooth = mBluetooth;
   }
 
   bluetooth.forget(aBluetooth);
   return NS_OK;
 }
 #endif //MOZ_B2G_BT
--- a/dom/base/nsStructuredCloneContainer.cpp
+++ b/dom/base/nsStructuredCloneContainer.cpp
@@ -80,16 +80,17 @@ nsStructuredCloneContainer::InitFromVari
   jsval jsData;
   nsresult rv = aData->GetAsJSVal(&jsData);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_UNEXPECTED);
 
   // Make sure that we serialize in the right context.
   JSAutoRequest ar(aCx);
   JSAutoEnterCompartment ac;
   NS_ENSURE_STATE(ac.enter(aCx, JS_GetGlobalObject(aCx)));
+  JS_WrapValue(aCx, &jsData);
 
   nsCxPusher cxPusher;
   cxPusher.Push(aCx);
 
   uint64_t* jsBytes = nsnull;
   bool success = JS_WriteStructuredClone(aCx, jsData, &jsBytes, &mSize,
                                            nsnull, nsnull);
   NS_ENSURE_STATE(success);
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -1,21 +1,41 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=40: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "BluetoothAdapter.h"
+
 #include "nsDOMClassInfo.h"
 #include "nsDOMEvent.h"
 #include "nsThreadUtils.h"
 #include "nsXPCOMCIDInternal.h"
 #include "mozilla/LazyIdleThread.h"
+#include "mozilla/Util.h"
 #include <dlfcn.h>
-#include "BluetoothAdapter.h"
+
+static void
+FireEnabled(bool aResult, nsIDOMDOMRequest* aDomRequest)
+{
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+
+  if (!rs) {
+    NS_WARNING("No DOMRequest Service!");
+    return;
+  }
+
+  mozilla::DebugOnly<nsresult> rv = aResult ?     
+                                    rs->FireSuccess(aDomRequest, JSVAL_VOID) :
+                                    rs->FireError(aDomRequest, 
+                                                  NS_LITERAL_STRING("Bluetooth firmware loading failed"));
+
+  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Bluetooth firmware loading failed");
+}
 
 USING_BLUETOOTH_NAMESPACE
 
 static struct BluedroidFunctions {
   bool initialized;
   bool tried_initialization;
 
   BluedroidFunctions() :
@@ -62,178 +82,169 @@ static bool EnsureBluetoothInit() {
   }
   sBluedroidFunctions.initialized = true;
   return true;
 }
 
 class ToggleBtResultTask : public nsRunnable
 {
   public:
-    ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr, bool result)
-      : mResult(result)
+    ToggleBtResultTask(nsRefPtr<BluetoothAdapter>& adapterPtr, 
+                       nsCOMPtr<nsIDOMDOMRequest>& req,
+                       bool enabled,
+                       bool result)
+      : mResult(result),
+        mEnabled(enabled)
     {
       MOZ_ASSERT(!NS_IsMainThread());
 
+      mDOMRequest.swap(req);
       mAdapterPtr.swap(adapterPtr);
     }
 
     NS_IMETHOD Run() 
     {
       MOZ_ASSERT(NS_IsMainThread());
 
-      if (!mResult) {
-        //TODO:Bug-731361
-        NS_WARNING("BT firmware loading fails.\n");
+      // Update bt power status to BluetoothAdapter only if loading bluetooth 
+      // firmware succeeds.
+      if (mResult) {
+        mAdapterPtr->SetEnabledInternal(mEnabled);
       }
- 
+
+      FireEnabled(mResult, mDOMRequest);
+
       //mAdapterPtr must be null before returning to prevent the background 
       //thread from racing to release it during the destruction of this runnable.
-      mAdapterPtr->FirePowered();
       mAdapterPtr = nsnull;
+      mDOMRequest = nsnull;
 
       return NS_OK;
     }
 
   private:
     nsRefPtr<BluetoothAdapter> mAdapterPtr;
+    nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
+    bool mEnabled;
     bool mResult;
 };
 
 class ToggleBtTask : public nsRunnable
 {
   public:
-    ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
-      : mOnOff(onOff),
+    ToggleBtTask(bool enabled, nsIDOMDOMRequest* req, BluetoothAdapter* adapterPtr)
+      : mEnabled(enabled),
+        mDOMRequest(req),
         mAdapterPtr(adapterPtr) 
     {
       MOZ_ASSERT(NS_IsMainThread());
     }
 
     NS_IMETHOD Run() 
     {
       MOZ_ASSERT(!NS_IsMainThread());
 
+      bool result;
+
+#ifdef MOZ_WIDGET_GONK
+      // Platform specific check for gonk until object is divided in
+      // different implementations per platform. Linux doesn't require
+      // bluetooth firmware loading, but code should work otherwise.
       if(!EnsureBluetoothInit()) {
         NS_ERROR("Failed to load bluedroid library.\n");
         return NS_ERROR_FAILURE;
       }
 
-      bool result;
-
-      //Toggle BT here
+      // return 1 if it's enabled, 0 if it's disabled, and -1 on error
+      int isEnabled = sBluedroidFunctions.bt_is_enabled();
 
-      if (mOnOff) {
-        result = sBluedroidFunctions.bt_enable();
+      if ((isEnabled == 1 && mEnabled) || (isEnabled == 0 && !mEnabled)) {
+        result = true;
+      } else if (isEnabled < 0) {
+        result = false;
+      } else if (mEnabled) {
+        result = (sBluedroidFunctions.bt_enable() == 0) ? true : false;
       } else {
-        result = sBluedroidFunctions.bt_disable();
+        result = (sBluedroidFunctions.bt_disable() == 0) ? true : false;
       }
+#else
+      result = true;
+      NS_WARNING("No bluetooth support in this build configuration, faking a success event instead");
+#endif
 
       // Create a result thread and pass it to Main Thread, 
-      nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, result);
+      nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(mAdapterPtr, mDOMRequest, mEnabled, result);
 
       if (NS_FAILED(NS_DispatchToMainThread(resultRunnable))) {
         NS_WARNING("Failed to dispatch to main thread!");
       }
 
       return NS_OK;
     }
 
   private:
-    bool mOnOff;
+    bool mEnabled;
     nsRefPtr<BluetoothAdapter> mAdapterPtr;
+    nsCOMPtr<nsIDOMDOMRequest> mDOMRequest;
 };
 
 DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter, 
                                                   nsDOMEventTargetHelper)
-  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(enabled)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter, 
                                                 nsDOMEventTargetHelper)
-  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(enabled)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
   NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
 
-BluetoothAdapter::BluetoothAdapter() 
-  : mPower(false)
+BluetoothAdapter::BluetoothAdapter(nsPIDOMWindow *aWindow) 
 {
+  BindToOwner(aWindow);
 }
 
 NS_IMETHODIMP
-BluetoothAdapter::GetPower(bool* aPower)
+BluetoothAdapter::SetEnabled(bool aEnabled, nsIDOMDOMRequest** aDomRequest)
 {
-#ifdef MOZ_WIDGET_GONK
-  if(!EnsureBluetoothInit()) {
-    NS_ERROR("Failed to load bluedroid library.\n");
+  nsCOMPtr<nsIDOMRequestService> rs = do_GetService("@mozilla.org/dom/dom-request-service;1");
+
+  if (!rs) {
+    NS_ERROR("No DOMRequest Service!");
     return NS_ERROR_FAILURE;
   }
-  *aPower = sBluedroidFunctions.bt_is_enabled();
-#else
-  *aPower = mPower;
-#endif
+
+  nsCOMPtr<nsIDOMDOMRequest> request;
+  nsresult rv = rs->CreateRequest(GetOwner(), getter_AddRefs(request));
+  NS_ENSURE_SUCCESS(rv, rv);
+  
+  if (!mToggleBtThread) {
+    mToggleBtThread = new LazyIdleThread(15000);
+  }
+
+  nsCOMPtr<nsIRunnable> r = new ToggleBtTask(aEnabled, request, this);
+
+  rv = mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  request.forget(aDomRequest);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
-BluetoothAdapter::SetPower(bool aPower)
+BluetoothAdapter::GetEnabled(bool* aEnabled)
 {
-
-#ifdef MOZ_WIDGET_GONK
-  // Platform specific check for gonk until object is divided in
-  // different implementations per platform. Linux doesn't require
-  // bluetooth firmware loading, but code should work otherwise.
-  if(!EnsureBluetoothInit()) {
-    NS_ERROR("Failed to load bluedroid library.\n");
-    return NS_ERROR_FAILURE;
-  }
-#endif
-  if (mPower != aPower) {
-    mPower = aPower;
-
-#ifdef MOZ_WIDGET_GONK
-    return ToggleBluetoothAsync();
-#endif
-  }
-
-  return NS_OK;
+  *aEnabled = mEnabled;
+  return NS_OK; 
 }
 
-nsresult
-BluetoothAdapter::ToggleBluetoothAsync()
-{
-  if (!mToggleBtThread) {
-    mToggleBtThread = new LazyIdleThread(15000);
-  }
-
-  nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this);
-
-  return mToggleBtThread->Dispatch(r, NS_DISPATCH_NORMAL);
-}
-
-nsresult
-BluetoothAdapter::FirePowered()
-{
-  nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
-  nsresult rv = event->InitEvent(NS_LITERAL_STRING("powered"), false, false);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = event->SetTrusted(true);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  bool dummy;
-  rv = DispatchEvent(event, &dummy);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
-NS_IMPL_EVENT_HANDLER(BluetoothAdapter, powered)
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothadapter_h__
 #define mozilla_dom_bluetooth_bluetoothadapter_h__
 
 #include "BluetoothCommon.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIDOMBluetoothAdapter.h"
+#include "nsIDOMDOMRequest.h"
 
 class nsIEventTarget;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothAdapter : public nsIDOMBluetoothAdapter
                        , public nsDOMEventTargetHelper
 {
@@ -22,24 +23,24 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMBLUETOOTHADAPTER
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
                                            nsDOMEventTargetHelper)
 
-  BluetoothAdapter();
+  BluetoothAdapter(nsPIDOMWindow*);
 
-  nsresult FirePowered();
+  inline void SetEnabledInternal(bool aEnabled) {mEnabled = aEnabled;}
 
 protected:
-  bool mPower;
+  bool mEnabled;
 
-  NS_DECL_EVENT_HANDLER(powered)
+  NS_DECL_EVENT_HANDLER(enabled)
 
 private:
   nsCOMPtr<nsIEventTarget> mToggleBtThread;
-  nsresult ToggleBluetoothAsync();
 };
 
 END_BLUETOOTH_NAMESPACE
+
 #endif
--- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl
+++ b/dom/bluetooth/nsIDOMBluetoothAdapter.idl
@@ -1,17 +1,18 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=40: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIDOMEventTarget.idl"
 
+interface nsIDOMDOMRequest;
 interface nsIDOMEventListener;
 
-[scriptable, builtinclass, uuid(3dbaa9f4-5c93-11e1-8592-ff9bfcc3ab4b)]
+[scriptable, builtinclass, uuid(ac288eab-dcdb-4f6a-b94d-6c0e286d6a73)]
 interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
 {
-  attribute boolean power;
+  readonly attribute bool enabled;
 
-  attribute nsIDOMEventListener onpowered;
+  nsIDOMDOMRequest setEnabled(in boolean enabled);
 };
--- a/dom/indexedDB/IDBKeyRange.cpp
+++ b/dom/indexedDB/IDBKeyRange.cpp
@@ -339,16 +339,23 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(IDBKeyRange)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IDBKeyRange)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IDBKeyRange)
 
 DOMCI_DATA(IDBKeyRange, IDBKeyRange)
 
+IDBKeyRange::~IDBKeyRange()
+{
+  if (mRooted) {
+    NS_DROP_JS_OBJECTS(this, IDBKeyRange);
+  }
+}
+
 NS_IMETHODIMP
 IDBKeyRange::GetLower(JSContext* aCx,
                       jsval* aLower)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveCachedLowerVal) {
     if (!mRooted) {
--- a/dom/indexedDB/IDBKeyRange.h
+++ b/dom/indexedDB/IDBKeyRange.h
@@ -165,17 +165,17 @@ public:
       rv = Upper().BindToStatement(aStatement, NS_LITERAL_CSTRING("upper_key"));
       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     }
 
     return NS_OK;
   }
 
 protected:
-  ~IDBKeyRange() { }
+  ~IDBKeyRange();
 
   Key mLower;
   Key mUpper;
   jsval mCachedLowerVal;
   jsval mCachedUpperVal;
   bool mLowerOpen;
   bool mUpperOpen;
   bool mIsOnly;
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -1313,30 +1313,27 @@ DOMStorageImpl::Clear(bool aCallerSecure
   mItems.Clear();
   return NS_OK;
 }
 
 nsDOMStorage::nsDOMStorage()
   : mStorageType(nsPIDOMStorage::Unknown)
   , mEventBroadcaster(nsnull)
 {
-  mSecurityChecker = this;
-
   if (XRE_GetProcessType() != GeckoProcessType_Default)
     mStorageImpl = new StorageChild(this);
   else
     mStorageImpl = new DOMStorageImpl(this);
 }
 
 nsDOMStorage::nsDOMStorage(nsDOMStorage& aThat)
   : mStorageType(aThat.mStorageType)
+  , mPrincipal(aThat.mPrincipal)
   , mEventBroadcaster(nsnull)
 {
-  mSecurityChecker = this;
-
   if (XRE_GetProcessType() != GeckoProcessType_Default) {
     StorageChild* other = static_cast<StorageChild*>(aThat.mStorageImpl.get());
     mStorageImpl = new StorageChild(this, *other);
   } else {
     DOMStorageImpl* other = static_cast<DOMStorageImpl*>(aThat.mStorageImpl.get());
     mStorageImpl = new DOMStorageImpl(this, *other);
   }
 }
@@ -1377,31 +1374,33 @@ GetDomainURI(nsIPrincipal *aPrincipal, b
 nsresult
 nsDOMStorage::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
 {
   nsCOMPtr<nsIURI> domainURI;
   nsresult rv = GetDomainURI(aPrincipal, true, getter_AddRefs(domainURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mDocumentURI = aDocumentURI;
+  mPrincipal = aPrincipal;
 
   mStorageType = SessionStorage;
 
   mStorageImpl->InitAsSessionStorage(domainURI);
   return NS_OK;
 }
 
 nsresult
 nsDOMStorage::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
 {
   nsCOMPtr<nsIURI> domainURI;
   nsresult rv = GetDomainURI(aPrincipal, false, getter_AddRefs(domainURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mDocumentURI = aDocumentURI;
+  mPrincipal = aPrincipal;
 
   mStorageType = LocalStorage;
 
   bool canUseChromePersist = false;
   nsCOMPtr<nsIURI> URI;
   if (NS_SUCCEEDED(aPrincipal->GetURI(getter_AddRefs(URI))) && URI) {
     canUseChromePersist = URICanUseChromePersist(URI);
   }
@@ -1490,18 +1489,17 @@ nsDOMStorage::CacheStoragePermissions()
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
   if (!ssm)
     return false;
 
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
   nsresult rv = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
   NS_ENSURE_SUCCESS(rv, false);
 
-  NS_ASSERTION(mSecurityChecker, "Has non-null mSecurityChecker");
-  return mSecurityChecker->CanAccess(subjectPrincipal);
+  return CanAccess(subjectPrincipal);
 }
 
 // static
 bool
 nsDOMStorage::URICanUseChromePersist(nsIURI* aURI) {
   bool isAbout;
   return
     (NS_SUCCEEDED(aURI->SchemeIs("moz-safe-about", &isAbout)) && isAbout) ||
@@ -1724,27 +1722,27 @@ nsDOMStorage::CanAccessSystem(nsIPrincip
   nsresult rv = ssm->IsSystemPrincipal(aPrincipal, &isSystem);
 
   return NS_SUCCEEDED(rv) && isSystem;
 }
 
 bool
 nsDOMStorage::CanAccess(nsIPrincipal *aPrincipal)
 {
-  // Allow C++/system callers to access the storage
-  if (CanAccessSystem(aPrincipal))
+  // Allow C++ callers to access the storage
+  if (!aPrincipal)
     return true;
 
-  nsCAutoString domain;
-  nsCOMPtr<nsIURI> unused;
-  nsresult rv = GetPrincipalURIAndHost(aPrincipal,
-                                       getter_AddRefs(unused), domain);
-  NS_ENSURE_SUCCESS(rv, false);
-
-  return domain.Equals(mStorageImpl->mDomain);
+  // Allow more powerful principals (e.g. system) to access the storage
+  bool subsumes;
+  nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
+  if (NS_FAILED(rv))
+    return false;
+
+  return subsumes;
 }
 
 nsPIDOMStorage::nsDOMStorageType
 nsDOMStorage::StorageType()
 {
   return mStorageType;
 }
 
@@ -1792,42 +1790,39 @@ NS_INTERFACE_MAP_END
 
 nsDOMStorage2::nsDOMStorage2()
 {
 }
 
 nsDOMStorage2::nsDOMStorage2(nsDOMStorage2& aThat)
 {
   mStorage = new nsDOMStorage(*aThat.mStorage.get());
-  mStorage->mSecurityChecker = mStorage;
   mPrincipal = aThat.mPrincipal;
 }
 
 nsresult
 nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
 {
   mStorage = new nsDOMStorage();
   if (!mStorage)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  mStorage->mSecurityChecker = this;
   mPrincipal = aPrincipal;
   mDocumentURI = aDocumentURI;
 
   return mStorage->InitAsSessionStorage(aPrincipal, aDocumentURI);
 }
 
 nsresult
 nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
 {
   mStorage = new nsDOMStorage();
   if (!mStorage)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  mStorage->mSecurityChecker = this;
   mPrincipal = aPrincipal;
   mDocumentURI = aDocumentURI;
 
   return mStorage->InitAsLocalStorage(aPrincipal, aDocumentURI);
 }
 
 already_AddRefed<nsIDOMStorage>
 nsDOMStorage2::Clone()
@@ -1887,30 +1882,17 @@ nsIPrincipal*
 nsDOMStorage2::Principal()
 {
   return mPrincipal;
 }
 
 bool
 nsDOMStorage2::CanAccess(nsIPrincipal *aPrincipal)
 {
-  if (mStorage->mSecurityChecker != this)
-    return mStorage->mSecurityChecker->CanAccess(aPrincipal);
-
-  // Allow C++ callers to access the storage
-  if (!aPrincipal)
-    return true;
-
-  // Allow more powerful principals (e.g. system) to access the storage
-  bool subsumes;
-  nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
-  if (NS_FAILED(rv))
-    return false;
-
-  return subsumes;
+  return mStorage->CanAccess(aPrincipal);
 }
 
 nsPIDOMStorage::nsDOMStorageType
 nsDOMStorage2::StorageType()
 {
   if (mStorage)
     return mStorage->StorageType();
 
--- a/dom/src/storage/nsDOMStorage.h
+++ b/dom/src/storage/nsDOMStorage.h
@@ -414,17 +414,17 @@ public:
 
   // true if this storage was initialized as a localStorage object.  localStorage
   // objects are scoped to scheme/host/port in the database, while globalStorage
   // objects are scoped just to host.  this flag also tells the manager to map
   // this storage also in mLocalStorages hash table.
   nsDOMStorageType mStorageType;
 
   friend class nsIDOMStorage2;
-  nsPIDOMStorage* mSecurityChecker;
+  nsCOMPtr<nsIPrincipal> mPrincipal;
   nsPIDOMStorage* mEventBroadcaster;
 };
 
 class nsDOMStorage2 : public nsIDOMStorage,
                       public nsPIDOMStorage
 {
 public:
   // nsISupports
--- a/dom/tests/mochitest/ajax/lib/AJAX_setup.js
+++ b/dom/tests/mochitest/ajax/lib/AJAX_setup.js
@@ -3,17 +3,17 @@ var AJAXtests = [];
 function runAJAXTest() {
   if (AJAXtests.length == 0) {
     SimpleTest.finish();
     return;
   }
 
   var test = AJAXtests.shift();
   var testframe = document.getElementById("testframe");
-  setTimeout(function() { testframe.src = test; }, 0);
+  testframe.src = test;
 }
 
 function onManifestLoad(manifest) {
   if (manifest.testcases) {
     AJAXtests = manifest.testcases;
     runAJAXTest();    
   } else {
     ok(false, "manifest check", "no manifest!?!");
--- a/dom/workers/EventTarget.cpp
+++ b/dom/workers/EventTarget.cpp
@@ -64,17 +64,17 @@ namespace {
 
 DECL_EVENTTARGET_CLASS(gClass, "EventTarget")
 DECL_EVENTTARGET_CLASS(gMainThreadClass, "WorkerEventTarget")
 
 #undef DECL_EVENTTARGET_CLASS
 
 inline
 bool
-EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, char* aFunctionName)
+EnsureObjectIsEventTarget(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
 {
   JSClass* classPtr = JS_GetClass(aObj);
   if (ClassIsWorker(classPtr) || ClassIsWorkerGlobalScope(classPtr) ||
       ClassIsXMLHttpRequest(classPtr)) {
     return true;
   }
 
   JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -3159,35 +3159,43 @@ WorkerPrivate::NotifyFeatures(JSContext*
       NS_WARNING("Failed to notify child worker!");
     }
   }
 }
 
 void
 WorkerPrivate::CancelAllTimeouts(JSContext* aCx)
 {
+  AssertIsOnWorkerThread();
+
   if (mTimerRunning) {
     NS_ASSERTION(mTimer, "Huh?!");
     NS_ASSERTION(!mTimeouts.IsEmpty(), "Huh?!");
 
     if (NS_FAILED(mTimer->Cancel())) {
       NS_WARNING("Failed to cancel timer!");
     }
 
     for (PRUint32 index = 0; index < mTimeouts.Length(); index++) {
       mTimeouts[index]->mCanceled = true;
     }
 
-    RunExpiredTimeouts(aCx);
-
-    mTimer = nsnull;
+    if (!RunExpiredTimeouts(aCx)) {
+      JS_ReportPendingException(aCx);
+    }
+
+    mTimerRunning = false;
   }
-  else {
+#ifdef DEBUG
+  else if (!mRunningExpiredTimeouts) {
     NS_ASSERTION(mTimeouts.IsEmpty(), "Huh?!");
   }
+#endif
+
+  mTimer = nsnull;
 }
 
 PRUint32
 WorkerPrivate::CreateNewSyncLoop()
 {
   AssertIsOnWorkerThread();
 
   NS_ASSERTION(mSyncQueues.Length() < PR_UINT32_MAX,
@@ -3506,18 +3514,25 @@ WorkerPrivate::SetTimeout(JSContext* aCx
   const PRUint32 timerId = mNextTimeoutId++;
 
   Status currentStatus;
   {
     MutexAutoLock lock(mMutex);
     currentStatus = mStatus;
   }
 
-  if (currentStatus > Running) {
+  // It's a script bug if setTimeout/setInterval are called from a close handler
+  // so throw an exception.
+  if (currentStatus == Closing) {
     JS_ReportError(aCx, "Cannot schedule timeouts from the close handler!");
+  }
+
+  // If the worker is trying to call setTimeout/setInterval and the parent
+  // thread has initiated the close process then just silently fail.
+  if (currentStatus >= Closing) {
     return false;
   }
 
   nsAutoPtr<TimeoutInfo> newInfo(new TimeoutInfo());
   newInfo->mIsInterval = aIsInterval;
   newInfo->mId = timerId;
 
   if (NS_UNLIKELY(timerId == PR_UINT32_MAX)) {
@@ -3650,16 +3665,17 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
 
   // We may be called recursively (e.g. close() inside a timeout) or we could
   // have been canceled while this event was pending, bail out if there is
   // nothing to do.
   if (mRunningExpiredTimeouts || !mTimerRunning) {
     return true;
   }
 
+  NS_ASSERTION(mTimer, "Must have a timer!");
   NS_ASSERTION(!mTimeouts.IsEmpty(), "Should have some work to do!");
 
   bool retval = true;
 
   AutoPtrComparator<TimeoutInfo> comparator = GetAutoPtrComparator(mTimeouts);
   JSObject* global = JS_GetGlobalObject(aCx);
   JSPrincipals* principal = GetWorkerPrincipal();
 
@@ -3714,22 +3730,26 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
                                 info->mExtraArgVals.Length(),
                                 info->mExtraArgVals.Elements(), &rval) &&
           !JS_ReportPendingException(aCx)) {
         retval = false;
         break;
       }
     }
 
+    NS_ASSERTION(mRunningExpiredTimeouts, "Someone changed this!");
+
     // Reschedule intervals.
-    if (info->mIsInterval) {
+    if (info->mIsInterval && !info->mCanceled) {
       PRUint32 timeoutIndex = mTimeouts.IndexOf(info);
       NS_ASSERTION(timeoutIndex != PRUint32(-1),
                    "Should still be in the main list!");
 
+      // This is nasty but we have to keep the old nsAutoPtr from deleting the
+      // info we're about to re-add.
       mTimeouts[timeoutIndex].forget();
       mTimeouts.RemoveElementAt(timeoutIndex);
 
       NS_ASSERTION(!mTimeouts.Contains(info), "Shouldn't have duplicates!");
 
       // NB: We must ensure that info->mTargetTime > now (where now is the
       // now above, not literally TimeStamp::Now()) or we will remove the
       // interval in the next loop below.
@@ -3750,18 +3770,18 @@ WorkerPrivate::RunExpiredTimeouts(JSCont
                    "Interval timers can only be removed when canceled!");
       mTimeouts.RemoveElement(info);
     }
     else {
       index++;
     }
   }
 
-  // Signal the parent that we're no longer using timeouts or reschedule the
-  // timer.
+  // Either signal the parent that we're no longer using timeouts or reschedule
+  // the timer.
   if (mTimeouts.IsEmpty()) {
     if (!ModifyBusyCountFromWorker(aCx, false)) {
       retval = false;
     }
     mTimerRunning = false;
   }
   else if (retval && !RescheduleTimeoutTimer(aCx)) {
     retval = false;
--- a/dom/workers/test/Makefile.in
+++ b/dom/workers/test/Makefile.in
@@ -51,16 +51,18 @@ DIRS = \
 
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = \
   test_404.html \
   test_atob.html \
   atob_worker.js \
   test_blobWorkers.html \
+  test_clearTimeouts.html \
+  clearTimeouts_worker.js \
   test_close.html \
   close_worker.js \
   test_closeOnGC.html \
   closeOnGC_worker.js \
   closeOnGC_server.sjs \
   test_dataURLWorker.html \
   test_errorPropagation.html \
   errorPropagation_iframe.html \
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/clearTimeouts_worker.js
@@ -0,0 +1,12 @@
+var count = 0;
+function timerFunction() {
+  if (++count == 30) {
+    close();
+    postMessage("ready");
+    while (true) { }
+  }
+}
+
+for (var i = 0; i < 10; i++) {
+  setInterval(timerFunction, 500);
+}
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/test_clearTimeouts.html
@@ -0,0 +1,30 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for DOM Worker Threads</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+  new Worker("clearTimeouts_worker.js").onmessage = function(event) {
+    event.target.terminate();
+
+    is(event.data, "ready", "Correct message");
+    setTimeout(function() { SimpleTest.finish(); }, 1000);
+  }
+
+  SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
--- a/editor/libeditor/text/tests/Makefile.in
+++ b/editor/libeditor/text/tests/Makefile.in
@@ -60,17 +60,16 @@ include $(topsrcdir)/config/rules.mk
 		test_bug604532.html \
 		test_bug625452.html \
 		test_bug629172.html \
 		test_bug638596.html \
 		test_bug641466.html \
 		test_bug645914.html \
 		test_bug681229.html \
 		test_bug692520.html \
-		test_bug717147.html \
 		test_dom_input_event_on_texteditor.html \
 		$(NULL)
 
 # disables the key handling test on gtk2 because gtk2 overrides some key events
 # on our editor, and the combinations depend on the system.
 ifneq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 _TEST_FILES += \
 		test_texteditor_keyevent_handling.html \
deleted file mode 100644
--- a/editor/libeditor/text/tests/test_bug717147.html
+++ /dev/null
@@ -1,99 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=717147
--->
-<head>
-  <title>Test for Bug 717147</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717147">Mozilla Bug 717147</a>
-<p id="display"></p>
-<div id="content">
-  <iframe id="formTarget" name="formTarget"></iframe>
-  <form action="data:text/html," target="formTarget">
-    <input name="test" id="initValue"><input type="submit">
-  </form>
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 717147 **/
-SimpleTest.waitForExplicitFinish();
-SimpleTest.waitForFocus(function() {
-  var formTarget = document.getElementById("formTarget");
-  var initValue = document.getElementById("initValue");
-
-  formTarget.addEventListener("load", function() {
-    var newInput = document.createElement("input");
-    newInput.setAttribute("name", "test");
-    document.body.appendChild(newInput);
-
-    setTimeout(function() {
-      var popupShown = false;
-      function listener() {
-        popupShown = true;
-      }
-      SpecialPowers.addAutoCompletePopupEventListener(window, listener);
-
-      newInput.value = "";
-      newInput.focus();
-
-      synthesizeComposition({ type: "compositionstart" });
-      synthesizeComposition({ type: "compositionupdate", data: "f" });
-      synthesizeText(
-        { "composition":
-          { "string": "f",
-            "clauses":
-            [
-              { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
-            ]
-          },
-          "caret": { "start": 1, "length": 0 }
-        });
-
-      hitEventLoop(function() {
-        ok(!popupShown, "Popup must not be opened during composition");
-
-        synthesizeText(
-          { "composition":
-            { "string": "f",
-              "clauses":
-              [
-                { "length": 0, "attr": 0 }
-              ]
-            },
-            "caret": { "start": 1, "length": 0 }
-          });
-        synthesizeComposition({ type: "compositionend", data: "f" });
-
-        hitEventLoop(function () {
-          ok(popupShown, "Popup must be opened after compositionend");
-
-          SpecialPowers.removeAutoCompletePopupEventListener(window, listener);
-          SimpleTest.finish();
-        }, 100);
-      }, 100);
-    }, 0);
-  }, false);
-
-  initValue.focus();
-  initValue.value = "foo";
-  synthesizeKey("VK_ENTER", {});
-});
-
-function hitEventLoop(func, times) {
-  if (times > 0) {
-    setTimeout(hitEventLoop, 0, func, times - 1);
-  } else {
-    setTimeout(func, 0);
-  }
-}
-
-</script>
-</pre>
-</body>
-</html>
--- a/embedding/components/find/src/nsFind.cpp
+++ b/embedding/components/find/src/nsFind.cpp
@@ -50,23 +50,23 @@
 #include "nsITextControlFrame.h"
 #include "nsIFormControl.h"
 #include "nsIEditor.h"
 #include "nsIPlaintextEditor.h"
 #include "nsIDocument.h"
 #include "nsTextFragment.h"
 #include "nsString.h"
 #include "nsIAtom.h"
-#include "nsParserCIID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsIDOMElement.h"
 #include "nsIWordBreaker.h"
 #include "nsCRT.h"
 #include "nsRange.h"
+#include "nsContentUtils.h"
 
 // Yikes!  Casting a char to unichar can fill with ones!
 #define CHAR_TO_UNICHAR(c) ((PRUnichar)(const unsigned char)c)
 
 static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
 static NS_DEFINE_CID(kCPreContentIteratorCID, NS_PRECONTENTITERATOR_CID);
 
 #define CH_SHY ((PRUnichar) 0xAD)
@@ -452,63 +452,27 @@ NS_NewFindContentIterator(bool aFindBack
   nsFindContentIterator* it = new nsFindContentIterator(aFindBackward);
   if (!it) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return it->QueryInterface(NS_GET_IID(nsIContentIterator), (void **)aResult);
 }
 // --------------------------------------------------------------------
 
-// Sure would be nice if we could just get these from somewhere else!
-PRInt32 nsFind::sInstanceCount = 0;
-nsIAtom* nsFind::sImgAtom = nsnull;
-nsIAtom* nsFind::sHRAtom = nsnull;
-nsIAtom* nsFind::sScriptAtom = nsnull;
-nsIAtom* nsFind::sNoframesAtom = nsnull;
-nsIAtom* nsFind::sSelectAtom = nsnull;
-nsIAtom* nsFind::sTextareaAtom = nsnull;
-nsIAtom* nsFind::sThAtom = nsnull;
-nsIAtom* nsFind::sTdAtom = nsnull;
-
 NS_IMPL_ISUPPORTS1(nsFind, nsIFind)
 
 nsFind::nsFind()
   : mFindBackward(false)
   , mCaseSensitive(false)
   , mIterOffset(0)
 {
-  // Initialize the atoms if they aren't already:
-  if (sInstanceCount <= 0)
-  {
-    sImgAtom = NS_NewAtom("img");
-    sHRAtom = NS_NewAtom("hr");
-    sScriptAtom = NS_NewAtom("script");
-    sNoframesAtom = NS_NewAtom("noframes");
-    sSelectAtom = NS_NewAtom("select");
-    sTextareaAtom = NS_NewAtom("textarea");
-    sThAtom = NS_NewAtom("th");
-    sTdAtom = NS_NewAtom("td");
-  }
-  ++sInstanceCount;
 }
 
 nsFind::~nsFind()
 {
-  if (sInstanceCount <= 1)
-  {
-    NS_IF_RELEASE(sImgAtom);
-    NS_IF_RELEASE(sHRAtom);
-    NS_IF_RELEASE(sScriptAtom);
-    NS_IF_RELEASE(sNoframesAtom);
-    NS_IF_RELEASE(sSelectAtom);
-    NS_IF_RELEASE(sTextareaAtom);
-    NS_IF_RELEASE(sThAtom);
-    NS_IF_RELEASE(sTdAtom);
-  }
-  --sInstanceCount;
 }
 
 #ifdef DEBUG_FIND
 static void DumpNode(nsIDOMNode* aNode)
 {
   if (!aNode)
   {
     printf(">>>> Node: NULL\n");
@@ -775,31 +739,23 @@ nsFind::NextNode(nsIDOMRange* aSearchRan
 bool nsFind::IsBlockNode(nsIContent* aContent)
 {
   if (!aContent->IsHTML()) {
     return false;
   }
 
   nsIAtom *atom = aContent->Tag();
 
-  if (atom == sImgAtom ||
-      atom == sHRAtom ||
-      atom == sThAtom ||
-      atom == sTdAtom)
+  if (atom == nsGkAtoms::img ||
+      atom == nsGkAtoms::hr ||
+      atom == nsGkAtoms::th ||
+      atom == nsGkAtoms::td)
     return true;
 
-  if (!mParserService) {
-    mParserService = do_GetService(NS_PARSERSERVICE_CONTRACTID);
-    if (!mParserService)
-      return false;
-  }
-
-  bool isBlock = false;
-  mParserService->IsBlock(mParserService->HTMLAtomTagToId(atom), isBlock);
-  return isBlock;
+  return nsContentUtils::IsHTMLBlock(atom);
 }
 
 bool nsFind::IsTextNode(nsIDOMNode* aNode)
 {
   PRUint16 nodeType;
   aNode->GetNodeType(&nodeType);
 
   return nodeType == nsIDOMNode::TEXT_NODE ||
@@ -844,19 +800,19 @@ bool nsFind::SkipNode(nsIContent* aConte
 
   nsIContent *content = aContent;
   while (content)
   {
     atom = content->Tag();
 
     if (aContent->IsNodeOfType(nsINode::eCOMMENT) ||
         (content->IsHTML() &&
-         (atom == sScriptAtom ||
-          atom == sNoframesAtom ||
-          atom == sSelectAtom)))
+         (atom == nsGkAtoms::script ||
+          atom == nsGkAtoms::noframes ||
+          atom == nsGkAtoms::select)))
     {
 #ifdef DEBUG_FIND
       printf("Skipping node: ");
       nsCOMPtr<nsIDOMNode> node (do_QueryInterface(content));
       DumpNode(node);
 #endif
 
       return true;
--- a/embedding/components/find/src/nsFind.h
+++ b/embedding/components/find/src/nsFind.h
@@ -40,17 +40,16 @@
 #define nsFind_h__
 
 #include "nsIFind.h"
 
 #include "nsCOMPtr.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMRange.h"
 #include "nsIContentIterator.h"
-#include "nsIParserService.h"
 #include "nsIWordBreaker.h"
 
 class nsIAtom;
 class nsIContent;
 
 #define NS_FIND_CONTRACTID "@mozilla.org/embedcomp/rangefind;1"
 
 #define NS_FIND_CID \
@@ -65,36 +64,22 @@ public:
   NS_DECL_NSIFIND
 
   nsFind();
   virtual ~nsFind();
 
   static already_AddRefed<nsIDOMRange> CreateRange();
 
 protected:
-  static PRInt32 sInstanceCount;
-
-  // HTML tags we treat specially
-  static nsIAtom* sImgAtom;
-  static nsIAtom* sHRAtom;
-  // Nodes we skip
-  static nsIAtom* sScriptAtom;
-  static nsIAtom* sNoframesAtom;
-  static nsIAtom* sSelectAtom;
-  static nsIAtom* sTextareaAtom;
-  static nsIAtom* sThAtom;
-  static nsIAtom* sTdAtom;
-
   // Parameters set from the interface:
   //nsCOMPtr<nsIDOMRange> mRange;   // search only in this range
   bool mFindBackward;
   bool mCaseSensitive;
 
   nsCOMPtr<nsIWordBreaker> mWordBreaker;
-  nsCOMPtr<nsIParserService> mParserService;
 
   PRInt32 mIterOffset;
   nsCOMPtr<nsIDOMNode> mIterNode;
 
   // Last block parent, so that we will notice crossing block boundaries:
   nsCOMPtr<nsIDOMNode> mLastBlockParent;
   nsresult GetBlockParent(nsIDOMNode* aNode, nsIDOMNode** aParent);
 
--- a/gfx/thebes/Makefile.in
+++ b/gfx/thebes/Makefile.in
@@ -45,16 +45,18 @@ LIBRARY_NAME	= thebes
 LIBXUL_LIBRARY	= 1
 EXPORT_LIBRARY	= 1
 
 EXPORTS	= \
         gfx2DGlue.h \
 	gfx3DMatrix.h \
 	gfxASurface.h \
 	gfxAlphaRecovery.h \
+	gfxAtomList.h \
+	gfxAtoms.h \
 	gfxBlur.h \
 	gfxCachedTempSurface.h \
 	gfxColor.h \
 	gfxContext.h \
 	gfxDrawable.h \
 	gfxFailure.h \
 	gfxFont.h \
 	gfxFontConstants.h \
--- a/gfx/thebes/gfxAtomList.h
+++ b/gfx/thebes/gfxAtomList.h
@@ -90,8 +90,14 @@ GFX_ATOM(x_tibt, "x-tibt")
 
 // used in gfxGDIFontList.h
 GFX_ATOM(ko_xxx, "ko-xxx")
 GFX_ATOM(x_central_euro, "x-central-euro")
 GFX_ATOM(x_symbol, "x-symbol")
 
 // referenced in all.js
 GFX_ATOM(x_user_def, "x-user-def")
+
+// additional languages that use Turkish-style case transformation
+GFX_ATOM(az, "az")
+GFX_ATOM(ba, "ba")
+GFX_ATOM(crh, "crh")
+GFX_ATOM(tt, "tt")
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -244,16 +244,33 @@ gfxDWriteFontFamily::LocalizedName(nsASt
     hr = names->GetString(idx, famName.Elements(), length + 1);
     if (FAILED(hr)) {
         return;
     }
 
     aLocalizedName = nsDependentString(famName.Elements());
 }
 
+void
+gfxDWriteFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                         FontListSizes*    aSizes) const
+{
+    gfxFontFamily::SizeOfExcludingThis(aMallocSizeOf, aSizes);
+    // TODO:
+    // This doesn't currently account for |mDWFamily|
+}
+
+void
+gfxDWriteFontFamily::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                         FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // gfxDWriteFontEntry
 
 gfxDWriteFontEntry::~gfxDWriteFontEntry()
 {
 }
 
 bool
@@ -372,17 +389,18 @@ gfxDWriteFontEntry::ReadCMAP()
         PRUint8 *cmap = buffer.Elements();
 
         bool          unicodeFont = false, symbolFont = false;
         rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
                                     mCharacterMap, mUVSOffset,
                                     unicodeFont, symbolFont);
 #ifdef PR_LOGGING
         LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
-                      NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
+                      NS_ConvertUTF16toUTF8(mName).get(),
+                      mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
         if (LOG_CMAPDATA_ENABLED()) {
             char prefix[256];
             sprintf(prefix, "(cmapdata) name: %.220s",
                     NS_ConvertUTF16toUTF8(mName).get());
             mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
         }
 #endif
         mHasCmapTable = NS_SUCCEEDED(rv);
@@ -419,17 +437,18 @@ gfxDWriteFontEntry::ReadCMAP()
                                     mUVSOffset,
                                     isUnicode,
                                     isSymbol);
     }
     fontFace->ReleaseFontTable(tableContext);
 
 #ifdef PR_LOGGING
     LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
-                  NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
+                  NS_ConvertUTF16toUTF8(mName).get(),
+                  mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
     if (LOG_CMAPDATA_ENABLED()) {
         char prefix[256];
         sprintf(prefix, "(cmapdata) name: %.220s",
                 NS_ConvertUTF16toUTF8(mName).get());
         mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
     }
 #endif
 
@@ -539,16 +558,33 @@ gfxDWriteFontEntry::IsCJKFont()
         if ((PRUint32(os2->codePageRange1) & CJK_CODEPAGE_BITS) != 0) {
             mIsCJK = true;
         }
     }
 
     return mIsCJK;
 }
 
+void
+gfxDWriteFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                        FontListSizes*    aSizes) const
+{
+    gfxFontEntry::SizeOfExcludingThis(aMallocSizeOf, aSizes);
+    // TODO:
+    // This doesn't currently account for the |mFont| and |mFontFile| members
+}
+
+void
+gfxDWriteFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                        FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // gfxDWriteFontList
 
 gfxDWriteFontList::gfxDWriteFontList()
     : mInitialized(false), mForceGDIClassicMaxFontSize(0.0)
 {
     mFontSubstitutes.Init();
 }
@@ -582,27 +618,26 @@ gfxDWriteFontList::GetDefaultFont(const 
 
     return nsnull;
 }
 
 gfxFontEntry *
 gfxDWriteFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
                                    const nsAString& aFullname)
 {
-    bool found;
     gfxFontEntry *lookup;
 
     // initialize name lookup tables if needed
     if (!mFaceNamesInitialized) {
         InitFaceNameLists();
     }
 
     // lookup in name lookup tables, return null if not found
-    if (!(lookup = mPostscriptNames.GetWeak(aFullname, &found)) &&
-        !(lookup = mFullnames.GetWeak(aFullname, &found))) 
+    if (!(lookup = mPostscriptNames.GetWeak(aFullname)) &&
+        !(lookup = mFullnames.GetWeak(aFullname))) 
     {
         return nsnull;
     }
     gfxDWriteFontEntry* dwriteLookup = static_cast<gfxDWriteFontEntry*>(lookup);
     gfxDWriteFontEntry *fe =
         new gfxDWriteFontEntry(lookup->Name(),
                                dwriteLookup->mFont,
                                aProxyEntry->Weight(),
@@ -1177,29 +1212,55 @@ gfxDWriteFontList::ResolveFontName(const
     if (!mInitialized) {
         mInitialized = true;
         DelayedInitFontList();
     }
 
     nsAutoString keyName(aFontName);
     BuildKeyNameFromFontName(keyName);
 
-    nsRefPtr<gfxFontFamily> ff;
-    if (mFontSubstitutes.Get(keyName, &ff)) {
+    gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
+    if (ff) {
         aResolvedFontName = ff->Name();
         return true;
     }
 
     if (mNonExistingFonts.Contains(keyName)) {
         return false;
     }
 
     return gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName);
 }
 
+void
+gfxDWriteFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                       FontListSizes*    aSizes) const
+{
+    gfxPlatformFontList::SizeOfExcludingThis(aMallocSizeOf, aSizes);
+
+    aSizes->mFontListSize +=
+        mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
+                                             aMallocSizeOf);
+
+    aSizes->mFontListSize +=
+        mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf);
+    for (PRUint32 i = 0; i < mNonExistingFonts.Length(); ++i) {
+        aSizes->mFontListSize +=
+            mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    }
+}
+
+void
+gfxDWriteFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                       FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+
 static nsresult GetFamilyName(IDWriteFont *aFont, nsString& aFamilyName)
 {
     HRESULT hr;
     nsRefPtr<IDWriteFontFamily> family;
 
     // clean out previous value
     aFamilyName.Truncate();
 
--- a/gfx/thebes/gfxDWriteFontList.h
+++ b/gfx/thebes/gfxDWriteFontList.h
@@ -74,16 +74,21 @@ public:
     virtual ~gfxDWriteFontFamily();
     
     virtual void FindStyleVariations();
 
     virtual void LocalizedName(nsAString& aLocalizedName);
 
     void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
 
+    virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
 protected:
     /** This font family's directwrite fontfamily object */
     nsRefPtr<IDWriteFontFamily> mDWFamily;
     bool mForceGDIClassic;
 };
 
 /**
  * \brief Class representing DirectWrite FontEntry (a unique font style/family)
@@ -174,16 +179,21 @@ public:
 
     nsresult ReadCMAP();
 
     bool IsCJKFont();
 
     void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
     bool GetForceGDIClassic() { return mForceGDIClassic; }
 
+    virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
 protected:
     friend class gfxDWriteFont;
     friend class gfxDWriteFontList;
 
     virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
                                         bool aNeedsBold);
     
     nsresult CreateFontFace(
@@ -375,16 +385,21 @@ public:
     bool UseGDIFontTableAccess() { return mGDIFontTableAccess; }
 
     virtual gfxFontFamily* FindFamily(const nsAString& aFamily);
 
     virtual void GetFontFamilyList(nsTArray<nsRefPtr<gfxFontFamily> >& aFamilyArray);
 
     gfxFloat GetForceGDIClassicMaxFontSize() { return mForceGDIClassicMaxFontSize; }
 
+    virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
 private:
     friend class gfxDWriteFontFamily;
 
     nsresult GetFontSubstitutes();
 
     void GetDirectWriteSubstitutes();
 
     // search fonts system-wide for a given character, null otherwise
@@ -396,17 +411,17 @@ private:
     virtual bool UsesSystemFallback() { return true; }
 
     /**
      * Fonts listed in the registry as substitutes but for which no actual
      * font family is found.
      */
     nsTArray<nsString> mNonExistingFonts;
 
-    typedef nsDataHashtable<nsStringHashKey, nsRefPtr<gfxFontFamily> > FontTable;
+    typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
 
     /**
      * Table of font substitutes, we grab this from the registry to get
      * alternative font names.
      */
     FontTable mFontSubstitutes;
 
     bool mInitialized;
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -384,16 +384,33 @@ FT2FontEntry::GetFontTable(PRUint32 aTab
     }
     PRUint8 *buf = aBuffer.Elements();
     status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, buf, &len);
     NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
 
     return NS_OK;
 }
 
+void
+FT2FontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                  FontListSizes*    aSizes) const
+{
+    gfxFontEntry::SizeOfExcludingThis(aMallocSizeOf, aSizes);
+    aSizes->mFontListSize +=
+        mFilename.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+}
+
+void
+FT2FontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                  FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+
 /*
  * FT2FontFamily
  * A standard gfxFontFamily; just adds a method used to support sending
  * the font list from chrome to content via IPC.
  */
 
 void
 FT2FontFamily::AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList)
--- a/gfx/thebes/gfxFT2FontList.h
+++ b/gfx/thebes/gfxFT2FontList.h
@@ -97,16 +97,21 @@ public:
                                         bool aNeedsBold);
 
     cairo_font_face_t *CairoFontFace();
     cairo_scaled_font_t *CreateScaledFont(const gfxFontStyle *aStyle);
 
     nsresult ReadCMAP();
     nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer);
 
+    virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
     FT_Face mFTFace;
     cairo_font_face_t *mFontFace;
 
     nsCString mFilename;
     PRUint8 mFTFontIndex;
 };
 
 class FT2FontFamily : public gfxFontFamily
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -267,16 +267,23 @@ public:
 
     // Disconnect from the HashEntry (because the blob has already been
     // removed from the hashtable).
     void ForgetHashEntry()
     {
         mHashEntry = nsnull;
     }
 
+    size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+        return mTableData.SizeOfExcludingThis(aMallocSizeOf);
+    }
+    size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+        return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
+    }
+
 private:
     // The font table data block, owned (via adoption)
     FallibleTArray<PRUint8> mTableData;
     // The blob destroy function needs to know the hashtable entry,
     FontTableHashEntry *mHashEntry;
     // and the owning hashtable, so that it can remove the entry.
     nsTHashtable<FontTableHashEntry> *mHashtable;
 
@@ -396,16 +403,56 @@ void
 gfxFontEntry::CheckForGraphiteTables()
 {
     AutoFallibleTArray<PRUint8,16384> buffer;
     mHasGraphiteTables =
         NS_SUCCEEDED(GetFontTable(TRUETYPE_TAG('S','i','l','f'), buffer));
 }
 #endif
 
+/* static */ size_t
+gfxFontEntry::FontTableHashEntry::SizeOfEntryExcludingThis
+    (FontTableHashEntry *aEntry,
+     nsMallocSizeOfFun   aMallocSizeOf,
+     void*               aUserArg)
+{
+    FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
+    if (aEntry->mBlob) {
+        sizes->mFontTableCacheSize += aMallocSizeOf(aEntry->mBlob);
+    }
+    if (aEntry->mSharedBlobData) {
+        sizes->mFontTableCacheSize +=
+            aEntry->mSharedBlobData->SizeOfIncludingThis(aMallocSizeOf);
+    }
+
+    // the size of the table is recorded in the FontListSizes record,
+    // so we return 0 here for the function result
+    return 0;
+}
+
+void
+gfxFontEntry::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                  FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
+    aSizes->mFontTableCacheSize +=
+        mFontTableCache.SizeOfExcludingThis(
+            FontTableHashEntry::SizeOfEntryExcludingThis,
+            aMallocSizeOf, aSizes);
+}
+
+void
+gfxFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                  FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 //
 // class gfxFontFamily
 //
 //////////////////////////////////////////////////////////////////////////////
 
 // we consider faces with mStandardFace == true to be "greater than" those with false,
 // because during style matching, later entries will replace earlier ones
@@ -970,16 +1017,42 @@ gfxFontFamily::FindFont(const nsAString&
     for (PRUint32 i = 0; i < numFonts; i++) {
         gfxFontEntry *fe = mAvailableFonts[i].get();
         if (fe && fe->Name() == aPostscriptName)
             return fe;
     }
     return nsnull;
 }
 
+void
+gfxFontFamily::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                   FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize +=
+        mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    aSizes->mCharMapsSize += mCharacterMap.SizeOfExcludingThis(aMallocSizeOf);
+
+    aSizes->mFontListSize +=
+        mAvailableFonts.SizeOfExcludingThis(aMallocSizeOf);
+    for (PRUint32 i = 0; i < mAvailableFonts.Length(); ++i) {
+        gfxFontEntry *fe = mAvailableFonts[i];
+        if (fe) {
+            fe->SizeOfIncludingThis(aMallocSizeOf, aSizes);
+        }
+    }
+}
+
+void
+gfxFontFamily::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                   FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+ 
 /*
  * gfxFontCache - global cache of gfxFont instances.
  * Expires unused fonts after a short interval;
  * notifies fonts to age their cached shaped-word records;
  * observes memory-pressure notification and tells fonts to clear their
  * shaped-word caches to free up memory.
  */
 
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -86,16 +86,18 @@ typedef struct _hb_blob_t hb_blob_t;
 
 // An OpenType feature tag and value pair
 struct THEBES_API gfxFontFeature {
     PRUint32 mTag; // see http://www.microsoft.com/typography/otspec/featuretags.htm
     PRUint32 mValue; // 0 = off, 1 = on, larger values may be used as parameters
                      // to features that select among multiple alternatives
 };
 
+struct FontListSizes;
+
 inline bool
 operator<(const gfxFontFeature& a, const gfxFontFeature& b)
 {
     return (a.mTag < b.mTag) || ((a.mTag == b.mTag) && (a.mValue < b.mValue));
 }
 
 inline bool
 operator==(const gfxFontFeature& a, const gfxFontFeature& b)
@@ -309,16 +311,22 @@ public:
     // reference is owned by the caller.  Removing the last reference
     // unregisters the table from the font entry.
     //
     // Pass NULL for aBuffer to indicate that the table is not present and
     // NULL will be returned.  Also returns NULL on OOM.
     hb_blob_t *ShareFontTableAndGetBlob(PRUint32 aTag,
                                         FallibleTArray<PRUint8>* aTable);
 
+    // For memory reporting
+    virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
     nsString         mName;
 
     bool             mItalic      : 1;
     bool             mFixedPitch  : 1;
     bool             mIsProxy     : 1;
     bool             mIsValid     : 1;
     bool             mIsBadUnderlineFont : 1;
     bool             mIsUserFont  : 1;
@@ -463,16 +471,21 @@ private:
         void SaveTable(FallibleTArray<PRUint8>& aTable);
 
         // Return a strong reference to the blob.
         // Callers must hb_blob_destroy the returned blob.
         hb_blob_t *GetBlob() const;
 
         void Clear();
 
+        static size_t
+        SizeOfEntryExcludingThis(FontTableHashEntry *aEntry,
+                                 nsMallocSizeOfFun   aMallocSizeOf,
+                                 void*               aUserArg);
+
     private:
         static void DeleteFontTableBlobData(void *aBlobData);
         // not implemented
         FontTableHashEntry& operator=(FontTableHashEntry& toCopy);
 
         FontTableBlobData *mSharedBlobData;
         hb_blob_t *mBlob;
     };
@@ -629,16 +642,22 @@ public:
     // sort available fonts to put preferred (standard) faces towards the end
     void SortAvailableFonts();
 
     // check whether the family fits into the simple 4-face model,
     // so we can use simplified style-matching;
     // if so set the mIsSimpleFamily flag (defaults to False before we've checked)
     void CheckForSimpleFamily();
 
+    // For memory reporter
+    virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
 protected:
     // fills in an array with weights of faces that match style,
     // returns whether any matching entries found
     virtual bool FindWeightsForStyle(gfxFontEntry* aFontsForWeights[],
                                        bool anItalic, PRInt16 aStretch);
 
     bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
                                        FallibleTArray<PRUint8>& aNameTable,
--- a/gfx/thebes/gfxFontUtils.h
+++ b/gfx/thebes/gfxFontUtils.h
@@ -259,24 +259,28 @@ public:
             const PRUint32 end = NS_MIN<PRUint32>(aEnd - blockFirstBit, BLOCK_SIZE_BITS - 1);
 
             for (PRUint32 bit = start; bit <= end; ++bit) {
                 block->mBits[bit>>3] &= ~(1 << (bit & 0x7));
             }
         }
     }
 
-    PRUint32 GetSize() {
-        PRUint32 size = 0;
+    size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+        size_t total = mBlocks.SizeOfExcludingThis(aMallocSizeOf);
         for (PRUint32 i = 0; i < mBlocks.Length(); i++) {
-            if (mBlocks[i])
-                size += sizeof(Block);
-            size += sizeof(nsAutoPtr<Block>);
+            if (mBlocks[i]) {
+                total += aMallocSizeOf(mBlocks[i]);
+            }
         }
-        return size;
+        return total;
+    }
+
+    size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+        return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
     }
 
     // clear out all blocks in the array
     void reset() {
         PRUint32 i;
         for (i = 0; i < mBlocks.Length(); i++)
             mBlocks[i] = nsnull;    
     }
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -241,17 +241,18 @@ GDIFontEntry::ReadCMAP()
     nsresult rv = gfxFontUtils::ReadCMAP(cmap, buffer.Length(),
                                          mCharacterMap, mUVSOffset,
                                          unicodeFont, symbolFont);
     mSymbolFont = symbolFont;
     mHasCmapTable = NS_SUCCEEDED(rv);
 
 #ifdef PR_LOGGING
     LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
-                  NS_ConvertUTF16toUTF8(mName).get(), mCharacterMap.GetSize()));
+                  NS_ConvertUTF16toUTF8(mName).get(),
+                  mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
     if (LOG_CMAPDATA_ENABLED()) {
         char prefix[256];
         sprintf(prefix, "(cmapdata) name: %.220s",
                 NS_ConvertUTF16toUTF8(mName).get());
         mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
     }
 #endif
     return rv;
@@ -454,16 +455,24 @@ GDIFontEntry::CreateFontEntry(const nsAS
     // jtdfix - need to set charset, unicode ranges, pitch/family
 
     GDIFontEntry *fe = new GDIFontEntry(aName, aFontType, aItalic,
                                         aWeight, aStretch, aUserFontData);
 
     return fe;
 }
 
+void
+GDIFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                  FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+
 /***************************************************************
  *
  * GDIFontFamily
  *
  */
 
 int CALLBACK
 GDIFontFamily::FamilyAddStylesProc(const ENUMLOGFONTEXW *lpelfe,
@@ -653,17 +662,17 @@ gfxGDIFontList::GetFontSubstitutes()
     }
 
     // "Courier" on a default Windows install is an ugly bitmap font.
     // If there is no substitution for Courier in the registry
     // substitute "Courier" with "Courier New".
     nsAutoString substituteName;
     substituteName.AssignLiteral("Courier");
     BuildKeyNameFromFontName(substituteName);
-    if (!mFontSubstitutes.Get(substituteName)) {
+    if (!mFontSubstitutes.GetWeak(substituteName)) {
         gfxFontFamily *ff;
         nsAutoString actualFontName;
         actualFontName.AssignLiteral("Courier New");
         BuildKeyNameFromFontName(actualFontName);
         ff = mFontFamilies.GetWeak(actualFontName);
         if (ff) {
             mFontSubstitutes.Put(substituteName, ff);
         }
@@ -738,27 +747,26 @@ gfxGDIFontList::EnumFontFamExProc(ENUMLO
 
     return 1;
 }
 
 gfxFontEntry* 
 gfxGDIFontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
                                 const nsAString& aFullname)
 {
-    bool found;
     gfxFontEntry *lookup;
 
     // initialize name lookup tables if needed
     if (!mFaceNamesInitialized) {
         InitFaceNameLists();
     }
 
     // lookup in name lookup tables, return null if not found
-    if (!(lookup = mPostscriptNames.GetWeak(aFullname, &found)) &&
-        !(lookup = mFullnames.GetWeak(aFullname, &found))) 
+    if (!(lookup = mPostscriptNames.GetWeak(aFullname)) &&
+        !(lookup = mFullnames.GetWeak(aFullname))) 
     {
         return nsnull;
     }
 
     // create a new font entry with the proxy entry style characteristics
     PRUint16 w = (aProxyEntry->mWeight == 0 ? 400 : aProxyEntry->mWeight);
     bool isCFF = false; // jtdfix -- need to determine this
     
@@ -1033,22 +1041,46 @@ gfxGDIFontList::GetDefaultFont(const gfx
 
 
 bool 
 gfxGDIFontList::ResolveFontName(const nsAString& aFontName, nsAString& aResolvedFontName)
 {
     nsAutoString keyName(aFontName);
     BuildKeyNameFromFontName(keyName);
 
-    nsRefPtr<gfxFontFamily> ff;
-    if (mFontSubstitutes.Get(keyName, &ff)) {
+    gfxFontFamily *ff = mFontSubstitutes.GetWeak(keyName);
+    if (ff) {
         aResolvedFontName = ff->Name();
         return true;
     }
 
     if (mNonExistingFonts.Contains(keyName))
         return false;
 
     if (gfxPlatformFontList::ResolveFontName(aFontName, aResolvedFontName))
         return true;
 
     return false;
 }
+
+void
+gfxGDIFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                    FontListSizes*    aSizes) const
+{
+    gfxPlatformFontList::SizeOfExcludingThis(aMallocSizeOf, aSizes);
+    aSizes->mFontListSize +=
+        mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
+                                             aMallocSizeOf);
+    aSizes->mFontListSize +=
+        mNonExistingFonts.SizeOfExcludingThis(aMallocSizeOf);
+    for (PRUint32 i = 0; i < mNonExistingFonts.Length(); ++i) {
+        aSizes->mFontListSize +=
+            mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    }
+}
+
+void
+gfxGDIFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                    FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
--- a/gfx/thebes/gfxGDIFontList.h
+++ b/gfx/thebes/gfxGDIFontList.h
@@ -269,16 +269,19 @@ public:
     }
 
     virtual bool SkipDuringSystemFallback() { 
         return !HasCmapTable(); // explicitly skip non-SFNT fonts
     }
 
     virtual bool TestCharacterMap(PRUint32 aCh);
 
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
     // create a font entry for a font with a given name
     static GDIFontEntry* CreateFontEntry(const nsAString& aName,
                                          gfxWindowsFontType aFontType,
                                          bool aItalic,
                                          PRUint16 aWeight, PRInt16 aStretch,
                                          gfxUserFontData* aUserFontData);
 
     // create a font entry for a font referenced by its fullname
@@ -342,29 +345,34 @@ public:
                                           const nsAString& aFontName);
 
     virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
                                            const PRUint8 *aFontData, PRUint32 aLength);
 
     virtual bool ResolveFontName(const nsAString& aFontName,
                                    nsAString& aResolvedFontName);
 
+    virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
 private:
     friend class gfxWindowsPlatform;
 
     gfxGDIFontList();
 
     void InitializeFontEmbeddingProcs();
 
     nsresult GetFontSubstitutes();
 
     static int CALLBACK EnumFontFamExProc(ENUMLOGFONTEXW *lpelfe,
                                           NEWTEXTMETRICEXW *lpntme,
                                           DWORD fontType,
                                           LPARAM lParam);
 
-    typedef nsDataHashtable<nsStringHashKey, nsRefPtr<gfxFontFamily> > FontTable;
+    typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontTable;
 
     FontTable mFontSubstitutes;
     nsTArray<nsString> mNonExistingFonts;
 };
 
 #endif /* GFX_GDIFONTLIST_H */
--- a/gfx/thebes/gfxMacPlatformFontList.h
+++ b/gfx/thebes/gfxMacPlatformFontList.h
@@ -106,16 +106,19 @@ public:
 
     ATSFontRef GetATSFontRef();
 
     virtual CGFontRef GetFontRef();
 
     virtual nsresult GetFontTable(PRUint32 aTableTag,
                                   FallibleTArray<PRUint8>& aBuffer);
 
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
 protected:
     virtual bool HasFontTable(PRUint32 aTableTag);
 
     ATSFontRef   mATSFontRef;
     bool mATSFontRefInitialized;
 };
 
 class CGFontEntry : public MacOSFontEntry
@@ -129,16 +132,19 @@ public:
                 PRUint16 aWeight, PRUint16 aStretch, PRUint32 aItalicStyle,
                 bool aIsUserFont, bool aIsLocal);
 
     virtual CGFontRef GetFontRef();
 
     virtual nsresult GetFontTable(PRUint32 aTableTag,
                                   FallibleTArray<PRUint8>& aBuffer);
 
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
 protected:
     virtual bool HasFontTable(PRUint32 aTableTag);
 };
 
 class gfxMacPlatformFontList : public gfxPlatformFontList {
 public:
     static gfxMacPlatformFontList* PlatformFontList() {
         return static_cast<gfxMacPlatformFontList*>(sPlatformFontList);
--- a/gfx/thebes/gfxMacPlatformFontList.mm
+++ b/gfx/thebes/gfxMacPlatformFontList.mm
@@ -265,17 +265,17 @@ MacOSFontEntry::ReadCMAP()
                                          gScriptsThatRequireShaping[s].rangeEnd);
             }
         }
     }
 
 #ifdef PR_LOGGING
     LOG_FONTLIST(("(fontlist-cmap) name: %s, size: %d\n",
                   NS_ConvertUTF16toUTF8(mName).get(),
-                  mCharacterMap.GetSize()));
+                  mCharacterMap.SizeOfExcludingThis(moz_malloc_size_of)));
     if (LOG_CMAPDATA_ENABLED()) {
         char prefix[256];
         sprintf(prefix, "(cmapdata) name: %.220s",
                 NS_ConvertUTF16toUTF8(mName).get());
         mCharacterMap.Dump(prefix, eGfxLog_cmapdata);
     }
 #endif
 
@@ -393,16 +393,24 @@ bool
 ATSFontEntry::HasFontTable(PRUint32 aTableTag)
 {
     ATSFontRef fontRef = GetATSFontRef();
     ByteCount size;
     return fontRef != kInvalidFont &&
         (::ATSFontGetTable(fontRef, aTableTag, 0, 0, 0, &size) == noErr);
 }
 
+void
+ATSFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                  FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+
 /* CGFontEntry - used on Mac OS X 10.6+ */
 #pragma mark-
 
 CGFontEntry::CGFontEntry(const nsAString& aPostscriptName,
                          PRInt32 aWeight,
                          gfxFontFamily *aFamily,
                          bool aIsStandardFace)
     : MacOSFontEntry(aPostscriptName, aWeight, aFamily, aIsStandardFace)
@@ -481,16 +489,24 @@ CGFontEntry::HasFontTable(PRUint32 aTabl
     if (!tableData) {
         return false;
     }
 
     ::CFRelease(tableData);
     return true;
 }
 
+void
+CGFontEntry::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                 FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
+
 /* gfxMacFontFamily */
 #pragma mark-
 
 class gfxMacFontFamily : public gfxFontFamily
 {
 public:
     gfxMacFontFamily(nsAString& aName) :
         gfxFontFamily(aName)
@@ -806,20 +822,19 @@ gfxMacPlatformFontList::InitSingleFaceLi
             GenerateFontListKey(familyName, key);
 #ifdef PR_LOGGING
             LOG_FONTLIST(("(fontlist-singleface) family name: %s, key: %s\n",
                           NS_ConvertUTF16toUTF8(familyName).get(),
                           NS_ConvertUTF16toUTF8(key).get()));
 #endif
 
             // add only if doesn't exist already
-            bool found;
-            gfxFontFamily *familyEntry;
-            if (!(familyEntry = mFontFamilies.GetWeak(key, &found))) {
-                familyEntry = new gfxSingleFaceMacFontFamily(familyName);
+            if (!mFontFamilies.GetWeak(key)) {
+                gfxFontFamily *familyEntry =
+                    new gfxSingleFaceMacFontFamily(familyName);
                 familyEntry->AddFontEntry(fontEntry);
                 familyEntry->SetHasStyles(true);
                 mFontFamilies.Put(key, familyEntry);
                 fontEntry->mFamily = familyEntry;
 #ifdef PR_LOGGING
                 LOG_FONTLIST(("(fontlist-singleface) added new family\n",
                               NS_ConvertUTF16toUTF8(familyName).get(),
                               NS_ConvertUTF16toUTF8(key).get()));
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -125,16 +125,73 @@ gfxFontListPrefObserver::Observe(nsISupp
     NS_ASSERTION(!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID), "invalid topic");
     // XXX this could be made to only clear out the cache for the prefs that were changed
     // but it probably isn't that big a deal.
     gfxPlatformFontList::PlatformFontList()->ClearPrefFonts();
     gfxFontCache::GetCache()->AgeAllGenerations();
     return NS_OK;
 }
 
+NS_IMPL_ISUPPORTS1(gfxPlatformFontList::MemoryReporter, nsIMemoryMultiReporter)
+
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FontListMallocSizeOf, "font-list")
+
+NS_IMETHODIMP
+gfxPlatformFontList::MemoryReporter::GetName(nsACString &aName)
+{
+    aName.AssignLiteral("font-list");
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+gfxPlatformFontList::MemoryReporter::CollectReports
+    (nsIMemoryMultiReporterCallback* aCb,
+     nsISupports* aClosure)
+{
+    FontListSizes sizes;
+    sizes.mFontListSize = 0;
+    sizes.mFontTableCacheSize = 0;
+    sizes.mCharMapsSize = 0;
+
+    gfxPlatformFontList::PlatformFontList()->SizeOfIncludingThis(&FontListMallocSizeOf,
+                                                                 &sizes);
+
+    aCb->Callback(EmptyCString(),
+                  NS_LITERAL_CSTRING("explicit/gfx/font-list"),
+                  nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
+                  sizes.mFontListSize,
+                  NS_LITERAL_CSTRING("Memory used to manage the list of font families and faces."),
+                  aClosure);
+
+    aCb->Callback(EmptyCString(),
+                  NS_LITERAL_CSTRING("explicit/gfx/font-charmaps"),
+                  nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
+                  sizes.mCharMapsSize,
+                  NS_LITERAL_CSTRING("Memory used to record the character coverage of individual fonts."),
+                  aClosure);
+
+    if (sizes.mFontTableCacheSize) {
+        aCb->Callback(EmptyCString(),
+                      NS_LITERAL_CSTRING("explicit/gfx/font-tables"),
+                      nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
+                      sizes.mFontTableCacheSize,
+                      NS_LITERAL_CSTRING("Memory used for cached font metrics and layout tables."),
+                      aClosure);
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+gfxPlatformFontList::MemoryReporter::GetExplicitNonHeap(PRInt64* aAmount)
+{
+    // This reporter only measures heap memory.
+    *aAmount = 0;
+    return NS_OK;
+}
 
 gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
     : mNeedFullnamePostscriptNames(aNeedFullnamePostscriptNames),
       mStartIndex(0), mIncrement(kNumFontsPerSlice), mNumFamilies(0)
 {
     mFontFamilies.Init(100);
     mOtherFamilyNames.Init(30);
     mOtherFamilyNamesInitialized = false;
@@ -179,16 +236,18 @@ gfxPlatformFontList::InitFontList()
     mPrefFonts.Clear();
     CancelLoader();
 
     // initialize ranges of characters for which system-wide font search should be skipped
     mCodepointsWithNoFonts.reset();
     mCodepointsWithNoFonts.SetRange(0,0x1f);     // C0 controls
     mCodepointsWithNoFonts.SetRange(0x7f,0x9f);  // C1 controls
 
+    NS_RegisterMemoryMultiReporter(new MemoryReporter);
+
     sPlatformFontList = this;
 
     return NS_OK;
 }
 
 void
 gfxPlatformFontList::GenerateFontListKey(const nsAString& aKeyName, nsAString& aResult)
 {
@@ -239,22 +298,21 @@ gfxPlatformFontList::InitFaceNameListsPr
 void
 gfxPlatformFontList::PreloadNamesList()
 {
     nsAutoTArray<nsString, 10> preloadFonts;
     gfxFontUtils::GetPrefsFontList("font.preload-names-list", preloadFonts);
 
     PRUint32 numFonts = preloadFonts.Length();
     for (PRUint32 i = 0; i < numFonts; i++) {
-        bool found;
         nsAutoString key;
         GenerateFontListKey(preloadFonts[i], key);
         
         // only search canonical names!
-        gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key, &found);
+        gfxFontFamily *familyEntry = mFontFamilies.GetWeak(key);
         if (familyEntry) {
             familyEntry->ReadOtherFamilyNames(this);
         }
     }
 
 }
 
 void 
@@ -544,39 +602,38 @@ static void LogRegistryEvent(const wchar
 }
 #endif
 
 gfxFontFamily* 
 gfxPlatformFontList::FindFamily(const nsAString& aFamily)
 {
     nsAutoString key;
     gfxFontFamily *familyEntry;
-    bool found;
     GenerateFontListKey(aFamily, key);
 
     NS_ASSERTION(mFontFamilies.Count() != 0, "system font list was not initialized correctly");
 
     // lookup in canonical (i.e. English) family name list
-    if ((familyEntry = mFontFamilies.GetWeak(key, &found))) {
+    if ((familyEntry = mFontFamilies.GetWeak(key))) {
         return familyEntry;
     }
 
     // lookup in other family names list (mostly localized names)
-    if ((familyEntry = mOtherFamilyNames.GetWeak(key, &found)) != nsnull) {
+    if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nsnull) {
         return familyEntry;
     }
 
     // name not found and other family names not yet fully initialized so
     // initialize the rest of the list and try again.  this is done lazily
     // since reading name table entries is expensive.
     // although ASCII localized family names are possible they don't occur
     // in practice so avoid pulling in names at startup
     if (!mOtherFamilyNamesInitialized && !IsASCII(aFamily)) {
         InitOtherFamilyNames();
-        if ((familyEntry = mOtherFamilyNames.GetWeak(key, &found)) != nsnull) {
+        if ((familyEntry = mOtherFamilyNames.GetWeak(key)) != nsnull) {
             return familyEntry;
         }
     }
 
     return nsnull;
 }
 
 gfxFontEntry*
@@ -603,53 +660,48 @@ gfxPlatformFontList::SetPrefFontFamilyEn
 {
     mPrefFonts.Put(PRUint32(aLangGroup), array);
 }
 
 void 
 gfxPlatformFontList::AddOtherFamilyName(gfxFontFamily *aFamilyEntry, nsAString& aOtherFamilyName)
 {
     nsAutoString key;
-    bool found;
     GenerateFontListKey(aOtherFamilyName, key);
 
-    if (!mOtherFamilyNames.GetWeak(key, &found)) {
+    if (!mOtherFamilyNames.GetWeak(key)) {
         mOtherFamilyNames.Put(key, aFamilyEntry);
 #ifdef PR_LOGGING
         LOG_FONTLIST(("(fontlist-otherfamily) canonical family: %s, "
                       "other family: %s\n",
                       NS_ConvertUTF16toUTF8(aFamilyEntry->Name()).get(),
                       NS_ConvertUTF16toUTF8(aOtherFamilyName).get()));
 #endif
         if (mBadUnderlineFamilyNames.Contains(key))
             aFamilyEntry->SetBadUnderlineFamily();
     }
 }
 
 void
 gfxPlatformFontList::AddFullname(gfxFontEntry *aFontEntry, nsAString& aFullname)
 {
-    bool found;
-
-    if (!mFullnames.GetWeak(aFullname, &found)) {
+    if (!mFullnames.GetWeak(aFullname)) {
         mFullnames.Put(aFullname, aFontEntry);
 #ifdef PR_LOGGING
         LOG_FONTLIST(("(fontlist-fullname) name: %s, fullname: %s\n",
                       NS_ConvertUTF16toUTF8(aFontEntry->Name()).get(),
                       NS_ConvertUTF16toUTF8(aFullname).get()));
 #endif
     }
 }
 
 void
 gfxPlatformFontList::AddPostscriptName(gfxFontEntry *aFontEntry, nsAString& aPostscriptName)
 {
-    bool found;
-
-    if (!mPostscriptNames.GetWeak(aPostscriptName, &found)) {
+    if (!mPostscriptNames.GetWeak(aPostscriptName)) {
         mPostscriptNames.Put(aPostscriptName, aFontEntry);
 #ifdef PR_LOGGING
         LOG_FONTLIST(("(fontlist-postscript) name: %s, psname: %s\n",
                       NS_ConvertUTF16toUTF8(aFontEntry->Name()).get(),
                       NS_ConvertUTF16toUTF8(aPostscriptName).get()));
 #endif
     }
 }
@@ -709,8 +761,116 @@ gfxPlatformFontList::RunLoader()
 }
 
 void 
 gfxPlatformFontList::FinishLoader()
 {
     mFontFamiliesToLoad.Clear();
     mNumFamilies = 0;
 }
+
+// Support for memory reporting
+
+static size_t
+SizeOfFamilyEntryExcludingThis(const nsAString&               aKey,
+                               const nsRefPtr<gfxFontFamily>& aFamily,
+                               nsMallocSizeOfFun              aMallocSizeOf,
+                               void*                          aUserArg)
+{
+    FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
+    aFamily->SizeOfExcludingThis(aMallocSizeOf, sizes);
+
+    sizes->mFontListSize += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+
+    // we return zero here because the measurements have been added directly
+    // to the relevant fields of the FontListSizes record
+    return 0;
+}
+
+// this is also used by subclasses that hold additional hashes of family names
+/*static*/ size_t
+gfxPlatformFontList::SizeOfFamilyNameEntryExcludingThis
+    (const nsAString&               aKey,
+     const nsRefPtr<gfxFontFamily>& aFamily,
+     nsMallocSizeOfFun              aMallocSizeOf,
+     void*                          aUserArg)
+{
+    // we don't count the size of the family here, because this is an *extra*
+    // reference to a family that will have already been counted in the main list
+    return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+}
+
+static size_t
+SizeOfFontNameEntryExcludingThis(const nsAString&              aKey,
+                                 const nsRefPtr<gfxFontEntry>& aFont,
+                                 nsMallocSizeOfFun             aMallocSizeOf,
+                                 void*                         aUserArg)
+{
+    // the font itself is counted by its owning family; here we only care about
+    // the name stored in the hashtable key
+    return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+}
+
+static size_t
+SizeOfPrefFontEntryExcludingThis
+    (const PRUint32&                           aKey,
+     const nsTArray<nsRefPtr<gfxFontFamily> >& aList,
+     nsMallocSizeOfFun                         aMallocSizeOf,
+     void*                                     aUserArg)
+{
+    // again, we only care about the size of the array itself; we don't follow
+    // the refPtrs stored in it, because they point to entries already owned
+    // and accounted-for by the main font list
+    return aList.SizeOfExcludingThis(aMallocSizeOf);
+}
+
+static size_t
+SizeOfStringEntryExcludingThis(nsStringHashKey*  aHashEntry,
+                               nsMallocSizeOfFun aMallocSizeOf,
+                               void*             aUserArg)
+{
+    return aHashEntry->GetKey().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+}
+
+void
+gfxPlatformFontList::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                         FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize +=
+        mFontFamilies.SizeOfExcludingThis(SizeOfFamilyEntryExcludingThis,
+                                          aMallocSizeOf, aSizes);
+
+    aSizes->mFontListSize +=
+        mOtherFamilyNames.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
+                                              aMallocSizeOf);
+
+    if (mNeedFullnamePostscriptNames) {
+        aSizes->mFontListSize +=
+            mFullnames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
+                                           aMallocSizeOf);
+        aSizes->mFontListSize +=
+            mPostscriptNames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
+                                                 aMallocSizeOf);
+    }
+
+    aSizes->mFontListSize +=
+        mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
+    aSizes->mFontListSize +=
+        mReplacementCharFallbackFamily.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    aSizes->mFontListSize +=
+        mFontFamiliesToLoad.SizeOfExcludingThis(aMallocSizeOf);
+
+    aSizes->mFontListSize +=
+        mPrefFonts.SizeOfExcludingThis(SizeOfPrefFontEntryExcludingThis,
+                                       aMallocSizeOf);
+
+    aSizes->mFontListSize +=
+        mBadUnderlineFamilyNames.SizeOfExcludingThis(SizeOfStringEntryExcludingThis,
+                                                     aMallocSizeOf);
+}
+
+void
+gfxPlatformFontList::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                         FontListSizes*    aSizes) const
+{
+    aSizes->mFontListSize += aMallocSizeOf(this);
+    SizeOfExcludingThis(aMallocSizeOf, aSizes);
+}
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -42,26 +42,35 @@
 #include "nsDataHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsTHashtable.h"
 
 #include "gfxFontUtils.h"
 #include "gfxFont.h"
 #include "gfxPlatform.h"
 
+#include "nsIMemoryReporter.h"
 #include "mozilla/FunctionTimer.h"
 
 // gfxPlatformFontList is an abstract class for the global font list on the system;
 // concrete subclasses for each platform implement the actual interface to the system fonts.
 // This class exists because we cannot rely on the platform font-finding APIs to behave
 // in sensible/similar ways, particularly with rich, complex OpenType families,
 // so we do our own font family/style management here instead.
 
 // Much of this is based on the old gfxQuartzFontCache, but adapted for use on all platforms.
 
+struct FontListSizes {
+    PRUint32 mFontListSize; // size of the font list and dependent objects
+                            // (font family and face names, etc), but NOT
+                            // including the font table cache and the cmaps
+    PRUint32 mFontTableCacheSize; // memory used for the gfxFontEntry table caches
+    PRUint32 mCharMapsSize; // memory used for cmap coverage info
+};
+
 class gfxPlatformFontList : protected gfxFontInfoLoader
 {
 public:
     static gfxPlatformFontList* PlatformFontList() {
         return sPlatformFontList;
     }
 
     static nsresult Init() {
@@ -136,17 +145,30 @@ public:
     virtual gfxFontEntry* MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
                                            const PRUint8 *aFontData,
                                            PRUint32 aLength) = 0;
 
     // get the standard family name on the platform for a given font name
     // (platforms may override, eg Mac)
     virtual bool GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
 
+    virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+    virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
+                                     FontListSizes*    aSizes) const;
+
 protected:
+    class MemoryReporter
+        : public nsIMemoryMultiReporter
+    {
+    public:
+        NS_DECL_ISUPPORTS
+        NS_DECL_NSIMEMORYMULTIREPORTER
+    };
+
     gfxPlatformFontList(bool aNeedFullnamePostscriptNames = true);
 
     static gfxPlatformFontList *sPlatformFontList;
 
     static PLDHashOperator FindFontForCharProc(nsStringHashKey::KeyType aKey,
                                                nsRefPtr<gfxFontFamily>& aFamilyEntry,
                                                void* userArg);
 
@@ -195,16 +217,23 @@ protected:
                                 nsRefPtr<gfxFontFamily>& aFamilyEntry,
                                 void* aUserArg);
 
     // gfxFontInfoLoader overrides, used to load in font cmaps
     virtual void InitLoader();
     virtual bool RunLoader();
     virtual void FinishLoader();
 
+    // used by memory reporter to accumulate sizes of family names in the hash
+    static size_t
+    SizeOfFamilyNameEntryExcludingThis(const nsAString&               aKey,
+                                       const nsRefPtr<gfxFontFamily>& aFamily,
+                                       nsMallocSizeOfFun              aMallocSizeOf,
+                                       void*                          aUserArg);
+
     // canonical family name ==> family entry (unique, one name per family entry)
     nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mFontFamilies;
 
     // other family name ==> family entry (not unique, can have multiple names per
     // family entry, only names *other* than the canonical names are stored here)
     nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> mOtherFamilyNames;
 
     // flag set after InitOtherFamilyNames is called upon first name lookup miss
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -83,16 +83,22 @@ using namespace mozilla::gfx;
 #include <d3d10_1.h>
 #include <dxgi.h>
 
 #include "mozilla/gfx/2D.h"
 
 #include "nsMemory.h"
 #endif
 
+/*
+ * Required headers are not available in the current consumer preview Win8
+ * dev kit, disabling for now.
+ */
+#undef MOZ_WINSDK_TARGETVER
+
 /**
  * XXX below should be >= MOZ_NTDDI_WIN8 or such which is not defined yet
  */
 #if MOZ_WINSDK_TARGETVER > MOZ_NTDDI_WIN7
 #define ENABLE_GPU_MEM_REPORTER
 #endif
 
 #if defined CAIRO_HAS_D2D_SURFACE || defined ENABLE_GPU_MEM_REPORTER
--- a/intl/locale/src/language.properties
+++ b/intl/locale/src/language.properties
@@ -1,265 +1,265 @@
-aa.accept = 	false				
-ab.accept = 	true				
-ae.accept = 	false
-af.accept = 	true				
-ak.accept = 	false
-am.accept = 	true
-an.accept = 	true
-ar.accept = 	true				
-ar-ae.accept = true				
-ar-bh.accept = true				
-ar-dz.accept = true				
-ar-eg.accept = true				
-ar-iq.accept = true				
-ar-jo.accept = true				
-ar-kw.accept = true				
-ar-lb.accept = true				
-ar-ly.accept = true				
-ar-ma.accept = true				
-ar-om.accept = true				
-ar-qa.accept = true				
-ar-sa.accept = true				
-ar-sy.accept = true				
-ar-tn.accept = true				
-ar-ye.accept = true				
-as.accept =    true
-ast.accept = 	true				
-av.accept =	false
-ay.accept =     true
-az.accept = 	true
-ba.accept = 	false				
-be.accept = 	true				
-bg.accept = 	true				
-bh.accept = 	false				
-bi.accept = 	false				
-bm.accept = 	false				
-bn.accept = 	true
-bo.accept = 	true				
-br.accept = 	true
-bs.accept = 	true				
-ca.accept = 	true				
-ce.accept = 	true				
-ch.accept =	true
-co.accept = 	true
-cr.accept =	true
-cs.accept = 	true				
-cu.accept = 	false
-cv.accept = 	true
-cy.accept = 	true				
-da.accept = 	true				
-de.accept = 	true				
-de-at.accept = true				
-de-ch.accept = true				
-de-de.accept = true				
-de-li.accept = true				
-de-lu.accept = true				
-dv.accept =	false
-dz.accept =	true
-ee.accept =	false
-el.accept = 	true				
-en.accept = 	true				
-en-au.accept = true				
-en-bz.accept = true				
-en-ca.accept = true				
-en-gb.accept = true				
-en-ie.accept = true				
-en-jm.accept = true				
-en-nz.accept = true				
-en-ph.accept = true				
-en-tt.accept = true				
-en-us.accept = true				
-en-za.accept = true				
-en-zw.accept = true				
-eo.accept =	true				
-es.accept = 	true				
-es-ar.accept = true				
-es-bo.accept = true				
-es-cl.accept = true				
-es-co.accept = true				
-es-cr.accept = true				
-es-do.accept = true				
-es-ec.accept = true				
-es-es.accept = true				
-es-gt.accept = true				
-es-hn.accept = true				
-es-mx.accept = true				
-es-ni.accept = true				
-es-pa.accept = true				
-es-pe.accept = true				
-es-pr.accept = true				
-es-py.accept = true				
-es-sv.accept = true				
-es-uy.accept = true				
-es-ve.accept = true				
-et.accept = 	true	
-eu.accept = 	true				
-fa.accept = 	true
-fa-ir.accept =  true
-ff.accept =	false
-fi.accept = 	true				
-fj.accept = 	true				
-fo.accept = 	true				
-fr.accept = 	true				
-fr-be.accept = true				
-fr-ca.accept = true				
-fr-ch.accept = true				
-fr-fr.accept = true				
-fr-lu.accept = true				
-fr-mc.accept = true				
-fur.accept =	true
-fy.accept =	true
-ga.accept = 	true				
-gd.accept = 	true				
-gl.accept = 	true				
-gn.accept = 	true				
-gu.accept = 	true
-gv.accept =	true
-ha.accept = 	false				
-he.accept = 	true	
-hi.accept = 	true				
-ho.accept =	false
-hsb.accept =	true
-hr.accept = 	true				
-ht.accept =	true
-hu.accept = 	true				
-hy.accept = 	true				
-hz.accept =	false
-ia.accept =	true
-id.accept = 	true
-ie.accept = 	true
-ig.accept = 	false
-ii.accept = 	false
-ik.accept = 	false
-io.accept = 	false
-is.accept = 	true				
-it.accept = 	true				
-it-ch.accept = true				
-iu.accept =	true
-ja.accept = 	true				
-jv.accept = 	false
-ka.accept = 	true				
-kg.accept =	false
-ki.accept =	false
-kk.accept = 	true
-kl.accept = 	true				
-km.accept = 	true
-kn.accept = 	true			
-ko.accept = 	true				
-ko-kp.accept = true				
-ko-kr.accept = true				
-kok.accept =	true
-kr.accept =	false
-ks.accept =	true
-ku.accept =	true
-kv.accept =	false
-kw.accept =	false
-ky.accept =	true
-la.accept =	true
-lb.accept =	true
-lg.accept =	false
-li.accept =	false
-ln.accept =	true
-lo.accept =	false
-lt.accept = 	true	
-lu.accept = 	false
-lv.accept = 	true	
-mg.accept =	true
-mh.accept =	true
-mi.accept = 	true
-mk.accept = 	false
-mk-mk.accept = true				
-ml.accept =	true
-mn.accept = 	true				
-mr.accept = 	true
-ms.accept = 	true				
-mt.accept = 	true
-my.accept = 	true				
-na.accept =	true
-nb.accept =	true
-nd.accept =	true
-ne.accept = 	true
-ng.accept = 	true				
-nl.accept = 	true				
-nl-be.accept = true				
-nn.accept = 	true				
-no.accept = 	true				
-nr.accept =	true
-nso.accept =	true
-nv.accept =	true
-ny.accept =	true
-oc.accept =	true
-oj.accept =	false
-om.accept =	true
-or.accept = 	true				
-os.accept = 	false				
-pa.accept = 	true
-pa-in.accept = 	true
-pa-pk.accept = 	true
-pi.accept = 	false
-pl.accept = 	true				
-ps.accept = 	true
-pt.accept = 	true				
-pt-br.accept = true				
-qu.accept = 	true
-rm.accept = 	true
-rn.accept = 	true
-ro.accept = 	true				
-ro-md.accept = true				
-ro-ro.accept = true
-ru.accept = 	true				
-ru-md.accept = false				
-rw.accept =     true
-sa.accept =	true
-sc.accept = 	true
-sd.accept = 	true
-sg.accept = 	true
-si.accept = 	true
-sk.accept = 	true				
-sl.accept = 	true				
-sm.accept =     true
-so.accept = 	true
+aa.accept     = true                             
+ab.accept     = true                             
+ae.accept     = true
+af.accept     = true                            
+ak.accept     = true
+am.accept     = true
+an.accept     = true
+ar.accept     = true                            
+ar-ae.accept  = true                             
+ar-bh.accept  = true                             
+ar-dz.accept  = true                             
+ar-eg.accept  = true                             
+ar-iq.accept  = true                             
+ar-jo.accept  = true                             
+ar-kw.accept  = true                             
+ar-lb.accept  = true                             
+ar-ly.accept  = true                             
+ar-ma.accept  = true                             
+ar-om.accept  = true                             
+ar-qa.accept  = true                             
+ar-sa.accept  = true                             
+ar-sy.accept  = true                             
+ar-tn.accept  = true                             
+ar-ye.accept  = true                             
+as.accept     = true
+ast.accept    = true                            
+av.accept     = true
+ay.accept     = true
+az.accept     = true
+ba.accept     = true                            
+be.accept     = true                            
+bg.accept     = true                            
+bh.accept     = true                            
+bi.accept     = true                            
+bm.accept     = true                            
+bn.accept     = true
+bo.accept     = true                            
+br.accept     = true
+bs.accept     = true                            
+ca.accept     = true                            
+ce.accept     = true                            
+ch.accept     = true
+co.accept     = true
+cr.accept     = true
+cs.accept     = true                            
+cu.accept     = true
+cv.accept     = true
+cy.accept     = true                            
+da.accept     = true                            
+de.accept     = true                            
+de-at.accept  = true                             
+de-ch.accept  = true                             
+de-de.accept  = true                             
+de-li.accept  = true                             
+de-lu.accept  = true                             
+dv.accept     = true
+dz.accept     = true
+ee.accept     = true
+el.accept     = true                            
+en.accept     = true                            
+en-au.accept  = true                             
+en-bz.accept  = true                             
+en-ca.accept  = true                             
+en-gb.accept  = true                             
+en-ie.accept  = true                             
+en-jm.accept  = true                             
+en-nz.accept  = true                             
+en-ph.accept  = true                             
+en-tt.accept  = true                             
+en-us.accept  = true                             
+en-za.accept  = true                             
+en-zw.accept  = true                             
+eo.accept     = true                            
+es.accept     = true                            
+es-ar.accept  = true                             
+es-bo.accept  = true                             
+es-cl.accept  = true                             
+es-co.accept  = true                             
+es-cr.accept  = true                             
+es-do.accept  = true                             
+es-ec.accept  = true                             
+es-es.accept  = true                             
+es-gt.accept  = true                             
+es-hn.accept  = true                             
+es-mx.accept  = true                             
+es-ni.accept  = true                             
+es-pa.accept  = true                             
+es-pe.accept  = true                             
+es-pr.accept  = true                             
+es-py.accept  = true                             
+es-sv.accept  = true                             
+es-uy.accept  = true                             
+es-ve.accept  = true                             
+et.accept     = true    
+eu.accept     = true                            
+fa.accept     = true
+fa-ir.accept  = true
+ff.accept     = true
+fi.accept     = true                            
+fj.accept     = true                            
+fo.accept     = true                            
+fr.accept     = true                            
+fr-be.accept  = true                             
+fr-ca.accept  = true                             
+fr-ch.accept  = true                             
+fr-fr.accept  = true                             
+fr-lu.accept  = true                             
+fr-mc.accept  = true                             
+fur.accept    = true
+fy.accept     = true
+ga.accept     = true                            
+gd.accept     = true                            
+gl.accept     = true                            
+gn.accept     = true                            
+gu.accept     = true
+gv.accept     = true
+ha.accept     = true                            
+he.accept     = true    
+hi.accept     = true                            
+ho.accept     = true
+hsb.accept    = true
+hr.accept     = true                            
+ht.accept     = true
+hu.accept     = true                            
+hy.accept     = true                            
+hz.accept     = true
+ia.accept     = true
+id.accept     = true
+ie.accept     = true
+ig.accept     = true
+ii.accept     = true
+ik.accept     = true
+io.accept     = true
+is.accept     = true                            
+it.accept     = true                            
+it-ch.accept  = true                             
+iu.accept     = true
+ja.accept     = true                            
+jv.accept     = true
+ka.accept     = true                            
+kg.accept     = true
+ki.accept     = true
+kk.accept     = true
+kl.accept     = true                            
+km.accept     = true
+kn.accept     = true                    
+ko.accept     = true                            
+ko-kp.accept  = true                             
+ko-kr.accept  = true                             
+kok.accept    = true
+kr.accept     = true
+ks.accept     = true
+ku.accept     = true
+kv.accept     = true
+kw.accept     = true
+ky.accept     = true
+la.accept     = true
+lb.accept     = true
+lg.accept     = true
+li.accept     = true
+ln.accept     = true
+lo.accept     = true
+lt.accept     = true    
+lu.accept     = true
+lv.accept     = true    
+mg.accept     = true
+mh.accept     = true
+mi.accept     = true
+mk.accept     = true
+mk-mk.accept  = true                             
+ml.accept     = true
+mn.accept     = true                            
+mr.accept     = true
+ms.accept     = true                            
+mt.accept     = true
+my.accept     = true                            
+na.accept     = true
+nb.accept     = true
+nd.accept     = true
+ne.accept     = true
+ng.accept     = true                            
+nl.accept     = true                            
+nl-be.accept  = true                             
+nn.accept     = true                            
+no.accept     = true                            
+nr.accept     = true
+nso.accept    = true
+nv.accept     = true
+ny.accept     = true
+oc.accept     = true
+oj.accept     = true
+om.accept     = true
+or.accept     = true                            
+os.accept     = true                            
+pa.accept     = true
+pa-in.accept  = true
+pa-pk.accept  = true
+pi.accept     = true
+pl.accept     = true                            
+ps.accept     = true
+pt.accept     = true                            
+pt-br.accept  = true                             
+qu.accept     = true
+rm.accept     = true
+rn.accept     = true
+ro.accept     = true                            
+ro-md.accept  = true                             
+ro-ro.accept  = true
+ru.accept     = true                            
+ru-md.accept  = true                             
+rw.accept     = true
+sa.accept     = true
+sc.accept     = true
+sd.accept     = true
+sg.accept     = true
+si.accept     = true
+sk.accept     = true                            
+sl.accept     = true                            
+sm.accept     = true
+so.accept     = true
 son-ml.accept = true
-sq.accept = 	true				
-sr.accept = 	true				
-ss.accept =	true
-st.accept =	true
-su.accept = 	false
-sv.accept = 	true				
-sv-fi.accept = true				
-sv-se.accept = true
-sw.accept = 	true
-ta.accept = 	true
-te.accept = 	true				
-tg.accept = 	false
-th.accept = 	true				
-ti.accept = 	true
-tig.accept = 	true
-tk.accept = 	true
-tl.accept = 	true
-tlh.accept =    true
-tn.accept = 	true				
-to.accept = 	true				
-tr.accept = 	true				
-ts.accept = 	true				
-tt.accept = 	true
-tw.accept = 	false				
-ty.accept = 	false				
-ug.accept = 	false
-uk.accept = 	true				
-ur.accept = 	true				
-uz.accept = 	false				
-ve.accept = 	true				
-vi.accept = 	true				
-vo.accept = 	true				
-wa.accept = 	true
-wo.accept = 	true
-xh.accept = 	true				
-yi.accept = 	true				
-yo.accept = 	false
-za.accept =	false
-zh.accept = 	true				
-zh-cn.accept = true				
-zh-hk.accept = true				
-zh-sg.accept = true				
-zh-tw.accept = true				
-zu.accept =	true				
+sq.accept     = true                            
+sr.accept     = true                            
+ss.accept     = true
+st.accept     = true
+su.accept     = true
+sv.accept     = true                            
+sv-fi.accept  = true                             
+sv-se.accept  = true
+sw.accept     = true
+ta.accept     = true
+te.accept     = true                            
+tg.accept     = true
+th.accept     = true                            
+ti.accept     = true
+tig.accept    = true
+tk.accept     = true
+tl.accept     = true
+tlh.accept    = true
+tn.accept     = true                            
+to.accept     = true                            
+tr.accept     = true                            
+ts.accept     = true                            
+tt.accept     = true
+tw.accept     = true                            
+ty.accept     = true                            
+ug.accept     = true
+uk.accept     = true                            
+ur.accept     = true                            
+uz.accept     = true                            
+ve.accept     = true                            
+vi.accept     = true                            
+vo.accept     = true                            
+wa.accept     = true
+wo.accept     = true
+xh.accept     = true                            
+yi.accept     = true                            
+yo.accept     = true
+za.accept     = true
+zh.accept     = true                            
+zh-cn.accept  = true                             
+zh-hk.accept  = true                             
+zh-sg.accept  = true                             
+zh-tw.accept  = true                             
+zu.accept     = true                            
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -963,32 +963,16 @@ EmitObjectOp(JSContext *cx, ObjectBox *o
 
 static bool
 EmitRegExp(JSContext *cx, uint32_t index, BytecodeEmitter *bce)
 {
     return EmitIndex32(cx, JSOP_REGEXP, index, bce);
 }
 
 static bool
-EmitSlotObjectOp(JSContext *cx, JSOp op, unsigned slot, uint32_t index, BytecodeEmitter *bce)
-{
-    JS_ASSERT(JOF_OPTYPE(op) == JOF_SLOTOBJECT);
-
-    ptrdiff_t off = EmitN(cx, bce, op, SLOTNO_LEN + UINT32_INDEX_LEN);
-    if (off < 0)
-        return false;
-
-    jsbytecode *pc = bce->code(off);
-    SET_SLOTNO(pc, slot);
-    pc += SLOTNO_LEN;
-    SET_UINT32_INDEX(pc, index);
-    return true;
-}
-
-static bool
 EmitArguments(JSContext *cx, BytecodeEmitter *bce)
 {
     if (!bce->mayOverwriteArguments())
         return Emit1(cx, bce, JSOP_ARGUMENTS) >= 0;
     return EmitAtomOp(cx, cx->runtime->atomState.argumentsAtom, JSOP_NAME, bce);
 }
 
 bool
@@ -4577,53 +4561,16 @@ EmitWith(JSContext *cx, BytecodeEmitter 
     if (!EmitTree(cx, bce, pn->pn_right))
         return false;
     if (Emit1(cx, bce, JSOP_LEAVEWITH) < 0)
         return false;
     return PopStatementBCE(cx, bce);
 }
 
 static bool
-SetMethodFunction(JSContext *cx, FunctionBox *funbox, JSAtom *atom)
-{
-    RootedVarObject parent(cx);
-    parent = funbox->function()->getParent();
-
-    /*
-     * Replace a boxed function with a new one with a method atom. Methods
-     * require a function with the extended size finalize kind, which normal
-     * functions don't have. We don't eagerly allocate functions with the
-     * expanded size for boxed functions, as most functions are not methods.
-     */
-    JSFunction *fun = js_NewFunction(cx, NULL, NULL,
-                                     funbox->function()->nargs,
-                                     funbox->function()->flags,
-                                     parent,
-                                     funbox->function()->atom,
-                                     JSFunction::ExtendedFinalizeKind);
-    if (!fun)
-        return false;
-
-    JSScript *script = funbox->function()->script();
-    if (script) {
-        fun->setScript(script);
-        if (!script->typeSetFunction(cx, fun))
-            return false;
-    }
-
-    JS_ASSERT(funbox->function()->joinable());
-    fun->setJoinable();
-
-    fun->setMethodAtom(atom);
-
-    funbox->object = fun;
-    return true;
-}
-
-static bool
 EmitForIn(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
 {
     StmtInfo stmtInfo;
     PushStatement(bce, &stmtInfo, STMT_FOR_IN_LOOP, top);
 
     ParseNode *forHead = pn->pn_left;
     ParseNode *forBody = pn->pn_right;
 
@@ -5049,17 +4996,24 @@ EmitFunc(JSContext *cx, BytecodeEmitter 
         JS_ASSERT(index < JS_BIT(20));
         pn->pn_index = index;
         if (pn->isClosed() &&
             !bce->callsEval() &&
             !bce->closedVars.append(pn->pn_cookie.slot()))
         {
             return false;
         }
-        return EmitSlotObjectOp(cx, JSOP_DEFLOCALFUN, slot, index, bce);
+
+        if (NewSrcNote(cx, bce, SRC_CONTINUE) < 0)
+            return false;
+        if (!EmitIndexOp(cx, JSOP_LAMBDA, index, bce))
+            return false;
+        EMIT_UINT16_IMM_OP(JSOP_SETLOCAL, slot);
+        if (Emit1(cx, bce, JSOP_POP) < 0)
+            return false;
     }
 
     return true;
 }
 
 static bool
 EmitDo(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
 {
@@ -5375,33 +5329,16 @@ EmitStatement(JSContext *cx, BytecodeEmi
         if (!wantval &&
             pn2->isKind(PNK_ASSIGN) &&
             !MaybeEmitGroupAssignment(cx, bce, op, pn2, &op))
         {
             return false;
         }
 #endif
         if (op != JSOP_NOP) {
-            /*
-             * Specialize JSOP_SETPROP to JSOP_SETMETHOD to defer or
-             * avoid null closure cloning. Do this only for assignment
-             * statements that are not completion values wanted by a
-             * script evaluator, to ensure that the joined function
-             * can't escape directly.
-             */
-            if (!wantval &&
-                pn2->isKind(PNK_ASSIGN) &&
-                pn2->pn_left->isOp(JSOP_SETPROP) &&
-                pn2->pn_right->isOp(JSOP_LAMBDA) &&
-                pn2->pn_right->pn_funbox->joinable())
-            {
-                if (!SetMethodFunction(cx, pn2->pn_right->pn_funbox, pn2->pn_left->pn_atom))
-                    return false;
-                pn2->pn_left->setOp(JSOP_SETMETHOD);
-            }
             if (!EmitTree(cx, bce, pn2))
                 return false;
             if (Emit1(cx, bce, op) < 0)
                 return false;
         }
     } else if (!pn->isDirectivePrologueMember()) {
         /* Don't complain about directive prologue members; just don't emit their code. */
         bce->current->currentLine = pn2->pn_pos.begin.lineno;
@@ -5898,38 +5835,23 @@ EmitObject(JSContext *cx, BytecodeEmitte
             if (Emit1(cx, bce, JSOP_INITELEM) < 0)
                 return false;
         } else {
             JS_ASSERT(pn3->isKind(PNK_NAME) || pn3->isKind(PNK_STRING));
             jsatomid index;
             if (!bce->makeAtomIndex(pn3->pn_atom, &index))
                 return false;
 
-            /* Check whether we can optimize to JSOP_INITMETHOD. */
-            ParseNode *init = pn2->pn_right;
-            bool lambda = init->isOp(JSOP_LAMBDA);
-            if (lambda)
-                ++methodInits;
-            if (op == JSOP_INITPROP && lambda && init->pn_funbox->joinable()) {
+            /*
+             * Disable NEWOBJECT on initializers that set __proto__, which has
+             * a non-standard setter on objects.
+             */
+            if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
                 obj = NULL;
-                op = JSOP_INITMETHOD;
-                if (!SetMethodFunction(cx, init->pn_funbox, pn3->pn_atom))
-                    return JS_FALSE;
-                pn2->setOp(op);
-            } else {
-                /*
-                 * Disable NEWOBJECT on initializers that set __proto__, which has
-                 * a non-standard setter on objects.
-                 */
-                if (pn3->pn_atom == cx->runtime->atomState.protoAtom)
-                    obj = NULL;
-                op = JSOP_INITPROP;
-                if (lambda)
-                    ++slowMethodInits;
-            }
+            op = JSOP_INITPROP;
 
             if (obj) {
                 JS_ASSERT(!obj->inDictionaryMode());
                 if (!DefineNativeProperty(cx, obj, ATOM_TO_JSID(pn3->pn_atom),
                                           UndefinedValue(), NULL, NULL,
                                           JSPROP_ENUMERATE, 0, 0))
                 {
                     return false;
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -156,136 +156,137 @@ struct StmtInfo {
  */
 #define CATCHNOTE(stmt)  ((stmt).update)
 #define GOSUBS(stmt)     ((stmt).breaks)
 #define GUARDJUMP(stmt)  ((stmt).continues)
 
 #define SET_STATEMENT_TOP(stmt, top)                                          \
     ((stmt)->update = (top), (stmt)->breaks = (stmt)->continues = (-1))
 
-#define TCF_COMPILING           0x01 /* TreeContext is BytecodeEmitter */
-#define TCF_IN_FUNCTION         0x02 /* parsing inside function body */
-#define TCF_RETURN_EXPR         0x04 /* function has 'return expr;' */
-#define TCF_RETURN_VOID         0x08 /* function has 'return;' */
-#define TCF_IN_FOR_INIT         0x10 /* parsing init expr of for; exclude 'in' */
-#define TCF_FUN_SETS_OUTER_NAME 0x20 /* function set outer name (lexical or free) */
-#define TCF_FUN_PARAM_ARGUMENTS 0x40 /* function has parameter named arguments */
-#define TCF_FUN_LOCAL_ARGUMENTS 0x80 /* function may contain a local named arguments */
-#define TCF_FUN_USES_ARGUMENTS 0x100 /* function uses arguments except as a
-                                        parameter name */
-#define TCF_FUN_HEAVYWEIGHT    0x200 /* function needs Call object per call */
-#define TCF_FUN_IS_GENERATOR   0x400 /* parsed yield statement in function */
-#define TCF_FUN_USES_OWN_NAME  0x800 /* named function expression that uses its
-                                        own name */
-#define TCF_HAS_FUNCTION_STMT 0x1000 /* block contains a function statement */
-#define TCF_GENEXP_LAMBDA     0x2000 /* flag lambda from generator expression */
-#define TCF_COMPILE_N_GO      0x4000 /* compile-and-go mode of script, can
-                                        optimize name references based on scope
-                                        chain */
-#define TCF_NO_SCRIPT_RVAL    0x8000 /* API caller does not want result value
-                                        from global script */
-/*
- * Set when parsing a declaration-like destructuring pattern.  This
- * flag causes PrimaryExpr to create PN_NAME parse nodes for variable
- * references which are not hooked into any definition's use chain,
- * added to any tree context's AtomList, etc. etc.  CheckDestructuring
- * will do that work later.
- *
- * The comments atop CheckDestructuring explain the distinction
- * between assignment-like and declaration-like destructuring
- * patterns, and why they need to be treated differently.
- */
-#define TCF_DECL_DESTRUCTURING  0x10000
+JS_ENUM_HEADER(TreeContextFlags, uint32_t)
+{
+    /* TreeContext is BytecodeEmitter */
+    TCF_COMPILING =                            0x1,
+
+    /* parsing inside function body */
+    TCF_IN_FUNCTION =                          0x2,
+
+    /* function has 'return expr;' */
+    TCF_RETURN_EXPR =                          0x4,
+
+    /* function has 'return;' */
+    TCF_RETURN_VOID =                          0x8,
+
+    /* parsing init expr of for; exclude 'in' */
+    TCF_IN_FOR_INIT =                         0x10,
+
+    /* function has parameter named arguments */
+    TCF_FUN_PARAM_ARGUMENTS =                 0x20,
+
+    /* function may contain a local named arguments */
+    TCF_FUN_LOCAL_ARGUMENTS =                 0x40,
 
-/*
- * This function/global/eval code body contained a Use Strict Directive. Treat
- * certain strict warnings as errors, and forbid the use of 'with'. See also
- * TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and JSREPORT_STRICT_ERROR.
- */
-#define TCF_STRICT_MODE_CODE    0x20000
+    /* function uses arguments except as a parameter name */
+    TCF_FUN_USES_ARGUMENTS =                  0x80,
+
+    /* function needs Call object per call */
+    TCF_FUN_HEAVYWEIGHT =                    0x100,
+
+    /* parsed yield statement in function */
+    TCF_FUN_IS_GENERATOR =                   0x200,
+
+    /* named function expression that uses its own name */
+    TCF_FUN_USES_OWN_NAME =                  0x400,
 
-/* bits 0x40000 and 0x80000 are unused */
+    /* block contains a function statement */
+    TCF_HAS_FUNCTION_STMT =                  0x800,
+
+    /* flag lambda from generator expression */
+    TCF_GENEXP_LAMBDA =                     0x1000,
 
-/*
- * "Module pattern", i.e., a lambda that is immediately applied and the whole
- * of an expression statement.
- */
-#define TCF_FUN_MODULE_PATTERN 0x200000
+    /* script can optimize name references based on scope chain */
+    TCF_COMPILE_N_GO =                      0x2000,
+
+    /* API caller does not want result value from global script */
+    TCF_NO_SCRIPT_RVAL =                    0x4000,
 
-/*
- * Flag to prevent a non-escaping function from being optimized into a null
- * closure (i.e., a closure that needs only its global object for free variable
- * resolution), because this function contains a closure that needs one or more
- * scope objects surrounding it (i.e., a Call object for an outer heavyweight
- * function). See bug 560234.
- */
-#define TCF_FUN_ENTRAINS_SCOPES 0x400000
-
-/* The function calls 'eval'. */
-#define TCF_FUN_CALLS_EVAL       0x800000
+    /*
+     * Set when parsing a declaration-like destructuring pattern.  This flag
+     * causes PrimaryExpr to create PN_NAME parse nodes for variable references
+     * which are not hooked into any definition's use chain, added to any tree
+     * context's AtomList, etc. etc.  CheckDestructuring will do that work
+     * later.
+     *
+     * The comments atop CheckDestructuring explain the distinction between
+     * assignment-like and declaration-like destructuring patterns, and why
+     * they need to be treated differently.
+     */
+    TCF_DECL_DESTRUCTURING =                0x8000,
 
-/* The function mutates a positional (non-destructuring) parameter. */
-#define TCF_FUN_MUTATES_PARAMETER 0x1000000
+    /*
+     * This function/global/eval code body contained a Use Strict Directive.
+     * Treat certain strict warnings as errors, and forbid the use of 'with'.
+     * See also TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and
+     * JSREPORT_STRICT_ERROR.
+     */
+    TCF_STRICT_MODE_CODE =                 0x10000,
 
-/*
- * Compiling an eval() script.
- */
-#define TCF_COMPILE_FOR_EVAL     0x2000000
+    /* The function calls 'eval'. */
+    TCF_FUN_CALLS_EVAL =                   0x20000,
 
-/*
- * The function or a function that encloses it may define new local names
- * at runtime through means other than calling eval.
- */
-#define TCF_FUN_MIGHT_ALIAS_LOCALS  0x4000000
+    /* The function mutates a positional (non-destructuring) parameter. */
+    TCF_FUN_MUTATES_PARAMETER =            0x40000,
+
+    /* Compiling an eval() script. */
+    TCF_COMPILE_FOR_EVAL =                0x100000,
 
-/*
- * The script contains singleton initialiser JSOP_OBJECT.
- */
-#define TCF_HAS_SINGLETONS       0x8000000
+    /*
+     * The function or a function that encloses it may define new local names
+     * at runtime through means other than calling eval.
+     */
+    TCF_FUN_MIGHT_ALIAS_LOCALS =          0x200000,
 
-/*
- * Some enclosing scope is a with-statement or E4X filter-expression.
- */
-#define TCF_IN_WITH             0x10000000
+    /* The script contains singleton initialiser JSOP_OBJECT. */
+    TCF_HAS_SINGLETONS =                  0x400000,
+
+    /* Some enclosing scope is a with-statement or E4X filter-expression. */
+    TCF_IN_WITH =                         0x800000,
 
-/*
- * This function does something that can extend the set of bindings in its
- * call objects --- it does a direct eval in non-strict code, or includes a
- * function statement (as opposed to a function definition).
- *
- * This flag is *not* inherited by enclosed or enclosing functions; it
- * applies only to the function in whose flags it appears.
- */
-#define TCF_FUN_EXTENSIBLE_SCOPE 0x20000000
+    /*
+     * This function does something that can extend the set of bindings in its
+     * call objects --- it does a direct eval in non-strict code, or includes a
+     * function statement (as opposed to a function definition).
+     *
+     * This flag is *not* inherited by enclosed or enclosing functions; it
+     * applies only to the function in whose flags it appears.
+     */
+    TCF_FUN_EXTENSIBLE_SCOPE =           0x1000000,
 
-/*
- * The caller is JS_Compile*Script*.
- */
-#define TCF_NEED_SCRIPT_GLOBAL 0x40000000
+    /* The caller is JS_Compile*Script*. */
+    TCF_NEED_SCRIPT_GLOBAL =             0x2000000
 
-/*
- * Flags to check for return; vs. return expr; in a function.
- */
-#define TCF_RETURN_FLAGS        (TCF_RETURN_EXPR | TCF_RETURN_VOID)
+} JS_ENUM_FOOTER(TreeContextFlags);
+
+/* Flags to check for return; vs. return expr; in a function. */
+static const uint32_t TCF_RETURN_FLAGS = TCF_RETURN_EXPR | TCF_RETURN_VOID;
 
 /*
  * Sticky deoptimization flags to propagate from FunctionBody.
  */
-#define TCF_FUN_FLAGS           (TCF_FUN_SETS_OUTER_NAME |                    \
-                                 TCF_FUN_USES_ARGUMENTS  |                    \
-                                 TCF_FUN_PARAM_ARGUMENTS |                    \
-                                 TCF_FUN_LOCAL_ARGUMENTS |                    \
-                                 TCF_FUN_HEAVYWEIGHT     |                    \
-                                 TCF_FUN_IS_GENERATOR    |                    \
-                                 TCF_FUN_USES_OWN_NAME   |                    \
-                                 TCF_FUN_CALLS_EVAL      |                    \
-                                 TCF_FUN_MIGHT_ALIAS_LOCALS |                 \
-                                 TCF_FUN_MUTATES_PARAMETER |                  \
-                                 TCF_STRICT_MODE_CODE    |                    \
-                                 TCF_FUN_EXTENSIBLE_SCOPE)
+static const uint32_t TCF_FUN_FLAGS = TCF_FUN_USES_ARGUMENTS |
+                                      TCF_FUN_PARAM_ARGUMENTS |
+                                      TCF_FUN_LOCAL_ARGUMENTS |
+                                      TCF_FUN_HEAVYWEIGHT |
+                                      TCF_FUN_IS_GENERATOR |
+                                      TCF_FUN_USES_OWN_NAME |
+                                      TCF_FUN_CALLS_EVAL |
+                                      TCF_FUN_MIGHT_ALIAS_LOCALS |
+                                      TCF_FUN_MUTATES_PARAMETER |
+                                      TCF_STRICT_MODE_CODE |
+                                      TCF_FUN_EXTENSIBLE_SCOPE;
 
 struct BytecodeEmitter;
 
 struct TreeContext {                /* tree context for semantic checks */
     uint32_t        flags;          /* statement state flags, see above */
     uint32_t        bodyid;         /* block number of program/function body */
     uint32_t        blockidGen;     /* preincremented block number generator */
     uint32_t        parenDepth;     /* nesting depth of parens that might turn out
@@ -438,24 +439,26 @@ struct TreeContext {                /* t
         JS_ASSERT(inFunction());
         JS_ASSERT_IF(inStrictMode(),
                      !(flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS)));
         return !inStrictMode() &&
                (callsEval() ||
                 flags & (TCF_FUN_PARAM_ARGUMENTS | TCF_FUN_LOCAL_ARGUMENTS));
     }
 
+    void noteLocalOverwritesArguments() {
+        flags |= TCF_FUN_LOCAL_ARGUMENTS;
+    }
+
     void noteArgumentsNameUse(ParseNode *node) {
         JS_ASSERT(inFunction());
         JS_ASSERT(node->isKind(PNK_NAME));
         JS_ASSERT(node->pn_atom == parser->context->runtime->atomState.argumentsAtom);
         countArgumentsUse(node);
         flags |= TCF_FUN_USES_ARGUMENTS;
-        if (funbox)
-            funbox->node->pn_dflags |= PND_FUNARG;
     }
 
     /*
      * Uses of |arguments| must be noted so that such uses can be forbidden if
      * they occur inside generator expressions (which desugar to functions and
      * yields, in which |arguments| would have an entirely different meaning).
      */
     void countArgumentsUse(ParseNode *node) {
--- a/js/src/frontend/ParseNode.cpp
+++ b/js/src/frontend/ParseNode.cpp
@@ -104,25 +104,16 @@ ParseNode::clear()
     pn_type = PNK_LIMIT;
     setOp(JSOP_NOP);
     pn_used = pn_defn = false;
     pn_arity = PN_NULLARY;
     pn_parens = false;
 }
 
 bool
-FunctionBox::joinable() const
-{
-    return function()->isNullClosure() &&
-           (tcflags & (TCF_FUN_USES_ARGUMENTS |
-                       TCF_FUN_USES_OWN_NAME |
-                       TCF_COMPILE_N_GO)) == TCF_COMPILE_N_GO;
-}
-
-bool
 FunctionBox::inAnyDynamicScope() const
 {
     for (const FunctionBox *funbox = this; funbox; funbox = funbox->parent) {
         if (funbox->tcflags & (TCF_IN_WITH | TCF_FUN_EXTENSIBLE_SCOPE))
             return true;
     }
     return false;
 }
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -760,25 +760,24 @@ struct ParseNode {
 #define PND_CONST       0x02            /* const binding (orthogonal to let) */
 #define PND_INITIALIZED 0x04            /* initialized declaration */
 #define PND_ASSIGNED    0x08            /* set if ever LHS of assignment */
 #define PND_TOPLEVEL    0x10            /* see isTopLevel() below */
 #define PND_BLOCKCHILD  0x20            /* use or def is direct block child */
 #define PND_GVAR        0x40            /* gvar binding, can't close over
                                            because it could be deleted */
 #define PND_PLACEHOLDER 0x80            /* placeholder definition for lexdep */
-#define PND_FUNARG     0x100            /* downward or upward funarg usage */
-#define PND_BOUND      0x200            /* bound to a stack or global slot */
-#define PND_DEOPTIMIZED 0x400           /* former pn_used name node, pn_lexdef
+#define PND_BOUND      0x100            /* bound to a stack or global slot */
+#define PND_DEOPTIMIZED 0x200           /* former pn_used name node, pn_lexdef
                                            still valid, but this use no longer
                                            optimizable via an upvar opcode */
-#define PND_CLOSED      0x800           /* variable is closed over */
+#define PND_CLOSED      0x400           /* variable is closed over */
 
 /* Flags to propagate from uses to definition. */
-#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_FUNARG | PND_CLOSED)
+#define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
 
 /* PN_LIST pn_xflags bits. */
 #define PNX_STRCAT      0x01            /* PNK_ADD list has string term */
 #define PNX_CANTFOLD    0x02            /* PNK_ADD list has unfoldable term */
 #define PNX_POPVAR      0x04            /* PNK_VAR or PNK_CONST last result
                                            needs popping */
 #define PNX_FORINVAR    0x08            /* PNK_VAR is left kid of PNK_FORIN node
                                            which is left kid of PNK_FOR */
@@ -811,36 +810,32 @@ struct ParseNode {
 
     bool isLet() const          { return test(PND_LET); }
     bool isConst() const        { return test(PND_CONST); }
     bool isInitialized() const  { return test(PND_INITIALIZED); }
     bool isBlockChild() const   { return test(PND_BLOCKCHILD); }
     bool isPlaceholder() const  { return test(PND_PLACEHOLDER); }
     bool isDeoptimized() const  { return test(PND_DEOPTIMIZED); }
     bool isAssigned() const     { return test(PND_ASSIGNED); }
-    bool isFunArg() const       { return test(PND_FUNARG); }
     bool isClosed() const       { return test(PND_CLOSED); }
 
     /*
      * True iff this definition creates a top-level binding in the overall
      * script being compiled -- that is, it affects the whole program's
      * bindings, not bindings for a specific function (unless this definition
      * is in the outermost scope in eval code, executed within a function) or
      * the properties of a specific object (through the with statement).
      *
      * NB: Function sub-statements found in overall program code and not nested
      *     within other functions are not currently top level, even though (if
      *     executed) they do create top-level bindings; there is no particular
      *     rationale for this behavior.
      */
     bool isTopLevel() const     { return test(PND_TOPLEVEL); }
 
-    /* Defined below, see after struct Definition. */
-    void setFunArg();
-
     void become(ParseNode *pn2);
     void clear();
 
     /* True if pn is a parsenode representing a literal constant. */
     bool isLiteral() const {
         return isKind(PNK_NUMBER) ||
                isKind(PNK_STRING) ||
                isKind(PNK_TRUE) ||
@@ -1426,36 +1421,16 @@ void DumpParseTree(ParseNode *pn, int in
  *
  * Thus if a later var x is parsed in the outer function satisfying an earlier
  * inner function's use of x, we will remove dn from tc->lexdeps and re-use it
  * as the new definition node in the outer function's parse tree.
  *
  * When the compiler unwinds from the outermost tc, tc->lexdeps contains the
  * definition nodes with use chains for all free variables. These are either
  * global variables or reference errors.
- *
- * We analyze whether a binding is initialized, whether the bound names is ever
- * assigned apart from its initializer, and if the bound name definition or use
- * is in a direct child of a block. These PND_* flags allow a subset dominance
- * computation telling whether an initialized var dominates its uses. An inner
- * function using only such outer vars (and formal parameters) can be optimized
- * into a flat closure. See JSOP_{GET,CALL}DSLOT.
- *
- * Another important subset dominance relation: ... { var x = ...; ... x ... }
- * where x is not assigned after initialization and not used outside the block.
- * This style is common in the absence of 'let'. Even though the var x is not
- * at top level, we can tell its initialization dominates all uses cheaply,
- * because the above one-pass algorithm sees the definition before any uses,
- * and because all uses are contained in the same block as the definition.
- *
- * We also analyze function uses to flag upward/downward funargs.  If a lambda
- * post-dominates each of its upvars' sole, inevitable (i.e. not hidden behind
- * conditions or within loops or the like) initialization or assignment; then
- * we can optimize the lambda as a flat closure (after Chez Scheme's display
- * closures).
  */
 #define dn_uses         pn_link
 
 struct Definition : public ParseNode
 {
     /*
      * We store definition pointers in PN_NAMESET AtomDefnMapPtrs in the AST,
      * but due to redefinition these nodes may become uses of other
@@ -1523,46 +1498,27 @@ class ParseNodeAllocator {
     ParseNode *freelist;
 };
 
 inline bool
 ParseNode::test(unsigned flag) const
 {
     JS_ASSERT(pn_defn || pn_arity == PN_FUNC || pn_arity == PN_NAME);
 #ifdef DEBUG
-    if ((flag & (PND_ASSIGNED | PND_FUNARG)) && pn_defn && !(pn_dflags & flag)) {
+    if ((flag & PND_ASSIGNED) && pn_defn && !(pn_dflags & flag)) {
         for (ParseNode *pn = ((Definition *) this)->dn_uses; pn; pn = pn->pn_link) {
             JS_ASSERT(!pn->pn_defn);
             JS_ASSERT(!(pn->pn_dflags & flag));
         }
     }
 #endif
     return !!(pn_dflags & flag);
 }
 
 inline void
-ParseNode::setFunArg()
-{
-    /*
-     * pn_defn NAND pn_used must be true, per this chart:
-     *
-     *   pn_defn pn_used
-     *         0       0        anonymous function used implicitly, e.g. by
-     *                          hidden yield in a genexp
-     *         0       1        a use of a definition or placeholder
-     *         1       0        a definition or placeholder
-     *         1       1        error: this case must not be possible
-     */
-    JS_ASSERT(!(pn_defn & pn_used));
-    if (pn_used)
-        pn_lexdef->pn_dflags |= PND_FUNARG;
-    pn_dflags |= PND_FUNARG;
-}
-
-inline void
 LinkUseToDef(ParseNode *pn, Definition *dn, TreeContext *tc)
 {
     JS_ASSERT(!pn->isUsed());
     JS_ASSERT(!pn->isDefn());
     JS_ASSERT(pn != dn->dn_uses);
     pn->pn_link = dn->dn_uses;
     dn->dn_uses = pn;
     dn->pn_dflags |= pn->pn_dflags & PND_USE2DEF_FLAGS;
@@ -1593,18 +1549,16 @@ struct FunctionBox : public ObjectBox
     Bindings            bindings;               /* bindings for this function */
     uint32_t            queued:1,
                         inLoop:1,               /* in a loop in parent function */
                         level:JSFB_LEVEL_BITS;
     uint32_t            tcflags;
 
     JSFunction *function() const { return (JSFunction *) object; }
 
-    bool joinable() const;
-
     /*
      * True if this function is inside the scope of a with-statement, an E4X
      * filter-expression, or a function that uses direct eval.
      */
     bool inAnyDynamicScope() const;
 
     /* 
      * Must this function's descendants be marked as having an extensible
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1064,43 +1064,20 @@ LeaveFunction(ParseNode *fn, TreeContext
             JSAtom *atom = r.front().key();
             Definition *dn = r.front().value();
             JS_ASSERT(dn->isPlaceholder());
 
             if (atom == funName && kind == Expression) {
                 dn->setOp(JSOP_CALLEE);
                 dn->pn_cookie.set(funtc->staticLevel, UpvarCookie::CALLEE_SLOT);
                 dn->pn_dflags |= PND_BOUND;
-
-                /*
-                 * If this named function expression uses its own name other
-                 * than to call itself, flag this function specially.
-                 */
-                if (dn->isFunArg())
-                    funbox->tcflags |= TCF_FUN_USES_OWN_NAME;
                 foundCallee = 1;
                 continue;
             }
 
-            if (!(funbox->tcflags & TCF_FUN_SETS_OUTER_NAME) &&
-                dn->isAssigned()) {
-                /*
-                 * Make sure we do not fail to set TCF_FUN_SETS_OUTER_NAME if
-                 * any use of dn in funtc assigns. See NoteLValue for the easy
-                 * backward-reference case; this is the hard forward-reference
-                 * case where we pay a higher price.
-                 */
-                for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
-                    if (pnu->isAssigned() && pnu->pn_blockid >= funtc->bodyid) {
-                        funbox->tcflags |= TCF_FUN_SETS_OUTER_NAME;
-                        break;
-                    }
-                }
-            }
-
             Definition *outer_dn = tc->decls.lookupFirst(atom);
 
             /*
              * Make sure to deoptimize lexical dependencies that are polluted
              * by eval or with, to safely bind globals (see bug 561923).
              */
             if (funtc->callsEval() ||
                 (outer_dn && tc->innermostWith &&
@@ -1376,33 +1353,23 @@ Parser::functionDef(PropertyName *funNam
     JS_ASSERT_IF(kind == Statement, funName);
 
     /* Make a TOK_FUNCTION node. */
     ParseNode *pn = FunctionNode::create(PNK_FUNCTION, tc);
     if (!pn)
         return NULL;
     pn->pn_body = NULL;
     pn->pn_cookie.makeFree();
-
-    /*
-     * If this is a function expression, mark this function as escaping (as a
-     * "funarg") unless it is immediately applied (we clear PND_FUNARG if so --
-     * see memberExpr).
-     *
-     * Treat function sub-statements (those not at body level of a function or
-     * program) as escaping funargs, since we can't statically analyze their
-     * definitions and uses.
-     */
-    bool bodyLevel = tc->atBodyLevel();
-    pn->pn_dflags = (kind == Expression || !bodyLevel) ? PND_FUNARG : 0;
+    pn->pn_dflags = 0;
 
     /*
      * Record names for function statements in tc->decls so we know when to
      * avoid optimizing variable references that might name a function.
      */
+    bool bodyLevel = tc->atBodyLevel();
     if (kind == Statement) {
         if (Definition *dn = tc->decls.lookupFirst(funName)) {
             Definition::Kind dn_kind = dn->kind();
 
             JS_ASSERT(!dn->isUsed());
             JS_ASSERT(dn->isDefn());
 
             if (context->hasStrictOption() || dn_kind == Definition::CONST) {
@@ -1633,41 +1600,36 @@ Parser::functionDef(PropertyName *funNam
      * If we collected flags that indicate nested heavyweight functions, or
      * this function contains heavyweight-making statements (with statement,
      * visible eval call, or assignment to 'arguments'), flag the function as
      * heavyweight (requiring a call object per invocation).
      */
     if (funtc.flags & TCF_FUN_HEAVYWEIGHT) {
         fun->flags |= JSFUN_HEAVYWEIGHT;
         outertc->flags |= TCF_FUN_HEAVYWEIGHT;
-    } else {
-        /*
-         * If this function is not at body level of a program or function (i.e.
-         * it is a function statement that is not a direct child of a program
-         * or function), then our enclosing function, if any, must be
-         * heavyweight.
-         */
-        if (!bodyLevel && kind == Statement)
-            outertc->flags |= TCF_FUN_HEAVYWEIGHT;
     }
 
     JSOp op = JSOP_NOP;
     if (kind == Expression) {
         op = JSOP_LAMBDA;
     } else {
         if (!bodyLevel) {
             /*
              * Extension: in non-strict mode code, a function statement not at
              * the top level of a function body or whole program, e.g., in a
              * compound statement such as the "then" part of an "if" statement,
              * binds a closure only if control reaches that sub-statement.
              */
             JS_ASSERT(!outertc->inStrictMode());
             op = JSOP_DEFFUN;
             outertc->noteMightAliasLocals();
+            outertc->noteHasExtensibleScope();
+            outertc->flags |= TCF_FUN_HEAVYWEIGHT;
+            if (fun->atom == context->runtime->atomState.argumentsAtom)
+                outertc->noteLocalOverwritesArguments();
         }
     }
 
     funbox->kids = funtc.functionList;
 
     pn->pn_funbox = funbox;
     pn->setOp(op);
     if (pn->pn_body) {
@@ -1845,19 +1807,22 @@ Parser::statements()
              *
              * TCF_HAS_FUNCTION_STMT is for the TOK_LC case in Statement. It
              * is relevant only for function definitions not at body-level,
              * which we call function statements.
              */
             if (tc->atBodyLevel()) {
                 pn->pn_xflags |= PNX_FUNCDEFS;
             } else {
+                /*
+                 * General deoptimization was done in functionDef, here we just
+                 * need to tell TOK_LC in Parser::statement to add braces.
+                 */
+                JS_ASSERT(tc->hasExtensibleScope());
                 tc->flags |= TCF_HAS_FUNCTION_STMT;
-                /* Function statements extend the Call object at runtime. */
-                tc->noteHasExtensibleScope();
             }
         }
         pn->append(next);
     }
 
     /*
      * Handle the case where there was a let declaration under this block.  If
      * it replaced tc->blockNode with a new block node then we must refresh pn
@@ -2077,17 +2042,17 @@ DefineGlobal(ParseNode *pn, BytecodeEmit
              *   2) Configurable properties.
              *   3) Properties without slots, or with getters/setters.
              */
             const Shape *shape = (const Shape *)prop;
             if (funbox ||
                 globalObj != holder ||
                 shape->configurable() ||
                 !shape->hasSlot() ||
-                !shape->hasDefaultGetterOrIsMethod() ||
+                !shape->hasDefaultGetter() ||
                 !shape->hasDefaultSetter()) {
                 return true;
             }
 
             def = GlobalScope::GlobalDef(shape->slot());
         } else {
             def = GlobalScope::GlobalDef(name, funbox);
         }
@@ -2408,35 +2373,33 @@ NoteLValue(JSContext *cx, ParseNode *pn,
             pn->isBlockChild() &&
             dn->pn_blockid == pn->pn_blockid &&
             dn->pn_pos.end <= pn->pn_pos.begin &&
             dn->dn_uses == pn) {
             dflag = PND_INITIALIZED;
         }
 
         dn->pn_dflags |= dflag;
-
-        if (dn->pn_cookie.isFree() || dn->frameLevel() < tc->staticLevel)
-            tc->flags |= TCF_FUN_SETS_OUTER_NAME;
     }
 
     pn->pn_dflags |= dflag;
 
     /*
      * Both arguments and the enclosing function's name are immutable bindings
      * in ES5, so assignments to them must do nothing or throw a TypeError
      * depending on code strictness.  Assignment to arguments is a syntax error
      * in strict mode and thus cannot happen.  Outside strict mode, we optimize
      * away assignment to the function name.  For assignment to function name
      * to fail in strict mode, we must have a binding for it in the scope
      * chain; we ensure this happens by making such functions heavyweight.
      */
     JSAtom *lname = pn->pn_atom;
     if (lname == cx->runtime->atomState.argumentsAtom) {
-        tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
+        tc->flags |= TCF_FUN_HEAVYWEIGHT;
+        tc->noteLocalOverwritesArguments();
         tc->countArgumentsUse(pn);
     } else if (tc->inFunction() && lname == tc->fun()->atom) {
         tc->flags |= TCF_FUN_HEAVYWEIGHT;
     }
 }
 
 #if JS_HAS_DESTRUCTURING
 
@@ -2447,18 +2410,20 @@ BindDestructuringVar(JSContext *cx, Bind
 
     /*
      * Destructuring is a form of assignment, so just as for an initialized
      * simple variable, we must check for assignment to 'arguments' and flag
      * the enclosing function (if any) as heavyweight.
      */
     JS_ASSERT(pn->isKind(PNK_NAME));
     atom = pn->pn_atom;
-    if (atom == cx->runtime->atomState.argumentsAtom)
-        tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
+    if (atom == cx->runtime->atomState.argumentsAtom) {
+        tc->flags |= TCF_FUN_HEAVYWEIGHT;
+        tc->noteLocalOverwritesArguments();
+    }
 
     data->pn = pn;
     if (!data->binder(cx, data, atom, tc))
         return JS_FALSE;
 
     /*
      * Select the appropriate name-setting opcode, respecting eager selection
      * done by the data->binder function.
@@ -3917,46 +3882,33 @@ Parser::expressionStatement()
     }
 
     ParseNode *pn = UnaryNode::create(PNK_SEMI, tc);
     if (!pn)
         return NULL;
     pn->pn_pos = pn2->pn_pos;
     pn->pn_kid = pn2;
 
-    switch (pn2->getKind()) {
-      case PNK_LP:
-        /*
-         * Flag lambdas immediately applied as statements as instances of
-         * the JS "module pattern". See CheckForImmediatelyAppliedLambda.
-         */
-        if (pn2->pn_head->isKind(PNK_FUNCTION) &&
-            !pn2->pn_head->pn_funbox->node->isFunArg()) {
-            pn2->pn_head->pn_funbox->tcflags |= TCF_FUN_MODULE_PATTERN;
-        }
-        break;
-      case PNK_ASSIGN:
+    if (pn2->getKind() == PNK_ASSIGN) {
         /*
          * Keep track of all apparent methods created by assignments such
          * as this.foo = function (...) {...} in a function that could end
          * up a constructor function. See Parser::setFunctionKinds.
          */
         JS_ASSERT(pn2->isOp(JSOP_NOP));
         if (tc->funbox &&
             pn2->pn_left->isOp(JSOP_SETPROP) &&
             pn2->pn_left->pn_expr->isKind(PNK_THIS) &&
             pn2->pn_right->isOp(JSOP_LAMBDA))
         {
             JS_ASSERT(!pn2->isDefn());
             JS_ASSERT(!pn2->isUsed());
             pn2->pn_right->pn_link = tc->funbox->methods;
             tc->funbox->methods = pn2->pn_right;
         }
-        break;
-      default:;
     }
 
     /* Check termination of this primitive statement. */
     return MatchOrInsertSemicolon(context, &tokenStream) ? pn : NULL;
 }
 
 ParseNode *
 Parser::statement()
@@ -4418,18 +4370,20 @@ Parser::variables(ParseNodeKind kind, St
 
             NoteLValue(context, pn2, tc, data.fresh ? PND_INITIALIZED : PND_ASSIGNED);
 
             /* The declarator's position must include the initializer. */
             pn2->pn_pos.end = init->pn_pos.end;
 
             if (tc->inFunction() && name == context->runtime->atomState.argumentsAtom) {
                 tc->noteArgumentsNameUse(pn2);
-                if (!blockObj)
-                    tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
+                if (!blockObj) {
+                    tc->flags |= TCF_FUN_HEAVYWEIGHT;
+                    tc->noteLocalOverwritesArguments();
+                }
             }
         }
     } while (tokenStream.matchToken(TOK_COMMA));
 
     pn->pn_pos.end = pn->last()->pn_pos.end;
     return pn;
 }
 
@@ -5597,17 +5551,17 @@ Parser::generatorExpr(ParseNode *kid)
     pn->pn_hidden = true;
 
     /* Make a new node for the desugared generator function. */
     ParseNode *genfn = FunctionNode::create(PNK_FUNCTION, tc);
     if (!genfn)
         return NULL;
     genfn->setOp(JSOP_LAMBDA);
     JS_ASSERT(!genfn->pn_body);
-    genfn->pn_dflags = PND_FUNARG;
+    genfn->pn_dflags = 0;
 
     {
         TreeContext *outertc = tc;
         TreeContext gentc(tc->parser);
         if (!gentc.init(context))
             return NULL;
 
         FunctionBox *funbox = EnterFunction(genfn, &gentc);
@@ -5706,48 +5660,32 @@ Parser::argumentList(ParseNode *listNode
 
     if (tokenStream.getToken() != TOK_RP) {
         reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_PAREN_AFTER_ARGS);
         return JS_FALSE;
     }
     return JS_TRUE;
 }
 
-/* Check for an immediately-applied (new'ed) lambda and clear PND_FUNARG. */
-static ParseNode *
-CheckForImmediatelyAppliedLambda(ParseNode *pn)
-{
-    if (pn->isKind(PNK_FUNCTION)) {
-        JS_ASSERT(pn->isArity(PN_FUNC));
-
-        FunctionBox *funbox = pn->pn_funbox;
-        JS_ASSERT((funbox->function())->flags & JSFUN_LAMBDA);
-        if (!(funbox->tcflags & (TCF_FUN_USES_ARGUMENTS | TCF_FUN_USES_OWN_NAME)))
-            pn->pn_dflags &= ~PND_FUNARG;
-    }
-    return pn;
-}
-
 ParseNode *
 Parser::memberExpr(JSBool allowCallSyntax)
 {
     ParseNode *lhs;
 
     JS_CHECK_RECURSION(context, return NULL);
 
     /* Check for new expression first. */
     TokenKind tt = tokenStream.getToken(TSF_OPERAND);
     if (tt == TOK_NEW) {
         lhs = ListNode::create(PNK_NEW, tc);
         if (!lhs)
             return NULL;
         ParseNode *ctorExpr = memberExpr(JS_FALSE);
         if (!ctorExpr)
             return NULL;
-        ctorExpr = CheckForImmediatelyAppliedLambda(ctorExpr);
         lhs->setOp(JSOP_NEW);
         lhs->initList(ctorExpr);
         lhs->pn_pos.begin = ctorExpr->pn_pos.begin;
 
         if (tokenStream.matchToken(TOK_LP) && !argumentList(lhs))
             return NULL;
         if (lhs->pn_count > ARGC_LIMIT) {
             JS_ReportErrorNumber(context, js_GetErrorMessage, NULL,
@@ -5911,17 +5849,16 @@ Parser::memberExpr(JSBool allowCallSynta
             if (!nextMember)
                 return NULL;
         } else if (allowCallSyntax && tt == TOK_LP) {
             nextMember = ListNode::create(PNK_LP, tc);
             if (!nextMember)
                 return NULL;
             nextMember->setOp(JSOP_CALL);
 
-            lhs = CheckForImmediatelyAppliedLambda(lhs);
             if (lhs->isOp(JSOP_NAME)) {
                 if (lhs->pn_atom == context->runtime->atomState.evalAtom) {
                     /* Select JSOP_EVAL and flag tc as heavyweight. */
                     nextMember->setOp(JSOP_EVAL);
                     tc->noteCallsEval();
                     tc->flags |= TCF_FUN_HEAVYWEIGHT;
                     /*
                      * In non-strict mode code, direct calls to eval can add
@@ -6076,17 +6013,18 @@ Parser::qualifiedSuffix(ParseNode *pn)
     JS_ASSERT(!tc->inStrictMode());
 
     JS_ASSERT(tokenStream.currentToken().type == TOK_DBLCOLON);
     ParseNode *pn2 = NameNode::create(PNK_DBLCOLON, NULL, tc);
     if (!pn2)
         return NULL;
 
     /* This qualifiedSuffice may refer to 'arguments'. */
-    tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
+    tc->flags |= TCF_FUN_HEAVYWEIGHT;
+    tc->noteLocalOverwritesArguments();
 
     /* Left operand of :: must be evaluated if it is an identifier. */
     if (pn->isOp(JSOP_QNAMEPART))
         pn->setOp(JSOP_NAME);
 
     TokenKind tt = tokenStream.getToken(TSF_KEYWORD_IS_NAME);
     if (tt == TOK_STAR || tt == TOK_NAME) {
         /* Inline and specialize propertySelector for JSOP_QNAMECONST. */
@@ -6122,17 +6060,18 @@ Parser::qualifiedIdentifier()
 {
     JS_ASSERT(!tc->inStrictMode());
 
     ParseNode *pn = propertySelector();
     if (!pn)
         return NULL;
     if (tokenStream.matchToken(TOK_DBLCOLON)) {
         /* Hack for bug 496316. Slowing down E4X won't make it go away, alas. */
-        tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
+        tc->flags |= TCF_FUN_HEAVYWEIGHT;
+        tc->noteLocalOverwritesArguments();
         pn = qualifiedSuffix(pn);
     }
     return pn;
 }
 
 ParseNode *
 Parser::attributeIdentifier()
 {
@@ -6637,17 +6576,18 @@ ParseNode *
 Parser::propertyQualifiedIdentifier()
 {
     JS_ASSERT(!tc->inStrictMode());
     JS_ASSERT(tokenStream.isCurrentTokenType(TOK_NAME));
     JS_ASSERT(tokenStream.currentToken().t_op == JSOP_NAME);
     JS_ASSERT(tokenStream.peekToken() == TOK_DBLCOLON);
 
     /* Deoptimize QualifiedIdentifier properties to avoid tricky analysis. */
-    tc->flags |= (TCF_FUN_HEAVYWEIGHT | TCF_FUN_LOCAL_ARGUMENTS);
+    tc->flags |= TCF_FUN_HEAVYWEIGHT;
+    tc->noteLocalOverwritesArguments();
 
     PropertyName *name = tokenStream.currentToken().name();
     ParseNode *node = NameNode::create(PNK_NAME, name, tc);
     if (!node)
         return NULL;
     node->setOp(JSOP_NAME);
     node->pn_dflags |= PND_DEOPTIMIZED;
 
@@ -6717,41 +6657,22 @@ Parser::identifierName(bool afterDoubleD
                  * - Be adopted when we parse the real defining
                  *   declaration, or
                  * - Be left as a free variable definition if we never
                  *   see the real definition.
                  */
                 dn = MakePlaceholder(node, tc);
                 if (!dn || !tc->lexdeps->add(p, name, dn))
                     return NULL;
-
-                /*
-                 * In case this is a forward reference to a function,
-                 * we pessimistically set PND_FUNARG if the next token
-                 * is not a left parenthesis.
-                 *
-                 * If the definition eventually parsed into dn is not a
-                 * function, this flag won't hurt, and if we do parse a
-                 * function with pn's name, then the PND_FUNARG flag is
-                 * necessary for safe context->display-based optimiza-
-                 * tion of the closure's static link.
-                 */
-                if (tokenStream.peekToken() != TOK_LP)
-                    dn->pn_dflags |= PND_FUNARG;
             }
         }
 
         JS_ASSERT(dn->isDefn());
         LinkUseToDef(node, dn, tc);
 
-        /* Here we handle the backward function reference case. */
-        if (tokenStream.peekToken() != TOK_LP)
-            dn->pn_dflags |= PND_FUNARG;
-
-        node->pn_dflags |= (dn->pn_dflags & PND_FUNARG);
         if (stmt && stmt->type == STMT_WITH)
             node->pn_dflags |= PND_DEOPTIMIZED;
     }
 
 #if JS_HAS_XML_SUPPORT
     if (!tc->inStrictMode() && tokenStream.matchToken(TOK_DBLCOLON)) {
         if (afterDoubleDot) {
             if (!checkForFunctionNode(name, node))
--- a/js/src/frontend/SemanticAnalysis.cpp
+++ b/js/src/frontend/SemanticAnalysis.cpp
@@ -121,238 +121,32 @@ CleanFunctionList(ParseNodeAllocator *al
             CleanFunctionList(allocator, &box->kids);
 
             /* Keep the box on the list, and move to the next link. */
             link = &box->siblings;
         }
     }
 }
 
-/*
- * Mark as funargs any functions that reach up to one or more upvars across an
- * already-known funarg. The parser will flag the o_m lambda as a funarg in:
- *
- *   function f(o, p) {
- *       o.m = function o_m(a) {
- *           function g() { return p; }
- *           function h() { return a; }
- *           return g() + h();
- *       }
- *   }
- *
- * but without this extra marking phase, function g will not be marked as a
- * funarg since it is called from within its parent scope. But g reaches up to
- * f's parameter p, so if o_m escapes f's activation scope, g does too and
- * cannot assume that p's stack slot is still alive. In contast function h
- * neither escapes nor uses an upvar "above" o_m's level.
- *
- * If function g itself contained lambdas that contained non-lambdas that reach
- * up above its level, then those non-lambdas would have to be marked too. This
- * process is potentially exponential in the number of functions, but generally
- * not so complex. But it can't be done during a single recursive traversal of
- * the funbox tree, so we must use a work queue.
- *
- * Return the minimal "skipmin" for funbox and its siblings. This is the delta
- * between the static level of the bodies of funbox and its peers (which must
- * be funbox->level + 1), and the static level of the nearest upvar among all
- * the upvars contained by funbox and its peers. If there are no upvars, return
- * FREE_STATIC_LEVEL. Thus this function never returns 0.
- */
-static unsigned
-FindFunArgs(FunctionBox *funbox, int level, FunctionBoxQueue *queue)
-{
-    unsigned allskipmin = UpvarCookie::FREE_LEVEL;
-
-    do {
-        ParseNode *fn = funbox->node;
-        JS_ASSERT(fn->isArity(PN_FUNC));
-        int fnlevel = level;
-
-        /*
-         * An eval can leak funbox, functions along its ancestor line, and its
-         * immediate kids. Since FindFunArgs uses DFS and the parser propagates
-         * TCF_FUN_HEAVYWEIGHT bottom up, funbox's ancestor function nodes have
-         * already been marked as funargs by this point. Therefore we have to
-         * flag only funbox->node and funbox->kids' nodes here.
-         *
-         * Generators need to be treated in the same way. Even if the value
-         * of a generator function doesn't escape, anything defined or referred
-         * to inside the generator can escape through a call to the generator.
-         * We could imagine doing static analysis to track the calls and see
-         * if any iterators or values returned by iterators escape, but that
-         * would be hard, so instead we just assume everything might escape.
-         */
-        if (funbox->tcflags & (TCF_FUN_HEAVYWEIGHT | TCF_FUN_IS_GENERATOR)) {
-            fn->setFunArg();
-            for (FunctionBox *kid = funbox->kids; kid; kid = kid->siblings)
-                kid->node->setFunArg();
-        }
-
-        /*
-         * Compute in skipmin the least distance from fun's static level up to
-         * an upvar, whether used directly by fun, or indirectly by a function
-         * nested in fun.
-         */
-        unsigned skipmin = UpvarCookie::FREE_LEVEL;
-        ParseNode *pn = fn->pn_body;
-
-        if (pn->isKind(PNK_UPVARS)) {
-            AtomDefnMapPtr &upvars = pn->pn_names;
-            JS_ASSERT(upvars->count() != 0);
-
-            for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
-                Definition *defn = r.front().value();
-                Definition *lexdep = defn->resolve();
-
-                if (!lexdep->isFreeVar()) {
-                    unsigned upvarLevel = lexdep->frameLevel();
-
-                    if (int(upvarLevel) <= fnlevel)
-                        fn->setFunArg();
-
-                    unsigned skip = (funbox->level + 1) - upvarLevel;
-                    if (skip < skipmin)
-                        skipmin = skip;
-                }
-            }
-        }
-
-        /*
-         * If this function escapes, whether directly (the parser detects such
-         * escapes) or indirectly (because this non-escaping function uses an
-         * upvar that reaches across an outer function boundary where the outer
-         * function escapes), enqueue it for further analysis, and bump fnlevel
-         * to trap any non-escaping children.
-         */
-        if (fn->isFunArg()) {
-            queue->push(funbox);
-            fnlevel = int(funbox->level);
-        }
-
-        /*
-         * Now process the current function's children, and recalibrate their
-         * cumulative skipmin to be relative to the current static level.
-         */
-        if (funbox->kids) {
-            unsigned kidskipmin = FindFunArgs(funbox->kids, fnlevel, queue);
-
-            JS_ASSERT(kidskipmin != 0);
-            if (kidskipmin != UpvarCookie::FREE_LEVEL) {
-                --kidskipmin;
-                if (kidskipmin != 0 && kidskipmin < skipmin)
-                    skipmin = kidskipmin;
-            }
-        }
-
-        /*
-         * Finally, after we've traversed all of the current function's kids,
-         * minimize allskipmin against our accumulated skipmin. Minimize across
-         * funbox and all of its siblings, to compute our return value.
-         */
-        if (skipmin != UpvarCookie::FREE_LEVEL) {
-            if (skipmin < allskipmin)
-                allskipmin = skipmin;
-        }
-    } while ((funbox = funbox->siblings) != NULL);
-
-    return allskipmin;
-}
-
-static bool
-MarkFunArgs(JSContext *cx, FunctionBox *funbox, uint32_t functionCount)
-{
-    FunctionBoxQueue queue;
-    if (!queue.init(functionCount)) {
-        js_ReportOutOfMemory(cx);
-        return false;
-    }
-
-    FindFunArgs(funbox, -1, &queue);
-    while ((funbox = queue.pull()) != NULL) {
-        ParseNode *fn = funbox->node;
-        JS_ASSERT(fn->isFunArg());
-
-        ParseNode *pn = fn->pn_body;
-        if (pn->isKind(PNK_UPVARS)) {
-            AtomDefnMapPtr upvars = pn->pn_names;
-            JS_ASSERT(!upvars->empty());
-
-            for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
-                Definition *defn = r.front().value();
-                Definition *lexdep = defn->resolve();
-
-                if (!lexdep->isFreeVar() &&
-                    !lexdep->isFunArg() &&
-                    (lexdep->kind() == Definition::FUNCTION ||
-                     lexdep->isOp(JSOP_CALLEE))) {
-                    /*
-                     * Mark this formerly-Algol-like function as an escaping
-                     * function (i.e., as a funarg), because it is used from
-                     * another funarg.
-                     *
-                     * Progress is guaranteed because we set the funarg flag
-                     * here, which suppresses revisiting this function (thanks
-                     * to the !lexdep->isFunArg() test just above).
-                     */
-                    lexdep->setFunArg();
-
-                    FunctionBox *afunbox;
-                    if (lexdep->isOp(JSOP_CALLEE)) {
-                        /*
-                         * A named function expression will not appear to be a
-                         * funarg if it is immediately applied. However, if its
-                         * name is used in an escaping function nested within
-                         * it, then it must become flagged as a funarg again.
-                         * See bug 545980.
-                         */
-                        afunbox = funbox;
-                        unsigned calleeLevel = lexdep->pn_cookie.level();
-                        unsigned staticLevel = afunbox->level + 1U;
-                        while (staticLevel != calleeLevel) {
-                            afunbox = afunbox->parent;
-                            --staticLevel;
-                        }
-                        JS_ASSERT(afunbox->level + 1U == calleeLevel);
-                        afunbox->node->setFunArg();
-                    } else {
-                       afunbox = lexdep->pn_funbox;
-                    }
-                    queue.push(afunbox);
-
-                    /*
-                     * Walk over nested functions again, now that we have
-                     * changed the level across which it is unsafe to access
-                     * upvars using the runtime dynamic link (frame chain).
-                     */
-                    if (afunbox->kids)
-                        FindFunArgs(afunbox->kids, afunbox->level, &queue);
-                }
-            }
-        }
-    }
-    return true;
-}
-
 static void
 FlagHeavyweights(Definition *dn, FunctionBox *funbox, uint32_t *tcflags)
 {
     unsigned dnLevel = dn->frameLevel();
 
     while ((funbox = funbox->parent) != NULL) {
         /*
          * Notice that funbox->level is the static level of the definition or
          * expression of the function parsed into funbox, not the static level
          * of its body. Therefore we must add 1 to match dn's level to find the
          * funbox whose body contains the dn definition.
          */
         if (funbox->level + 1U == dnLevel || (dnLevel == 0 && dn->isLet())) {
             funbox->tcflags |= TCF_FUN_HEAVYWEIGHT;
             break;
         }
-        funbox->tcflags |= TCF_FUN_ENTRAINS_SCOPES;
     }
 
     if (!funbox && (*tcflags & TCF_IN_FUNCTION))
         *tcflags |= TCF_FUN_HEAVYWEIGHT;
 }
 
 static void
 SetFunctionKinds(FunctionBox *funbox, uint32_t *tcflags, bool isDirectEval)
@@ -418,19 +212,16 @@ SetFunctionKinds(FunctionBox *funbox, ui
 
             for (AtomDefnRange r = upvars->all(); !r.empty(); r.popFront()) {
                 Definition *defn = r.front().value();
                 Definition *lexdep = defn->resolve();
                 if (!lexdep->isFreeVar())
                     FlagHeavyweights(lexdep, funbox, tcflags);
             }
         }
-
-        if (funbox->joinable())
-            fun->setJoinable();
     }
 }
 
 /*
  * Walk the FunctionBox tree looking for functions whose call objects may
  * acquire new bindings as they execute: non-strict functions that call eval,
  * and functions that contain function statements (definitions not appearing
  * within the top statement list, which don't take effect unless they are
@@ -468,16 +259,14 @@ MarkExtensibleScopeDescendants(JSContext
 }
 
 bool
 frontend::AnalyzeFunctions(TreeContext *tc)
 {
     CleanFunctionList(&tc->parser->allocator, &tc->functionList);
     if (!tc->functionList)
         return true;
-    if (!MarkFunArgs(tc->parser->context, tc->functionList, tc->parser->functionCount))
-        return false;
     if (!MarkExtensibleScopeDescendants(tc->parser->context, tc->functionList, false))
         return false;
     bool isDirectEval = !!tc->parser->callerFrame;
     SetFunctionKinds(tc->functionList, &tc->flags, isDirectEval);
     return true;
 }
--- a/js/src/frontend/SemanticAnalysis.h
+++ b/js/src/frontend/SemanticAnalysis.h
@@ -43,18 +43,18 @@
 namespace js {
 
 struct TreeContext;
 
 namespace frontend {
 
 /*
  * For each function in the compilation unit given by tc, decide whether the
- * function is a full closure, a null closure, or a flat closure, and set the
- * heavyweight bit if necessary.
+ * function is a full closure or a null closure and set JSFunction flags
+ * accordingly.
  */
 bool
 AnalyzeFunctions(TreeContext *tc);
 
 } /* namespace frontend */
 } /* namespace js */
 
 #endif /* SemanticAnalysis_h__ */
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug738841.js
@@ -0,0 +1,49 @@
+try {
+    for (let z = 0; z < 1; ++evalcx("[]", newGlobal("new-compartment"))) {}
+} catch (e) {}
+try {
+    for (y in [schedulegc(58)]) {
+        b
+    }
+} catch (e) {}
+try {
+    e
+} catch (e) {}
+try {
+    (function() {
+        h
+    }())
+} catch (e) {}
+try {
+    (function() {
+        this.m.f = function() {}
+    }())
+} catch (e) {}
+try {
+    t()
+} catch (e) {}
+try {
+    p
+} catch (e) {}
+try {
+    gc()
+    p
+} catch (e) {}
+try {
+    (function() {
+        for (var v of m) {}
+    }())
+} catch (e) {}
+try {
+    m
+} catch (e) {}
+try {
+    var f = function() {
+        {
+            print(new function(q)("", s))
+            let u
+        }
+    };
+    dis(f);
+    f();
+} catch (e) {}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug738846.js
@@ -0,0 +1,49 @@
+try {
+    (function() {
+        var m
+        ArrayBuffer()
+        var _ = t
+        var _2 = []
+    }())
+} catch (e) {}
+try {
+    for (y in [schedulegc(58)]) {
+        m
+    }
+} catch (e) {}
+try {
+    (function() {
+        n.(O)
+    }())
+} catch (e) {}
+try {
+    (function() {
+        s
+    }())
+} catch (e) {}
+try {
+    e
+} catch (e) {}
+try {
+    "" ()
+} catch (e) {}
+try {
+    gc()
+    s
+} catch (e) {}
+try {
+    (function() {
+        for (v of m) {}
+    }())
+} catch (e) {}
+try {
+    t
+} catch (e) {}
+try {
+    (function() {
+        "use strict";
+        print(new function() {
+            r
+        }(this))
+    }())
+} catch (e) {}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug739694-1.js
@@ -0,0 +1,12 @@
+function newFunc(x) { new Function(x)(); }; try { newFunc("\
+var g = newGlobal('new-compartment');\
+g.h = function () {\
+    names = foo.blaaaaaaaaaaaaah().environment.names();\
+};\
+g.eval('var obj = {a: 1};' + \"with ({a: 1, '0xcafe': 2, ' ': 3, '': 4, '0': 5}) h();\");\
+");
+} catch(exc1) {}
+function newFunc(x) { new Function(x)(); }; newFunc("\
+gczeal(2);\
+  a=b=c=d=0; this.__defineGetter__('g', gc); for each (y in this);\
+");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug739694-2.js
@@ -0,0 +1,8 @@
+try {
+    ({
+        f: evalcx("evalcx(\"e\",newGlobal('new-compartment'))",
+                  newGlobal('new-compartment'))
+    })
+} catch (e) {}
+gc()
+gc()
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/testFunctionStatementNamedArguments.js
@@ -0,0 +1,10 @@
+var g;
+function foo(b) {
+    if (b)
+        function arguments() {};
+    return arguments;
+}
+
+var a = foo(true);
+assertEq(typeof a, "function");
+assertEq(a.name, "arguments");
deleted file mode 100644
--- a/js/src/jit-test/tests/basic/testInitDictionary.js
+++ /dev/null
@@ -1,51 +0,0 @@
-
-var shapes = {};
-
-function stringify(a) {
-  assertEq(shapes[shapeOf(a)], undefined);
-  shapes[shapeOf(a)] = 1;
-  var b = "";
-  for (var c in a) {
-    b += c + ":";
-    if (typeof a[c] == "function")
-      b += "function,";
-    else
-      b += a[c] + ",";
-  }
-  return b;
-}
-
-function test1() {
-  return stringify({a: 0, b: 1, a: function() {} });
-}
-for (var i = 0; i < 3; i++)
-  assertEq(test1(), "a:function,b:1,");
-
-// This does not cause the object to go to dictionary mode, unlike the above.
-function test2() {
-  return stringify({a: 0, b: 1, a: 2, b: 3});
-}
-assertEq(test2(), "a:2,b:3,");
-
-function test3() {
-  return stringify({
-    aa:0,ab:1,ac:2,ad:3,ae:4,af:5,ag:6,ah:7,ai:8,aj:9,
-    ba:0,bb:1,bc:2,bd:3,be:4,bf:5,bg:6,bh:7,bi:8,bj:9,
-    ca:0,cb:1,cc:2,cd:3,ce:4,cf:5,cg:6,ch:7,ci:8,cj:9,
-    da:0,db:1,dc:2,dd:3,de:4,df:5,dg:6,dh:7,di:8,dj:9,
-    ea:0,eb:1,ec:2,ed:3,ee:4,ef:5,eg:6,eh:7,ei:8,ej:9,
-    fa:0,fb:1,fc:2,fd:3,fe:4,ff:5,fg:6,fh:7,fi:8,fj:9,
-    ga:0,gb:1,gc:2,gd:3,ge:4,gf:5,gg:6,gh:7,gi:8,gj:9,
-    ha:0,hb:1,hc:2,hd:3,he:4,hf:5,hg:6,hh:7,hi:8,hj:9,
-    ia:0,ib:1,ic:2,id:3,ie:4,if:5,ig:6,ih:7,ii:8,ij:9,
-    ja:0,jb:1,jc:2,jd:3,je:4,jf:5,jg:6,jh:7,ji:8,jj:9,
-    ka:0,kb:1,kc:2,kd:3,ke:4,kf:5,kg:6,kh:7,ki:8,kj:9,
-    la:0,lb:1,lc:2,ld:3,le:4,lf:5,lg:6,lh:7,li:8,lj:9,
-    ma:0,mb:1,mc:2,md:3,me:4,mf:5,mg:6,mh:7,mi:8,mj:9,
-    na:0,nb:1,nc:2,nd:3,ne:4,nf:5,ng:6,nh:7,ni:8,nj:9,
-    oa:0,ob:1,oc:2,od:3,oe:4,of:5,og:6,oh:7,oi:8,oj:9,
-    pa:0,pb:1,pc:2,pd:3,pe:4,pf:5,pg:6,ph:7,pi:8,pj:9,
-        });
-}
-for (var i = 0; i < 10; i++)
-  assertEq(test3(), "aa:0,ab:1,ac:2,ad:3,ae:4,af:5,ag:6,ah:7,ai:8,aj:9,ba:0,bb:1,bc:2,bd:3,be:4,bf:5,bg:6,bh:7,bi:8,bj:9,ca:0,cb:1,cc:2,cd:3,ce:4,cf:5,cg:6,ch:7,ci:8,cj:9,da:0,db:1,dc:2,dd:3,de:4,df:5,dg:6,dh:7,di:8,dj:9,ea:0,eb:1,ec:2,ed:3,ee:4,ef:5,eg:6,eh:7,ei:8,ej:9,fa:0,fb:1,fc:2,fd:3,fe:4,ff:5,fg:6,fh:7,fi:8,fj:9,ga:0,gb:1,gc:2,gd:3,ge:4,gf:5,gg:6,gh:7,gi:8,gj:9,ha:0,hb:1,hc:2,hd:3,he:4,hf:5,hg:6,hh:7,hi:8,hj:9,ia:0,ib:1,ic:2,id:3,ie:4,if:5,ig:6,ih:7,ii:8,ij:9,ja:0,jb:1,jc:2,jd:3,je:4,jf:5,jg:6,jh:7,ji:8,jj:9,ka:0,kb:1,kc:2,kd:3,ke:4,kf:5,kg:6,kh:7,ki:8,kj:9,la:0,lb:1,lc:2,ld:3,le:4,lf:5,lg:6,lh:7,li:8,lj:9,ma:0,mb:1,mc:2,md:3,me:4,mf:5,mg:6,mh:7,mi:8,mj:9,na:0,nb:1,nc:2,nd:3,ne:4,nf:5,ng:6,nh:7,ni:8,nj:9,oa:0,ob:1,oc:2,od:3,oe:4,of:5,og:6,oh:7,oi:8,oj:9,pa:0,pb:1,pc:2,pd:3,pe:4,pf:5,pg:6,ph:7,pi:8,pj:9,");
--- a/js/src/jsanalyze.cpp
+++ b/js/src/jsanalyze.cpp
@@ -535,17 +535,16 @@ ScriptAnalysis::analyzeBytecode(JSContex
             modifiesArguments_ = true;
             isInlineable = false;
             break;
 
           /* Additional opcodes which can be compiled but which can't be inlined. */
           case JSOP_ARGUMENTS:
           case JSOP_THROW:
           case JSOP_EXCEPTION:
-          case JSOP_DEFLOCALFUN:
           case JSOP_LAMBDA:
           case JSOP_DEBUGGER:
           case JSOP_FUNCALL:
           case JSOP_FUNAPPLY:
             isInlineable = false;
             break;
 
           /* Additional opcodes which can be both compiled both normally and inline. */
@@ -613,21 +612,19 @@ ScriptAnalysis::analyzeBytecode(JSContex
           case JSOP_GETARG:
           case JSOP_CALLARG:
           case JSOP_BINDGNAME:
           case JSOP_UINT16:
           case JSOP_NEWINIT:
           case JSOP_NEWARRAY:
           case JSOP_NEWOBJECT:
           case JSOP_ENDINIT:
-          case JSOP_INITMETHOD:
           case JSOP_INITPROP:
           case JSOP_INITELEM:
           case JSOP_SETPROP:
-          case JSOP_SETMETHOD:
           case JSOP_IN:
           case JSOP_INSTANCEOF:
           case JSOP_LINENO:
           case JSOP_ENUMELEM:
           case JSOP_CONDSWITCH:
           case JSOP_LABEL:
           case JSOP_RETRVAL:
           case JSOP_GETGNAME:
@@ -824,18 +821,17 @@ ScriptAnalysis::analyzeLifetimes(JSConte
             uint32_t slot = GetBytecodeSlot(script, pc);
             if (!slotEscapes(slot))
                 addVariable(cx, lifetimes[slot], offset, saved, savedCount);
             break;
           }
 
           case JSOP_SETARG:
           case JSOP_SETLOCAL:
-          case JSOP_SETLOCALPOP:
-          case JSOP_DEFLOCALFUN: {
+          case JSOP_SETLOCALPOP: {
             uint32_t slot = GetBytecodeSlot(script, pc);
             if (!slotEscapes(slot))
                 killVariable(cx, lifetimes[slot], offset, saved, savedCount);
             break;
           }
 
           case JSOP_INCARG:
           case JSOP_DECARG:
@@ -1519,17 +1515,16 @@ ScriptAnalysis::analyzeSSA(JSContext *cx
 
           /* Short circuit ops which push back one of their operands. */
 
           case JSOP_MOREITER:
             stack[stackDepth - 2].v = code->poppedValues[0];
             break;
 
           case JSOP_INITPROP:
-          case JSOP_INITMETHOD:
             stack[stackDepth - 1].v = code->poppedValues[1];
             break;
 
           case JSOP_INITELEM:
             stack[stackDepth - 1].v = code->poppedValues[2];
             break;
 
           case JSOP_DUP:
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -253,17 +253,16 @@ ExtendedDef(jsbytecode *pc)
     switch ((JSOp)*pc) {
       case JSOP_SETARG:
       case JSOP_INCARG:
       case JSOP_DECARG:
       case JSOP_ARGINC:
       case JSOP_ARGDEC:
       case JSOP_SETLOCAL:
       case JSOP_SETLOCALPOP:
-      case JSOP_DEFLOCALFUN:
       case JSOP_INCLOCAL:
       case JSOP_DECLOCAL:
       case JSOP_LOCALINC:
       case JSOP_LOCALDEC:
         return true;
       default:
         return false;
     }
@@ -382,17 +381,16 @@ static inline uint32_t GetBytecodeSlot(J
       case JSOP_ARGINC:
       case JSOP_ARGDEC:
         return ArgSlot(GET_SLOTNO(pc));
 
       case JSOP_GETLOCAL:
       case JSOP_CALLLOCAL:
       case JSOP_SETLOCAL:
       case JSOP_SETLOCALPOP:
-      case JSOP_DEFLOCALFUN:
       case JSOP_INCLOCAL:
       case JSOP_DECLOCAL:
       case JSOP_LOCALINC:
       case JSOP_LOCALDEC:
         return LocalSlot(script, GET_SLOTNO(pc));
 
       case JSOP_THIS:
         return ThisSlot();
@@ -406,17 +404,16 @@ static inline uint32_t GetBytecodeSlot(J
 /* Slot opcodes which update SSA information. */
 static inline bool
 BytecodeUpdatesSlot(JSOp op)
 {
     switch (op) {
       case JSOP_SETARG:
       case JSOP_SETLOCAL:
       case JSOP_SETLOCALPOP:
-      case JSOP_DEFLOCALFUN:
       case JSOP_INCARG:
       case JSOP_DECARG:
       case JSOP_ARGINC:
       case JSOP_ARGDEC:
       case JSOP_INCLOCAL:
       case JSOP_DECLOCAL:
       case JSOP_LOCALINC:
       case JSOP_LOCALDEC:
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -23,17 +23,16 @@ BEGIN_TEST(testLookup_bug522590)
 
     // This lookup must not return an internal function object.
     jsvalRoot r(cx);
     CHECK(JS_LookupProperty(cx, xobj, "f", r.addr()));
     CHECK(JSVAL_IS_OBJECT(r));
     JSObject *funobj = JSVAL_TO_OBJECT(r);
     CHECK(funobj->isFunction());
     CHECK(!js::IsInternalFunctionObject(funobj));
-    CHECK(funobj->toFunction()->isClonedMethod());
 
     return true;
 }
 END_TEST(testLookup_bug522590)
 
 JSBool
 document_resolve(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSObject **objp)
 {
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3450,21 +3450,16 @@ LookupResult(JSContext *cx, JSObject *ob
         /* XXX bad API: no way to tell "not defined" from "void value" */
         vp->setUndefined();
         return JS_TRUE;
     }
 
     if (obj2->isNative()) {
         Shape *shape = (Shape *) prop;
 
-        if (shape->isMethod()) {
-            vp->setObject(*obj2->nativeGetMethod(shape));
-            return !!obj2->methodReadBarrier(cx, *shape, vp);
-        }
-
         /* Peek at the native property's slot value, without doing a Get. */
         if (shape->hasSlot()) {
             *vp = obj2->nativeGetSlot(shape->slot());
             return true;
         }
     } else {
         if (obj2->isDenseArray())
             return js_GetDenseArrayElementValue(cx, obj2, id, vp);
@@ -3850,29 +3845,22 @@ GetPropertyDescriptorById(JSContext *cx,
         desc->value.setUndefined();
         return JS_TRUE;
     }
 
     desc->obj = obj2;
     if (obj2->isNative()) {
         Shape *shape = (Shape *) prop;
         desc->attrs = shape->attributes();
-
-        if (shape->isMethod()) {
-            desc->getter = JS_PropertyStub;
-            desc->setter = JS_StrictPropertyStub;
-            desc->value.setObject(*obj2->nativeGetMethod(shape));
-        } else {
-            desc->getter = shape->getter();
-            desc->setter = shape->setter();
-            if (shape->hasSlot())
-                desc->value = obj2->nativeGetSlot(shape->slot());
-            else
-                desc->value.setUndefined();
-        }
+        desc->getter = shape->getter();
+        desc->setter = shape->setter();
+        if (shape->hasSlot())
+            desc->value = obj2->nativeGetSlot(shape->slot());
+        else
+            desc->value.setUndefined();
     } else {
         if (obj2->isProxy()) {
             JSAutoResolveFlags rf(cx, flags);
             return own
                    ? Proxy::getOwnPropertyDescriptor(cx, obj2, id, false, desc)
                    : Proxy::getPropertyDescriptor(cx, obj2, id, false, desc);
         }
         if (!obj2->getGenericAttributes(cx, id, &desc->attrs))
@@ -3963,18 +3951,19 @@ SetPropertyAttributesById(JSContext *cx,
     JSProperty *prop;
 
     if (!LookupPropertyById(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
         return false;
     if (!prop || obj != obj2) {
         *foundp = false;
         return true;
     }
+    Shape *shape = (Shape *) prop;
     JSBool ok = obj->isNative()
-                ? js_SetNativeAttributes(cx, obj, (Shape *) prop, attrs)
+                ? obj->changePropertyAttributes(cx, shape, attrs)
                 : obj->setGenericAttributes(cx, id, &attrs);
     if (ok)
         *foundp = true;
     return ok;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_SetPropertyAttributes(JSContext *cx, JSObject *obj, const char *name,
@@ -4067,17 +4056,17 @@ JS_GetUCProperty(JSContext *cx, JSObject
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetMethodById(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, jsval *vp)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
-    if (!js_GetMethod(cx, obj, id, JSGET_METHOD_BARRIER, vp))
+    if (!js_GetMethod(cx, obj, id, 0, vp))
         return JS_FALSE;
     if (objp)
         *objp = obj;
     return JS_TRUE;
 }
 
 JS_PUBLIC_API(JSBool)
 JS_GetMethod(JSContext *cx, JSObject *obj, const char *name, JSObject **objp, jsval *vp)
@@ -5361,17 +5350,17 @@ JS_CallFunctionName(JSContext *cx, JSObj
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, JSValueArray(argv, argc));
     AutoLastFrameCheck lfc(cx);
 
     Value v;
     JSAtom *atom = js_Atomize(cx, name, strlen(name));
     return atom &&
-           js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, &v) &&
+           js_GetMethod(cx, obj, ATOM_TO_JSID(atom), 0, &v) &&
            Invoke(cx, ObjectOrNullValue(obj), v, argc, argv, rval);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, unsigned argc, jsval *argv,
                      jsval *rval)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
@@ -5904,31 +5893,33 @@ JS_ReadStructuredClone(JSContext *cx, co
 
 JS_PUBLIC_API(JSBool)
 JS_WriteStructuredClone(JSContext *cx, jsval v, uint64_t **bufp, size_t *nbytesp,
                         const JSStructuredCloneCallbacks *optionalCallbacks,
                         void *closure)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
+    assertSameCompartment(cx, v);
 
     const JSStructuredCloneCallbacks *callbacks =
         optionalCallbacks ?
         optionalCallbacks :
         cx->runtime->structuredCloneCallbacks;
     return WriteStructuredClone(cx, v, (uint64_t **) bufp, nbytesp, callbacks, closure);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_StructuredClone(JSContext *cx, jsval v, jsval *vp,
                    const JSStructuredCloneCallbacks *optionalCallbacks,
                    void *closure)
 {
     AssertNoGC(cx);
     CHECK_REQUEST(cx);
+    assertSameCompartment(cx, v);
 
     const JSStructuredCloneCallbacks *callbacks =
         optionalCallbacks ?
         optionalCallbacks :
         cx->runtime->structuredCloneCallbacks;
     JSAutoStructuredCloneBuffer buf;
     return buf.write(cx, v, callbacks, closure) &&
            buf.read(cx, vp, callbacks, closure);
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -640,27 +640,16 @@ JS_IsConstructorFrame(JSContext *cx, JSS
 
 JS_PUBLIC_API(JSObject *)
 JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp)
 {
     return Valueify(fp)->maybeCalleev().toObjectOrNull();
 }
 
 JS_PUBLIC_API(JSBool)
-JS_GetValidFrameCalleeObject(JSContext *cx, JSStackFrame *fp, jsval *vp)
-{
-    Value v;
-
-    if (!Valueify(fp)->getValidCalleeObject(cx, &v))
-        return false;
-    *vp = v.isObject() ? v : JSVAL_VOID;
-    return true;
-}
-
-JS_PUBLIC_API(JSBool)
 JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp)
 {
     return Valueify(fp)->isDebuggerFrame();
 }
 
 JS_PUBLIC_API(JSBool)
 JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp)
 {
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -287,49 +287,20 @@ JS_GetFrameReturnValue(JSContext *cx, JS
 
 extern JS_PUBLIC_API(void)
 JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval);
 
 /**
  * Return fp's callee function object (fp->callee) if it has one. Note that
  * this API cannot fail. A null return means "no callee": fp is a global or
  * eval-from-global frame, not a call frame.
- *
- * This API began life as an infallible getter, but now it can return either:
- *
- * 1. An optimized closure that was compiled assuming the function could not
- *    escape and be called from sites the compiler could not see.
- *
- * 2. A "joined function object", an optimization whereby SpiderMonkey avoids
- *    creating fresh function objects for every evaluation of a function
- *    expression that is used only once by a consumer that either promises to
- *    clone later when asked for the value or that cannot leak the value.
- *
- * Because Mozilla's Gecko embedding of SpiderMonkey (and no doubt other
- * embeddings) calls this API in potentially performance-sensitive ways (e.g.
- * in nsContentUtils::GetDocumentFromCaller), we are leaving this API alone. It
- * may now return an unwrapped non-escaping optimized closure, or a joined
- * function object. Such optimized objects may work well if called from the
- * correct context, never mutated or compared for identity, etc.
- *
- * However, if you really need to get the same callee object that JS code would
- * see, which means undoing the optimizations, where an undo attempt can fail,
- * then use JS_GetValidFrameCalleeObject.
  */
 extern JS_PUBLIC_API(JSObject *)
 JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp);
 
-/**
- * Return fp's callee function object after running the deferred closure
- * cloning "method read barrier". This API can fail! If the frame has no
- * callee, this API returns true with JSVAL_IS_VOID(*vp).
- */
-extern JS_PUBLIC_API(JSBool)
-JS_GetValidFrameCalleeObject(JSContext *cx, JSStackFrame *fp, jsval *vp);
-
 /************************************************************************/
 
 extern JS_PUBLIC_API(const char *)
 JS_GetScriptFilename(JSContext *cx, JSScript *script);
 
 extern JS_PUBLIC_API(const jschar *)
 JS_GetScriptSourceMap(JSContext *cx, JSScript *script);
 
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -369,17 +369,19 @@ InitExnPrivate(JSContext *cx, JSObject *
                 frame.argc = fp->numActualArgs();
                 if (!fp->forEachCanonicalActualArg(AppendWrappedArg(cx, values)))
                     return false;
             } else {
                 frame.funName = NULL;
                 frame.argc = 0;
             }
             if (fp->isScriptFrame()) {
-                frame.filename = fp->script()->filename;
+                frame.filename = SaveScriptFilename(cx, fp->script()->filename);
+                if (!frame.filename)
+                    return false;
                 frame.ulineno = PCToLineNumber(fp->script(), i.pc());
             } else {
                 frame.ulineno = 0;
                 frame.filename = NULL;
             }
         }
     }
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -92,117 +92,16 @@
 #include "vm/ScopeObject-inl.h"
 #include "vm/Stack-inl.h"
 
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 using namespace js::types;
 
-bool
-StackFrame::getValidCalleeObject(JSContext *cx, Value *vp)
-{
-    if (!isFunctionFrame()) {
-        vp->setNull();
-        return true;
-    }
-
-    JSFunction *fun = this->callee().toFunction();
-    vp->setObject(*fun);
-
-    /*
-     * Check for an escape attempt by a joined function object, which must go
-     * through the frame's |this| object's method read barrier for the method
-     * atom by which it was uniquely associated with a property.
-     */
-    const Value &thisv = functionThis();
-    if (thisv.isObject() && fun->methodAtom() && !fun->isClonedMethod()) {
-        JSObject *thisp = &thisv.toObject();
-        JSObject *first_barriered_thisp = NULL;
-
-        do {
-            /*
-             * While a non-native object is responsible for handling its
-             * entire prototype chain, notable non-natives including dense
-             * and typed arrays have native prototypes, so keep going.
-             */
-            if (!thisp->isNative())
-                continue;
-
-            const Shape *shape = thisp->nativeLookup(cx, ATOM_TO_JSID(fun->methodAtom()));
-            if (shape) {
-                /*
-                 * Two cases follow: the method barrier was not crossed
-                 * yet, so we cross it here; the method barrier *was*
-                 * crossed but after the call, in which case we fetch
-                 * and validate the cloned (unjoined) funobj from the
-                 * method property's slot.
-                 *
-                 * In either case we must allow for the method property
-                 * to have been replaced, or its value overwritten.
-                 */
-                if (shape->isMethod() && thisp->nativeGetMethod(shape) == fun) {
-                    if (!thisp->methodReadBarrier(cx, *shape, vp))
-                        return false;
-                    overwriteCallee(vp->toObject());
-                    return true;
-                }
-
-                if (shape->hasSlot()) {
-                    Value v = thisp->getSlot(shape->slot());
-                    JSFunction *clone;
-
-                    if (IsFunctionObject(v, &clone) &&
-                        clone->isInterpreted() &&
-                        clone->script() == fun->script() &&
-                        clone->methodObj() == thisp) {
-                        /*
-                         * N.B. If the method barrier was on a function
-                         * with singleton type, then while crossing the
-                         * method barrier CloneFunctionObject will have
-                         * ignored the attempt to clone the function.
-                         */
-                        JS_ASSERT_IF(!clone->hasSingletonType(), clone != fun);
-                        *vp = v;
-                        overwriteCallee(*clone);
-                        return true;
-                    }
-                }
-            }
-
-            if (!first_barriered_thisp)
-                first_barriered_thisp = thisp;
-        } while ((thisp = thisp->getProto()) != NULL);
-
-        if (!first_barriered_thisp)
-            return true;
-
-        /*
-         * At this point, we couldn't find an already-existing clone (or
-         * force to exist a fresh clone) created via thisp's method read
-         * barrier, so we must clone fun and store it in fp's callee to
-         * avoid re-cloning upon repeated foo.caller access.
-         *
-         * This must mean the code in js_DeleteGeneric could not find this
-         * stack frame on the stack when the method was deleted. We've lost
-         * track of the method, so we associate it with the first barriered
-         * object found starting from thisp on the prototype chain.
-         */
-        JSFunction *newfunobj = CloneFunctionObject(cx, fun);
-        if (!newfunobj)
-            return false;
-        newfunobj->setMethodObj(*first_barriered_thisp);
-        overwriteCallee(*newfunobj);
-        vp->setObject(*newfunobj);
-        return true;
-    }
-
-    return true;
-}
-
 static JSBool
 fun_getProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     while (!obj->isFunction()) {
         obj = obj->getProto();
         if (!obj)
             return true;
     }
@@ -222,20 +121,17 @@ fun_getProperty(JSContext *cx, JSObject 
     /* Set to early to null in case of error */
     vp->setNull();
 
     /* Find fun's top-most activation record. */
     StackFrame *fp = js_GetTopStackFrame(cx, FRAME_EXPAND_NONE);
     for (; fp; fp = fp->prev()) {
         if (!fp->isFunctionFrame() || fp->isEvalFrame())
             continue;
-        Value callee;
-        if (!fp->getValidCalleeObject(cx, &callee))
-            return false;
-        if (&callee.toObject() == fun)
+        if (fp->callee().toFunction() == fun)
             break;
     }
     if (!fp)
         return true;
 
 #ifdef JS_METHODJIT
     if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom) && fp && fp->prev()) {
         /*
@@ -272,24 +168,23 @@ fun_getProperty(JSContext *cx, JSObject 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.callerAtom)) {
         if (!fp->prev())
             return true;
 
         StackFrame *frame = fp->prev();
         while (frame && frame->isDummyFrame())
             frame = frame->prev();
 
-        if (frame && !frame->getValidCalleeObject(cx, vp))
-            return false;
-
-        if (!vp->isObject()) {
+        if (!frame || !frame->isFunctionFrame()) {
             JS_ASSERT(vp->isNull());
             return true;
         }
 
+        vp->setObject(frame->callee());
+
         /* Censor the caller if it is from another compartment. */
         JSObject &caller = vp->toObject();
         if (caller.compartment() != cx->compartment) {
             vp->setNull();
         } else if (caller.isFunction()) {
             JSFunction *callerFun = caller.toFunction();
             if (callerFun->isInterpreted() && callerFun->inStrictMode()) {
                 JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage, NULL,
@@ -1258,17 +1153,16 @@ LookupInterpretedFunctionPrototype(JSCon
     if (!shape) {
         if (!ResolveInterpretedFunctionPrototype(cx, funobj))
             return NULL;
         shape = funobj->nativeLookup(cx, id);
     }
     JS_ASSERT(!shape->configurable());
     JS_ASSERT(shape->isDataDescriptor());
     JS_ASSERT(shape->hasSlot());
-    JS_ASSERT(!shape->isMethod());
     return shape;
 }
 
 } /* namespace js */
 
 JSFunction *
 js_NewFunction(JSContext *cx, JSObject *funobj, Native native, unsigned nargs,
                unsigned flags, HandleObject parent, JSAtom *atom, js::gc::AllocKind kind)
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -62,20 +62,16 @@
  *
  * NB: JSFUN_EXPR_CLOSURE reuses JSFUN_STUB_GSOPS, which is an API request flag
  * bit only, never stored in fun->flags.
  *
  * If we need more bits in the future, all flags for interpreted functions can
  * move to u.i.script->flags. For now we use function flag bits to minimize
  * pointer-chasing.
  */
-#define JSFUN_JOINABLE      0x0001  /* function is null closure that does not
-                                       appear to call itself via its own name
-                                       or arguments.callee */
-
 #define JSFUN_PROTOTYPE     0x0800  /* function is Function.prototype for some
                                        global object */
 
 #define JSFUN_EXPR_CLOSURE  0x1000  /* expression closure: function(x) x*x */
 #define JSFUN_EXTENDED      0x2000  /* structure is FunctionExtended */
 #define JSFUN_INTERPRETED   0x4000  /* use u.i if kind >= this value else u.native */
 #define JSFUN_NULL_CLOSURE  0x8000  /* null closure entrains no scope chain */
 #define JSFUN_KINDMASK      0xc000  /* encode interp vs. native and closure
@@ -124,36 +120,26 @@ struct JSFunction : public JSObject
     }
 
     /* uint16_t representation bounds number of call object dynamic slots. */
     enum { MAX_ARGS_AND_VARS = 2 * ((1U << 16) - 1) };
 
 #define JS_LOCAL_NAME_TO_ATOM(nameWord)  ((JSAtom *) ((nameWord) & ~uintptr_t(1)))
 #define JS_LOCAL_NAME_IS_CONST(nameWord) ((((nameWord) & uintptr_t(1))) != 0)
 
-    bool mightEscape() const {
-        return isInterpreted() && isNullClosure();
-    }
-
-    bool joinable() const {
-        return flags & JSFUN_JOINABLE;
-    }
-
     /*
      * For an interpreted function, accessors for the initial scope object of
      * activations (stack frames) of the function.
      */
     inline JSObject *environment() const;
     inline void setEnvironment(JSObject *obj);
     inline void initEnvironment(JSObject *obj);
 
     static inline size_t offsetOfEnvironment() { return offsetof(JSFunction, u.i.env_); }
 
-    inline void setJoinable();
-
     js::HeapPtrScript &script() const {
         JS_ASSERT(isInterpreted());
         return *(js::HeapPtrScript *)&u.i.script_;
     }
 
     inline void setScript(JSScript *script_);
     inline void initScript(JSScript *script_);
 
@@ -213,43 +199,20 @@ struct JSFunction : public JSObject
     inline bool isExtended() const {
         JS_STATIC_ASSERT(FinalizeKind != ExtendedFinalizeKind);
         JS_ASSERT(!!(flags & JSFUN_EXTENDED) == (getAllocKind() == ExtendedFinalizeKind));
         return !!(flags & JSFUN_EXTENDED);
     }
 
   public:
     /* Accessors for data stored in extended functions. */
-
     inline void initializeExtended();
-
     inline void setExtendedSlot(size_t which, const js::Value &val);
     inline const js::Value &getExtendedSlot(size_t which) const;
 
-    /* Slot holding associated method property, needed for foo.caller handling. */
-    static const uint32_t METHOD_PROPERTY_SLOT = 0;
-
-    /* For cloned methods, slot holding the object this was cloned as a property from. */
-    static const uint32_t METHOD_OBJECT_SLOT = 1;
-
-    /* Whether this is a function cloned from a method. */
-    inline bool isClonedMethod() const;
-
-    /* For a cloned method, pointer to the object the method was cloned for. */
-    inline JSObject *methodObj() const;
-    inline void setMethodObj(JSObject& obj);
-
-    /*
-     * Method name imputed from property uniquely assigned to or initialized,
-     * where the function does not need to be cloned to carry a scope chain.
-     * This is set on both the original and cloned function.
-     */
-    inline JSAtom *methodAtom() const;
-    inline void setMethodAtom(JSAtom *atom);
-
   private:
     /* 
      * These member functions are inherited from JSObject, but should never be applied to
      * a value statically known to be a JSFunction.
      */
     inline JSFunction *toFunction() MOZ_DELETE;
     inline const JSFunction *toFunction() const MOZ_DELETE;
 };
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -80,58 +80,16 @@ JSFunction::initializeExtended()
     JS_ASSERT(isExtended());
 
     JS_ASSERT(js::ArrayLength(toExtended()->extendedSlots) == 2);
     toExtended()->extendedSlots[0].init(js::UndefinedValue());
     toExtended()->extendedSlots[1].init(js::UndefinedValue());
 }
 
 inline void
-JSFunction::setJoinable()
-{
-    JS_ASSERT(isInterpreted());
-    flags |= JSFUN_JOINABLE;
-}
-
-inline bool
-JSFunction::isClonedMethod() const
-{
-    return joinable() && isExtended() && getExtendedSlot(METHOD_OBJECT_SLOT).isObject();
-}
-
-inline JSAtom *
-JSFunction::methodAtom() const
-{
-    return (joinable() && isExtended() && getExtendedSlot(METHOD_PROPERTY_SLOT).isString())
-           ? (JSAtom *) getExtendedSlot(METHOD_PROPERTY_SLOT).toString()
-           : NULL;
-}
-
-inline void
-JSFunction::setMethodAtom(JSAtom *atom)
-{
-    JS_ASSERT(joinable());
-    setExtendedSlot(METHOD_PROPERTY_SLOT, js::StringValue(atom));
-}
-
-inline JSObject *
-JSFunction::methodObj() const
-{
-    JS_ASSERT(joinable());
-    return isClonedMethod() ? &getExtendedSlot(METHOD_OBJECT_SLOT).toObject() : NULL;
-}
-
-inline void
-JSFunction::setMethodObj(JSObject& obj)
-{
-    JS_ASSERT(joinable());
-    setExtendedSlot(METHOD_OBJECT_SLOT, js::ObjectValue(obj));
-}
-
-inline void
 JSFunction::setExtendedSlot(size_t which, const js::Value &val)
 {
     JS_ASSERT(which < js::ArrayLength(toExtended()->extendedSlots));
     toExtended()->extendedSlots[which] = val;
 }
 
 inline const js::Value &
 JSFunction::getExtendedSlot(size_t which) const
@@ -283,20 +241,20 @@ CloneFunctionObject(JSContext *cx, JSFun
 
     return js_CloneFunctionObject(cx, fun, parent, proto, kind);
 }
 
 inline JSFunction *
 CloneFunctionObjectIfNotSingleton(JSContext *cx, JSFunction *fun, JSObject *parent)
 {
     /*
-     * For attempts to clone functions at a function definition opcode or from
-     * a method barrier, don't perform the clone if the function has singleton
-     * type. This was called pessimistically, and we need to preserve the
-     * type's property that if it is singleton there is only a single object
+     * For attempts to clone functions at a function definition opcode,
+     * don't perform the clone if the function has singleton type. This
+     * was called pessimistically, and we need to preserve the type's
+     * property that if it is singleton there is only a single object
      * with its type in existence.
      */
     if (fun->hasSingletonType()) {
         if (!fun->setParent(cx, SkipScopeParent(parent)))
             return NULL;
         fun->setEnvironment(parent);
         return fun;
     }
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -795,17 +795,17 @@ TypeSet::addFilterPrimitives(JSContext *
     add(cx, cx->typeLifoAlloc().new_<TypeConstraintFilterPrimitive>(target, filter));
 }
 
 /* If id is a normal slotful 'own' property of an object, get its shape. */
 static inline const Shape *
 GetSingletonShape(JSContext *cx, JSObject *obj, jsid id)
 {
     const Shape *shape = obj->nativeLookup(cx, id);
-    if (shape && shape->hasDefaultGetterOrIsMethod() && shape->hasSlot())
+    if (shape && shape->hasDefaultGetter() && shape->hasSlot())
         return shape;
     return NULL;
 }
 
 void
 ScriptAnalysis::pruneTypeBarriers(JSContext *cx, uint32_t offset)
 {
     TypeBarrier **pbarrier = &getCode(offset).typeBarriers;
@@ -2734,17 +2734,17 @@ UpdatePropertyType(JSContext *cx, TypeSe
 {
     types->setOwnProperty(cx, false);
     if (!shape->writable())
         types->setOwnProperty(cx, true);
 
     if (shape->hasGetterValue() || shape->hasSetterValue()) {
         types->setOwnProperty(cx, true);
         types->addType(cx, Type::UnknownType());
-    } else if (shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) {
+    } else if (shape->hasDefaultGetter() && shape->hasSlot()) {
         const Value &value = obj->nativeGetSlot(shape->slot());
 
         /*
          * Don't add initial undefined types for singleton properties that are
          * not collated into the JSID_VOID property (see propertySet comment).
          */
         if (force || !value.isUndefined()) {
             Type type = GetValueType(cx, value);
@@ -3662,18 +3662,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
       case JSOP_ARGUMENTS:
         /* Compute a precise type only when we know the arguments won't escape. */
         if (script->needsArgsObj())
             pushed[0].addType(cx, Type::UnknownType());
         else
             pushed[0].addType(cx, Type::LazyArgsType());
         break;
 
-      case JSOP_SETPROP:
-      case JSOP_SETMETHOD: {
+      case JSOP_SETPROP: {
         jsid id = GetAtomId(cx, script, pc, 0);
         poppedTypes(pc, 1)->addSetProperty(cx, script, pc, poppedTypes(pc, 0), id);
         poppedTypes(pc, 0)->addSubset(cx, &pushed[0]);
         break;
       }
 
       case JSOP_LENGTH:
       case JSOP_GETPROP:
@@ -3747,34 +3746,22 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
         break;
 
       case JSOP_NEG:
       case JSOP_POS:
         poppedTypes(pc, 0)->addArith(cx, script, pc, &pushed[0]);
         break;
 
       case JSOP_LAMBDA:
-      case JSOP_DEFFUN:
-      case JSOP_DEFLOCALFUN: {
-        unsigned off = op == JSOP_DEFLOCALFUN ? SLOTNO_LEN : 0;
-        JSObject *obj = script->getObject(GET_UINT32_INDEX(pc + off));
+      case JSOP_DEFFUN: {
+        JSObject *obj = script->getObject(GET_UINT32_INDEX(pc));
 
         TypeSet *res = NULL;
-        if (op == JSOP_LAMBDA) {
+        if (op == JSOP_LAMBDA)
             res = &pushed[0];
-        } else if (op == JSOP_DEFLOCALFUN) {
-            uint32_t slot = GetBytecodeSlot(script, pc);
-            if (trackSlot(slot)) {
-                res = &pushed[0];
-            } else {
-                /* Should not see 'let' vars here. */
-                JS_ASSERT(slot < TotalSlots(script));
-                res = TypeScript::SlotTypes(script, slot);
-            }
-        }
 
         if (res) {
             if (script->hasGlobal())
                 res->addType(cx, Type::ObjectType(obj));
             else
                 res->addType(cx, Type::UnknownType());
         } else {
             cx->compartment->types.monitorBytecode(cx, script, offset);
@@ -3882,18 +3869,17 @@ ScriptAnalysis::analyzeTypesBytecode(JSC
       case JSOP_SETTER:
         state.hasGetSet = true;
         break;
 
       case JSOP_HOLE:
         state.hasHole = true;
         break;
 
-      case JSOP_INITPROP:
-      case JSOP_INITMETHOD: {
+      case JSOP_INITPROP: {
         const SSAValue &objv = poppedValue(pc, 1);
         jsbytecode *initpc = script->code + objv.pushedOffset();
         TypeObject *initializer = GetInitializerType(cx, script, initpc);
 
         if (initializer) {
             pushed[0].addType(cx, Type::ObjectType(initializer));
             if (!initializer->unknownProperties()) {
                 jsid id = GetAtomId(cx, script, pc, 0);
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -364,17 +364,17 @@ Class js_NoSuchMethodClass = {
  * call by name, and args is an Array containing this invocation's actual
  * parameters.
  */
 bool
 js::OnUnknownMethod(JSContext *cx, JSObject *obj, Value idval, Value *vp)
 {
     jsid id = ATOM_TO_JSID(cx->runtime->atomState.noSuchMethodAtom);
     AutoValueRooter tvr(cx);
-    if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, tvr.addr()))
+    if (!js_GetMethod(cx, obj, id, 0, tvr.addr()))
         return false;
     TypeScript::MonitorUnknown(cx, cx->fp()->script(), cx->regs().pc);
 
     if (tvr.value().isPrimitive()) {
         *vp = tvr.value();
     } else {
 #if JS_HAS_XML_SUPPORT
         /* Extract the function name from function::name qname. */
@@ -1210,21 +1210,19 @@ js::AssertValidPropertyCacheHit(JSContex
  */
 JS_STATIC_ASSERT(JSOP_NAME_LENGTH == JSOP_CALLNAME_LENGTH);
 JS_STATIC_ASSERT(JSOP_GETARG_LENGTH == JSOP_CALLARG_LENGTH);
 JS_STATIC_ASSERT(JSOP_GETLOCAL_LENGTH == JSOP_CALLLOCAL_LENGTH);
 JS_STATIC_ASSERT(JSOP_XMLNAME_LENGTH == JSOP_CALLXMLNAME_LENGTH);
 
 /*
  * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but
- * remain distinct for the decompiler. Likewise for JSOP_INIT{PROP,METHOD}.
+ * remain distinct for the decompiler.
  */
 JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETPROP_LENGTH);
-JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH == JSOP_SETMETHOD_LENGTH);
-JS_STATIC_ASSERT(JSOP_INITPROP_LENGTH == JSOP_INITMETHOD_LENGTH);
 
 /* See TRY_BRANCH_AFTER_COND. */
 JS_STATIC_ASSERT(JSOP_IFNE_LENGTH == JSOP_IFEQ_LENGTH);
 JS_STATIC_ASSERT(JSOP_IFNE == JSOP_IFEQ + 1);
 
 /* For the fastest case inder JSOP_INCNAME, etc. */
 JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_DECNAME_LENGTH);
 JS_STATIC_ASSERT(JSOP_INCNAME_LENGTH == JSOP_NAMEINC_LENGTH);
@@ -1708,16 +1706,19 @@ ADD_EMPTY_CASE(JSOP_UNUSED19)
 ADD_EMPTY_CASE(JSOP_UNUSED20)
 ADD_EMPTY_CASE(JSOP_UNUSED21)
 ADD_EMPTY_CASE(JSOP_UNUSED22)
 ADD_EMPTY_CASE(JSOP_UNUSED23)
 ADD_EMPTY_CASE(JSOP_UNUSED24)
 ADD_EMPTY_CASE(JSOP_UNUSED25)
 ADD_EMPTY_CASE(JSOP_UNUSED26)
 ADD_EMPTY_CASE(JSOP_UNUSED27)
+ADD_EMPTY_CASE(JSOP_UNUSED28)
+ADD_EMPTY_CASE(JSOP_UNUSED29)
+ADD_EMPTY_CASE(JSOP_UNUSED30)
 ADD_EMPTY_CASE(JSOP_CONDSWITCH)
 ADD_EMPTY_CASE(JSOP_TRY)
 #if JS_HAS_XML_SUPPORT
 ADD_EMPTY_CASE(JSOP_STARTXML)
 ADD_EMPTY_CASE(JSOP_STARTXMLEXPR)
 #endif
 ADD_EMPTY_CASE(JSOP_LOOPHEAD)
 ADD_EMPTY_CASE(JSOP_LOOPENTRY)
@@ -2579,17 +2580,16 @@ BEGIN_CASE(JSOP_CALLPROP)
     regs.sp[-1] = rval;
     assertSameCompartment(cx, regs.sp[-1]);
 }
 END_CASE(JSOP_GETPROP)
 
 BEGIN_CASE(JSOP_SETGNAME)
 BEGIN_CASE(JSOP_SETNAME)
 BEGIN_CASE(JSOP_SETPROP)
-BEGIN_CASE(JSOP_SETMETHOD)
 {
     const Value &rval = regs.sp[-1];
     const Value &lval = regs.sp[-2];
 
     if (!SetPropertyOperation(cx, regs.pc, lval, rval))
         goto error;
 
     regs.sp[-2] = regs.sp[-1];
@@ -3142,124 +3142,27 @@ BEGIN_CASE(JSOP_DEFFUN)
 
         /* Step 5f. */
         if (!parent->setProperty(cx, name, &rval, script->strictModeCode))
             goto error;
     } while (false);
 }
 END_CASE(JSOP_DEFFUN)
 
-BEGIN_CASE(JSOP_DEFLOCALFUN)
-{
-    /*
-     * Define a local function (i.e., one nested at the top level of another
-     * function), parented by the current scope chain, stored in a local
-     * variable slot that the compiler allocated.  This is an optimization over
-     * JSOP_DEFFUN that avoids requiring a call object for the outer function's
-     * activation.
-     */
-    JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc + SLOTNO_LEN));
-    JS_ASSERT(fun->isInterpreted());
-
-    JSObject *parent;
-    if (fun->isNullClosure()) {
-        parent = &regs.fp()->scopeChain();
-    } else {
-        parent = GetScopeChain(cx, regs.fp());
-        if (!parent)
-            goto error;
-    }
-    JSObject *obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
-    if (!obj)
-        goto error;
-
-    JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
-
-    regs.fp()->varSlot(GET_SLOTNO(regs.pc)) = ObjectValue(*obj);
-}
-END_CASE(JSOP_DEFLOCALFUN)
-
 BEGIN_CASE(JSOP_LAMBDA)
 {
     /* Load the specified function object literal. */
     JSFunction *fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
     JSObject *obj = fun;
 
     /* do-while(0) so we can break instead of using a goto. */
     do {
         JSObject *parent;
         if (fun->isNullClosure()) {
             parent = &regs.fp()->scopeChain();
-
-            if (fun->joinable()) {
-                jsbytecode *pc2 = regs.pc + JSOP_LAMBDA_LENGTH;
-                JSOp op2 = JSOp(*pc2);
-
-                /*
-                 * Optimize var obj = {method: function () { ... }, ...},
-                 * this.method = function () { ... }; and other significant
-                 * single-use-of-null-closure bytecode sequences.
-                 */
-                if (op2 == JSOP_INITMETHOD) {
-#ifdef DEBUG
-                    const Value &lref = regs.sp[-1];
-                    JS_ASSERT(lref.isObject());
-                    JSObject *obj2 = &lref.toObject();
-                    JS_ASSERT(obj2->isObject());
-#endif
-                    JS_ASSERT(fun->methodAtom() ==
-                              script->getAtom(GET_UINT32_INDEX(regs.pc + JSOP_LAMBDA_LENGTH)));
-                    break;
-                }
-
-                if (op2 == JSOP_SETMETHOD) {
-#ifdef DEBUG
-                    op2 = JSOp(pc2[JSOP_SETMETHOD_LENGTH]);
-                    JS_ASSERT(op2 == JSOP_POP || op2 == JSOP_POPV);
-#endif
-                    const Value &lref = regs.sp[-1];
-                    if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) {
-                        JS_ASSERT(fun->methodAtom() ==
-                                  script->getAtom(GET_UINT32_INDEX(regs.pc + JSOP_LAMBDA_LENGTH)));
-                        break;
-                    }
-                } else if (op2 == JSOP_CALL) {
-                    /*
-                     * Array.prototype.sort and String.prototype.replace are
-                     * optimized as if they are special form. We know that they
-                     * won't leak the joined function object in obj, therefore
-                     * we don't need to clone that compiler-created function
-                     * object for identity/mutation reasons.
-                     */
-                    int iargc = GET_ARGC(pc2);
-
-                    /*
-                     * Note that we have not yet pushed obj as the final argument,
-                     * so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
-                     * is the callee for this JSOP_CALL.
-                     */
-                    const Value &cref = regs.sp[1 - (iargc + 2)];
-                    JSFunction *fun;
-
-                    if (IsFunctionObject(cref, &fun)) {
-                        if (Native native = fun->maybeNative()) {
-                            if ((iargc == 1 && native == array_sort) ||
-                                (iargc == 2 && native == str_replace)) {
-                                break;
-                            }
-                        }
-                    }
-                } else if (op2 == JSOP_NULL) {
-                    pc2 += JSOP_NULL_LENGTH;
-                    op2 = JSOp(*pc2);
-
-                    if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0)
-                        break;
-                }
-            }
         } else {
             parent = GetScopeChain(cx, regs.fp());
             if (!parent)
                 goto error;
         }
 
         obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
         if (!obj)
@@ -3429,35 +3332,33 @@ BEGIN_CASE(JSOP_ENDINIT)
 {
     /* FIXME remove JSOP_ENDINIT bug 588522 */
     JS_ASSERT(regs.sp - regs.fp()->base() >= 1);
     JS_ASSERT(regs.sp[-1].isObject());
 }
 END_CASE(JSOP_ENDINIT)
 
 BEGIN_CASE(JSOP_INITPROP)
-BEGIN_CASE(JSOP_INITMETHOD)
 {
     /* Load the property's initial value into rval. */
     JS_ASSERT(regs.sp - regs.fp()->base() >= 2);
     Value rval = regs.sp[-1];
 
     /* Load the object being initialized into lval/obj. */
     JSObject *obj = &regs.sp[-2].toObject();
     JS_ASSERT(obj->isObject());
 
     JSAtom *atom;
     LOAD_ATOM(0, atom);
     jsid id = ATOM_TO_JSID(atom);
 
-    unsigned defineHow = (op == JSOP_INITMETHOD) ? DNP_SET_METHOD : 0;
     if (JS_UNLIKELY(atom == cx->runtime->atomState.protoAtom)
-        ? !js_SetPropertyHelper(cx, obj, id, defineHow, &rval, script->strictModeCode)
+        ? !js_SetPropertyHelper(cx, obj, id, 0, &rval, script->strictModeCode)
         : !DefineNativeProperty(cx, obj, id, rval, NULL, NULL,
-                                JSPROP_ENUMERATE, 0, 0, defineHow)) {
+                                JSPROP_ENUMERATE, 0, 0, 0)) {
         goto error;
     }
 
     regs.sp--;
 }
 END_CASE(JSOP_INITPROP);
 
 BEGIN_CASE(JSOP_INITELEM)
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -239,38 +239,34 @@ GetPropertyOperation(JSContext *cx, jsby
             }
         }
     }
 
     JSObject *obj = ValueToObject(cx, lval);
     if (!obj)
         return false;
 
-    unsigned flags = (op == JSOP_CALLPROP)
-                  ? JSGET_CACHE_RESULT | JSGET_NO_METHOD_BARRIER
-                  : JSGET_CACHE_RESULT | JSGET_METHOD_BARRIER;
-
     PropertyCacheEntry *entry;
     JSObject *obj2;
     PropertyName *name;
     JS_PROPERTY_CACHE(cx).test(cx, pc, obj, obj2, entry, name);
     if (!name) {
         AssertValidPropertyCacheHit(cx, obj, obj2, entry);
-        if (!NativeGet(cx, obj, obj2, entry->prop, flags, vp))
+        if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_CACHE_RESULT, vp))
             return false;
         return true;
     }
 
     jsid id = ATOM_TO_JSID(name);
 
     if (obj->getOps()->getProperty) {
         if (!GetPropertyGenericMaybeCallXML(cx, op, obj, id, vp))
             return false;
     } else {
-        if (!GetPropertyHelper(cx, obj, id, flags, vp))
+        if (!GetPropertyHelper(cx, obj, id, JSGET_CACHE_RESULT, vp))
             return false;
     }
 
 #if JS_HAS_NO_SUCH_METHOD
     if (op == JSOP_CALLPROP &&
         JS_UNLIKELY(vp->isPrimitive()) &&
         lval.isObject())
     {
@@ -284,17 +280,16 @@ GetPropertyOperation(JSContext *cx, jsby
 
 inline bool
 SetPropertyOperation(JSContext *cx, jsbytecode *pc, const Value &lval, const Value &rval)
 {
     JSObject *obj = ValueToObject(cx, lval);
     if (!obj)
         return false;
 
-    JS_ASSERT_IF(*pc == JSOP_SETMETHOD, IsFunctionObject(rval));
     JS_ASSERT_IF(*pc == JSOP_SETNAME || *pc == JSOP_SETGNAME, lval.isObject());
     JS_ASSERT_IF(*pc == JSOP_SETGNAME, obj == &cx->fp()->scopeChain().global());
 
     PropertyCacheEntry *entry;
     JSObject *obj2;
     PropertyName *name;
     if (JS_PROPERTY_CACHE(cx).testForSet(cx, pc, obj, &entry, &obj2, &name)) {
         /*
@@ -317,17 +312,17 @@ SetPropertyOperation(JSContext *cx, jsby
             } else {
                 JS_ASSERT(obj2->nativeContains(cx, *shape));
                 JS_ASSERT(entry->isPrototypePropertyHit());
                 JS_ASSERT(entry->kshape != entry->pshape);
                 JS_ASSERT(!shape->hasSlot());
             }
 #endif
 
-            if (shape->hasDefaultSetter() && shape->hasSlot() && !shape->isMethod()) {
+            if (shape->hasDefaultSetter() && shape->hasSlot()) {
                 /* Fast path for, e.g., plain Object instance properties. */
                 obj->nativeSetSlotWithType(cx, shape, rval);
             } else {
                 Value rref = rval;
                 bool strict = cx->stack.currentScript()->strictModeCode;
                 if (!js_NativeSet(cx, obj, shape, false, strict, &rref))
                     return false;
             }
@@ -339,23 +334,19 @@ SetPropertyOperation(JSContext *cx, jsby
 
     bool strict = cx->stack.currentScript()->strictModeCode;
     Value rref = rval;
 
     JSOp op = JSOp(*pc);
 
     jsid id = ATOM_TO_JSID(name);
     if (JS_LIKELY(!obj->getOps()->setProperty)) {
-        unsigned defineHow;
-        if (op == JSOP_SETMETHOD)
-            defineHow = DNP_CACHE_RESULT | DNP_SET_METHOD;
-        else if (op == JSOP_SETNAME)
-            defineHow = DNP_CACHE_RESULT | DNP_UNQUALIFIED;
-        else
-            defineHow = DNP_CACHE_RESULT;
+        unsigned defineHow = (op == JSOP_SETNAME)
+                             ? DNP_CACHE_RESULT | DNP_UNQUALIFIED
+                             : DNP_CACHE_RESULT;
         if (!js_SetPropertyHelper(cx, obj, id, defineHow, &rref, strict))
             return false;
     } else {
         if (!obj->setGeneric(cx, id, &rref, strict))
             return false;
     }
 
     return true;
@@ -379,17 +370,17 @@ NameOperation(JSContext *cx, jsbytecode 
         obj = &obj->global();
 
     PropertyCacheEntry *entry;
     JSObject *obj2;
     PropertyName *name;
     JS_PROPERTY_CACHE(cx).test(cx, pc, obj, obj2, entry, name);
     if (!name) {
         AssertValidPropertyCacheHit(cx, obj, obj2, entry);
-        if (!NativeGet(cx, obj, obj2, entry->prop, JSGET_METHOD_BARRIER, vp))
+        if (!NativeGet(cx, obj, obj2, entry->prop, 0, vp))
             return false;
         return true;
     }
 
     jsid id = ATOM_TO_JSID(name);
 
     JSProperty *prop;
     if (!FindPropertyHelper(cx, name, true, obj, &obj, &obj2, &prop))
@@ -411,17 +402,17 @@ NameOperation(JSContext *cx, jsbytecode 
     if (!obj->isNative() || !obj2->isNative()) {
         if (!obj->getGeneric(cx, id, vp))
             return false;
     } else {
         Shape *shape = (Shape *)prop;
         JSObject *normalized = obj;
         if (normalized->getClass() == &WithClass && !shape->hasDefaultGetter())
             normalized = &normalized->asWith().object();
-        if (!NativeGet(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, vp))
+        if (!NativeGet(cx, normalized, obj2, shape, 0, vp))
             return false;
     }
 
     return true;
 }
 
 inline bool
 DefVarOrConstOperation(JSContext *cx, JSObject &varobj, PropertyName *dn, unsigned attrs)
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -454,17 +454,17 @@ GetCustomIterator(JSContext *cx, JSObjec
     if (flags == JSITER_FOR_OF) {
         js_ReportValueErrorFlags(cx, JSREPORT_ERROR, JSMSG_NOT_ITERABLE,
                                  JSDVG_SEARCH_STACK, ObjectValue(*obj), NULL, NULL, NULL);
         return false;
     }
 
     /* Check whether we have a valid __iterator__ method. */
     JSAtom *atom = cx->runtime->atomState.iteratorAtom;
-    if (!js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, vp))
+    if (!js_GetMethod(cx, obj, ATOM_TO_JSID(atom), 0, vp))
         return false;
 
     /* If there is no custom __iterator__ method, we are done here. */
     if (!vp->isObject()) {
         vp->setUndefined();
         return true;
     }
 
@@ -1237,17 +1237,17 @@ js_IteratorMore(JSContext *cx, JSObject 
             return false;
         if (rval->isMagic(JS_NO_ITER_VALUE)) {
             rval->setBoolean(false);
             return true;
         }
     } else {
         /* Call the iterator object's .next method. */
         jsid id = ATOM_TO_JSID(cx->runtime->atomState.nextAtom);
-        if (!js_GetMethod(cx, iterobj, id, JSGET_METHOD_BARRIER, rval))
+        if (!js_GetMethod(cx, iterobj, id, 0, rval))
             return false;
         if (!Invoke(cx, ObjectValue(*iterobj), *rval, 0, NULL, rval)) {
             /* Check for StopIteration. */
             if (!cx->isExceptionPending() || !IsStopIteration(cx->getPendingException()))
                 return false;
 
             cx->clearPendingException();
             cx->iterValue.setMagic(JS_NO_ITER_VALUE);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1958,17 +1958,17 @@ DefinePropertyOnObject(JSContext *cx, JS
                 if (!shape->configurable() &&
                     (!shape->hasDefaultGetter() || !shape->hasDefaultSetter()) &&
                     desc.isDataDescriptor() &&
                     (desc.hasWritable ? desc.writable() : shape->writable()))
                 {
                     return Reject(cx, JSMSG_CANT_REDEFINE_PROP, throwError, id, rval);
                 }
 
-                if (!js_NativeGet(cx, obj, obj2, shape, JSGET_NO_METHOD_BARRIER, &v))
+                if (!js_NativeGet(cx, obj, obj2, shape, 0, &v))
                     return JS_FALSE;
             }
 
             if (desc.isDataDescriptor()) {
                 if (!shape->isDataDescriptor())
                     break;
 
                 bool same;
@@ -2087,24 +2087,18 @@ DefinePropertyOnObject(JSContext *cx, JS
     if (desc.isGenericDescriptor()) {
         unsigned changed = 0;
         if (desc.hasConfigurable)
             changed |= JSPROP_PERMANENT;
         if (desc.hasEnumerable)
             changed |= JSPROP_ENUMERATE;
 
         attrs = (shape->attributes() & ~changed) | (desc.attrs & changed);
-        if (shape->isMethod()) {
-            JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
-            getter = JS_PropertyStub;
-            setter = JS_StrictPropertyStub;
-        } else {
-            getter = shape->getter();
-            setter = shape->setter();
-        }
+        getter = shape->getter();
+        setter = shape->setter();
     } else if (desc.isDataDescriptor()) {
         unsigned unchanged = 0;
         if (!desc.hasConfigurable)
             unchanged |= JSPROP_PERMANENT;
         if (!desc.hasEnumerable)
             unchanged |= JSPROP_ENUMERATE;
         /* Watch out for accessor -> data transformations here. */
         if (!desc.hasWritable && shape->isDataDescriptor())
@@ -2121,34 +2115,32 @@ DefinePropertyOnObject(JSContext *cx, JS
         /*
          * Getters and setters are just like watchpoints from an access
          * control point of view.
          */
         Value dummy;
         if (!CheckAccess(cx, obj2, id, JSACC_WATCH, &dummy, &attrs))
              return JS_FALSE;
 
-        JS_ASSERT_IF(shape->isMethod(), !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
-
         /* 8.12.9 step 12. */
         unsigned changed = 0;
         if (desc.hasConfigurable)
             changed |= JSPROP_PERMANENT;
         if (desc.hasEnumerable)
             changed |= JSPROP_ENUMERATE;
         if (desc.hasGet)
             changed |= JSPROP_GETTER | JSPROP_SHARED | JSPROP_READONLY;
         if (desc.hasSet)
             changed |= JSPROP_SETTER | JSPROP_SHARED | JSPROP_READONLY;
 
         attrs = (desc.attrs & changed) | (shape->attributes() & ~changed);
         if (desc.hasGet) {
             getter = desc.getter();
         } else {
-            getter = (shape->isMethod() || (shape->hasDefaultGetter() && !shape->hasGetterValue()))
+            getter = (shape->hasDefaultGetter() && !shape->hasGetterValue())
                      ? JS_PropertyStub
                      : shape->getter();
         }
         if (desc.hasSet) {
             setter = desc.setter();
         } else {
             setter = (shape->hasDefaultSetter() && !shape->hasSetterValue())
                      ? JS_StrictPropertyStub
@@ -4394,52 +4386,30 @@ js_PurgeScopeChainHelper(JSContext *cx, 
     return true;
 }
 
 Shape *
 js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
                      PropertyOp getter, StrictPropertyOp setter, uint32_t slot,
                      unsigned attrs, unsigned flags, int shortid)
 {
-    JS_ASSERT(!(flags & Shape::METHOD));
-
     /* Convert string indices to integers if appropriate. */
     id = js_CheckForStringIndex(id);
 
     /*
      * Purge the property cache of now-shadowed id in obj's scope chain. Do
      * this optimistically (assuming no failure below) before locking obj, so
      * we can lock the shadowed scope.
      */
     if (!js_PurgeScopeChain(cx, obj, id))
         return NULL;
 
     return obj->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid);
 }
 
-Shape *
-js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
-                             Shape *shape, unsigned attrs, unsigned mask,
-                             PropertyOp getter, StrictPropertyOp setter)
-{
-    /*
-     * Check for freezing an object with shape-memoized methods here, on a
-     * shape-by-shape basis.
-     */
-    if ((attrs & JSPROP_READONLY) && shape->isMethod()) {
-        Value v = ObjectValue(*obj->nativeGetMethod(shape));
-
-        shape = obj->methodReadBarrier(cx, *shape, &v);
-        if (!shape)
-            return NULL;
-    }
-
-    return obj->changeProperty(cx, shape, attrs, mask, getter, setter);
-}
-
 JSBool
 js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                   PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
 {
     return !!DefineNativeProperty(cx, obj, id, *value, getter, setter, attrs, 0, 0);
 }
 
 JSBool
@@ -4477,25 +4447,22 @@ CallAddPropertyHook(JSContext *cx, Class
 namespace js {
 
 const Shape *
 DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value_,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow /* = 0 */)
 {
     JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_DONT_PURGE |
-                             DNP_SET_METHOD | DNP_SKIP_TYPE)) == 0);
+                             DNP_SKIP_TYPE)) == 0);
 
     RootObject objRoot(cx, &obj);
     RootId idRoot(cx, &id);
 
-    /*
-     * Make a local copy of value, in case a method barrier needs to update the
-     * value to define, and just so addProperty can mutate its inout parameter.
-     */
+    /* Make a local copy of value so addProperty can mutate its inout parameter. */
     RootedVarValue value(cx);
     value = value_;
 
     /* Convert string indices to integers if appropriate. */
     id = js_CheckForStringIndex(id);
 
     /*
      * If defining a getter or setter, we must check for its counterpart and
@@ -4544,61 +4511,32 @@ DefineNativeProperty(JSContext *cx, JSOb
      */
     if (!(defineHow & DNP_DONT_PURGE)) {
         if (!js_PurgeScopeChain(cx, obj, id))
             return NULL;
     }
 
     /* Use the object's class getter and setter by default. */
     Class *clasp = obj->getClass();
-    if (!(defineHow & DNP_SET_METHOD)) {
-        if (!getter && !(attrs & JSPROP_GETTER))
-            getter = clasp->getProperty;
-        if (!setter && !(attrs & JSPROP_SETTER))
-            setter = clasp->setProperty;
-    }
-
-    if (((defineHow & DNP_SET_METHOD) || getter == JS_PropertyStub) &&
-        !(defineHow & DNP_SKIP_TYPE)) {
+    if (!getter && !(attrs & JSPROP_GETTER))
+        getter = clasp->getProperty;
+    if (!setter && !(attrs & JSPROP_SETTER))
+        setter = clasp->setProperty;
+
+    if ((getter == JS_PropertyStub) && !(defineHow & DNP_SKIP_TYPE)) {
         /*
          * Type information for normal native properties should reflect the
          * initial value of the property.
          */
         AddTypePropertyId(cx, obj, id, value);
         if (attrs & JSPROP_READONLY)
             MarkTypePropertyConfigured(cx, obj, id);
     }
 
     if (!shape) {
-        /* Add a new property, or replace an existing one of the same id. */
-        if (defineHow & DNP_SET_METHOD) {
-            JS_ASSERT(clasp == &ObjectClass);
-            JS_ASSERT(IsFunctionObject(value));
-            JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
-            JS_ASSERT(!getter && !setter);
-
-            JSObject *funobj = &value.raw().toObject();
-            if (!funobj->toFunction()->isClonedMethod())
-                flags |= Shape::METHOD;
-        }
-
-        if (const Shape *existingShape = obj->nativeLookup(cx, id)) {
-            if (existingShape->isMethod() &&
-                ObjectValue(*obj->nativeGetMethod(existingShape)) == value)
-            {
-                /*
-                 * Redefining an existing shape-memoized method object without
-                 * changing the property's value, perhaps to change attributes.
-                 * Clone now via the method read barrier.
-                 */
-                if (!obj->methodReadBarrier(cx, *existingShape, value.address()))
-                    return NULL;
-            }
-        }
-
         shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT,
                                  attrs, flags, shortid);
         if (!shape)
             return NULL;
     }
 
     /* Store valueCopy before calling addProperty, in case the latter GC's. */
     if (shape->hasSlot())
@@ -4965,44 +4903,38 @@ static JS_ALWAYS_INLINE JSBool
 js_NativeGetInline(JSContext *cx, JSObject *receiver, JSObject *obj, JSObject *pobj,
                    const Shape *shape, unsigned getHow, Value *vp)
 {
     JS_ASSERT(pobj->isNative());
 
     if (shape->hasSlot()) {
         *vp = pobj->nativeGetSlot(shape->slot());
         JS_ASSERT(!vp->isMagic());
-        JS_ASSERT_IF(!pobj->hasSingletonType() && shape->hasDefaultGetterOrIsMethod(),
+        JS_ASSERT_IF(!pobj->hasSingletonType() && shape->hasDefaultGetter(),
                      js::types::TypeHasProperty(cx, pobj->type(), shape->propid(), *vp));
     } else {
         vp->setUndefined();
     }
     if (shape->hasDefaultGetter())
         return true;
 
-    if (JS_UNLIKELY(shape->isMethod()) && (getHow & JSGET_NO_METHOD_BARRIER))
-        return true;
-
     jsbytecode *pc;
     JSScript *script = cx->stack.currentScript(&pc);
     if (script && script->hasAnalysis()) {
         analyze::Bytecode *code = script->analysis()->maybeCode(pc);
         if (code)
             code->accessGetter = true;
     }
 
     if (!shape->get(cx, receiver, obj, pobj, vp))
         return false;
 
     /* Update slotful shapes according to the value produced by the getter. */
-    if (shape->hasSlot() && pobj->nativeContains(cx, *shape)) {
-        /* Method shapes were removed by methodReadBarrier under shape->get(). */
-        JS_ASSERT(!shape->isMethod());
+    if (shape->hasSlot() && pobj->nativeContains(cx, *shape))
         pobj->nativeSetSlot(shape->slot(), *vp);
-    }
 
     return true;
 }
 
 JSBool
 js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj, const Shape *shape, unsigned getHow,
              Value *vp)
 {
@@ -5016,20 +4948,16 @@ js_NativeSet(JSContext *cx, JSObject *ob
 
     JS_ASSERT(obj->isNative());
 
     if (shape->hasSlot()) {
         uint32_t slot = shape->slot();
 
         /* If shape has a stub setter, just store *vp. */
         if (shape->hasDefaultSetter()) {
-            if (!added) {
-                if (shape->isMethod() && !obj->methodShapeChange(cx, *shape))
-                    return false;
-            }
             obj->nativeSetSlot(slot, *vp);
             return true;
         }
     } else {
         /*
          * Allow API consumers to create shared properties with stub setters.
          * Such properties effectively function as data descriptors which are
          * not writable, so attempting to set such a property should do nothing
@@ -5157,28 +5085,28 @@ js::GetPropertyHelper(JSContext *cx, JSO
 {
     return !!js_GetPropertyHelperInline(cx, obj, obj, id, getHow, vp);
 }
 
 JSBool
 js_GetProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp)
 {
     /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
-    return js_GetPropertyHelperInline(cx, obj, receiver, id, JSGET_METHOD_BARRIER, vp);
+    return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
 }
 
 JSBool
 js_GetElement(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp)
 {
     jsid id;
     if (!IndexToId(cx, index, &id))
         return false;
 
     /* This call site is hot -- use the always-inlined variant of js_GetPropertyHelper(). */
-    return js_GetPropertyHelperInline(cx, obj, receiver, id, JSGET_METHOD_BARRIER, vp);
+    return js_GetPropertyHelperInline(cx, obj, receiver, id, 0, vp);
 }
 
 JSBool
 js::GetPropertyDefault(JSContext *cx, JSObject *obj, jsid id, const Value &def, Value *vp)
 {
     JSProperty *prop;
     JSObject *obj2;
     if (!LookupPropertyWithFlags(cx, obj, id, JSRESOLVE_QUALIFIED, &obj2, &prop))
@@ -5256,62 +5184,44 @@ JSObject::reportNotExtensible(JSContext 
                                     JSDVG_IGNORE_STACK, ObjectValue(*this),
                                     NULL, NULL, NULL);
 }
 
 bool
 JSObject::callMethod(JSContext *cx, jsid id, unsigned argc, Value *argv, Value *vp)
 {
     Value fval;
-    return js_GetMethod(cx, this, id, JSGET_NO_METHOD_BARRIER, &fval) &&
+    return js_GetMethod(cx, this, id, 0, &fval) &&
            Invoke(cx, ObjectValue(*this), fval, argc, argv, vp);
 }
 
-static bool
-CloneFunctionForSetMethod(JSContext *cx, Value *vp)
-{
-    JSFunction *fun = vp->toObject().toFunction();
-
-    /* Clone the fun unless it already has been. */
-    if (!fun->isClonedMethod()) {
-        fun = CloneFunctionObject(cx, fun);
-        if (!fun)
-            return false;
-        vp->setObject(*fun);
-    }
-    return true;
-}
-
 JSBool
 js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, unsigned defineHow,
                      Value *vp, JSBool strict)
 {
     JSObject *pobj;
     JSProperty *prop;
     const Shape *shape;
     unsigned attrs, flags;
     int shortid;
     Class *clasp;
     PropertyOp getter;
     StrictPropertyOp setter;
     bool added;
 
-    JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_SET_METHOD | DNP_UNQUALIFIED)) == 0);
+    JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0);
 
     /* Convert string indices to integers if appropriate. */
     id = js_CheckForStringIndex(id);
 
     if (JS_UNLIKELY(obj->watched())) {
         /* Fire watchpoints, if any. */
         WatchpointMap *wpmap = cx->compartment->watchpointMap;
         if (wpmap && !wpmap->triggerWatchpoint(cx, obj, id, vp))
             return false;
-
-        /* A watchpoint handler may set *vp to a non-function value. */
-        defineHow &= ~DNP_SET_METHOD;
     }
 
     if (!LookupPropertyWithFlags(cx, obj, id, cx->resolveFlags, &pobj, &prop))
         return false;
     if (prop) {
         if (!pobj->isNative()) {
             if (pobj->isProxy()) {
                 AutoPropertyDescriptorRooter pd(cx);
@@ -5376,22 +5286,16 @@ js_SetPropertyHelper(JSContext *cx, JSOb
         }
 
         attrs = shape->attributes();
         if (pobj != obj) {
             /*
              * We found id in a prototype object: prepare to share or shadow.
              */
             if (!shape->shadowable()) {
-                if (defineHow & DNP_SET_METHOD) {
-                    JS_ASSERT(!shape->isMethod());
-                    if (!CloneFunctionForSetMethod(cx, vp))
-                        return false;
-                }
-
                 if (defineHow & DNP_CACHE_RESULT)
                     JS_PROPERTY_CACHE(cx).fill(cx, obj, 0, pobj, shape);
 
                 if (shape->hasDefaultSetter() && !shape->hasGetterValue())
                     return JS_TRUE;
 
                 return shape->set(cx, obj, strict, vp);
             }
@@ -5407,17 +5311,16 @@ js_SetPropertyHelper(JSContext *cx, JSOb
              *
              * A subset of slotless shared properties is the set of properties
              * with shortids, which must be preserved too. An old API requires
              * that the property's getter and setter receive the shortid, not
              * id, when they are called on the shadowing property that we are
              * about to create in obj.
              */
             if (!shape->hasSlot()) {
-                defineHow &= ~DNP_SET_METHOD;
                 if (shape->hasShortID()) {
                     flags = Shape::HAS_SHORTID;
                     shortid = shape->shortid();
                 }
                 attrs &= ~JSPROP_SHARED;
                 getter = shape->getter();
                 setter = shape->setter();
             } else {
@@ -5426,36 +5329,16 @@ js_SetPropertyHelper(JSContext *cx, JSOb
             }
 
             /*
              * Forget we found the proto-property now that we've copied any
              * needed member values.
              */
             shape = NULL;
         }
-
-        if (shape && (defineHow & DNP_SET_METHOD)) {
-            /*
-             * JSOP_SETMETHOD is assigning to an existing own property. If it
-             * is an identical method property, do nothing. Otherwise downgrade
-             * to ordinary assignment. Either way, do not fill the property
-             * cache, as the interpreter has no fast path for these unusual
-             * cases.
-             */
-            if (shape->isMethod()) {
-                if (obj->nativeGetMethod(shape) == &vp->toObject())
-                    return true;
-                shape = obj->methodShapeChange(cx, *shape);
-                if (!shape)
-                    return false;
-            }
-            if (!CloneFunctionForSetMethod(cx, vp))
-                return false;
-            return js_NativeSet(cx, obj, shape, false, strict, vp);
-        }
     }
 
     added = false;
     if (!shape) {
         if (!obj->isExtensible()) {
             /* Error in strict mode code, warn with strict option, otherwise do nothing. */
             if (strict)
                 return obj->reportNotExtensible(cx);
@@ -5466,29 +5349,16 @@ js_SetPropertyHelper(JSContext *cx, JSOb
 
         /*
          * Purge the property cache of now-shadowed id in obj's scope chain.
          * Do this early, before locking obj to avoid nesting locks.
          */
         if (!js_PurgeScopeChain(cx, obj, id))
             return JS_FALSE;
 
-        /*
-         * Check for Object class here to avoid defining a method on a class
-         * with magic resolve, addProperty, getProperty, etc. hooks.
-         */
-        if ((defineHow & DNP_SET_METHOD) && obj->canHaveMethodBarrier()) {
-            JS_ASSERT(IsFunctionObject(*vp));
-            JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
-
-            JSObject *funobj = &vp->toObject();
-            if (!funobj->toFunction()->isClonedMethod())
-                flags |= Shape::METHOD;
-        }
-
         shape = obj->putProperty(cx, id, getter, setter, SHAPE_INVALID_SLOT,
                                  attrs, flags, shortid);
         if (!shape)
             return JS_FALSE;
 
         /*
          * Initialize the new property value (passed to setter) to undefined.
          * Note that we store before calling addProperty, to match the order
@@ -5553,46 +5423,38 @@ js_GetElementAttributes(JSContext *cx, J
         return obj->getElementAttributes(cx, index, attrsp);
 
     const Shape *shape = (Shape *)prop;
     *attrsp = shape->attributes();
     return true;
 }
 
 JSBool
-js_SetNativeAttributes(JSContext *cx, JSObject *obj, Shape *shape, unsigned attrs)
-{
-    JS_ASSERT(obj->isNative());
-    return !!js_ChangeNativePropertyAttrs(cx, obj, shape, attrs, 0,
-                                          shape->getter(), shape->setter());
-}
-
-JSBool
 js_SetAttributes(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp)
 {
     JSProperty *prop;
     if (!js_LookupProperty(cx, obj, id, &obj, &prop))
         return false;
     if (!prop)
         return true;
     return obj->isNative()
-           ? js_SetNativeAttributes(cx, obj, (Shape *) prop, *attrsp)
+           ? obj->changePropertyAttributes(cx, (Shape *) prop, *attrsp)
            : obj->setGenericAttributes(cx, id, attrsp);
 }
 
 JSBool
 js_SetElementAttributes(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp)
 {
     JSProperty *prop;
     if (!js_LookupElement(cx, obj, index, &obj, &prop))
         return false;
     if (!prop)
         return true;
     return obj->isNative()
-           ? js_SetNativeAttributes(cx, obj, (Shape *) prop, *attrsp)
+           ? obj->changePropertyAttributes(cx, (Shape *) prop, *attrsp)
            : obj->setElementAttributes(cx, index, attrsp);
 }
 
 JSBool
 js_DeleteGeneric(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict)
 {
     JSObject *proto;
     JSProperty *prop;
@@ -5619,45 +5481,16 @@ js_DeleteGeneric(JSContext *cx, JSObject
             return obj->reportNotConfigurable(cx, id);
         rval->setBoolean(false);
         return true;
     }
 
     if (shape->hasSlot()) {
         const Value &v = obj->nativeGetSlot(shape->slot());
         GCPoke(cx->runtime, v);
-
-        /*
-         * Delete is rare enough that we can take the hit of checking for an
-         * active cloned method function object that must be homed to a callee
-         * slot on the active stack frame before this delete completes, in case
-         * someone saved the clone and checks it against foo.caller for a foo
-         * called from the active method.
-         *
-         * We do not check suspended frames. They can't be reached via caller,
-         * so the only way they could have the method's joined function object
-         * as callee is through an API abusage. We break any such edge case.
-         */
-        JSFunction *fun;
-        if (IsFunctionObject(v, &fun) && fun->isClonedMethod()) {
-            for (StackFrame *fp = cx->maybefp(); fp; fp = fp->prev()) {
-                if (fp->isFunctionFrame() &&
-                    fp->fun()->script() == fun->script() &&
-                    fp->thisValue().isObject())
-                {
-                    JSObject *tmp = &fp->thisValue().toObject();
-                    do {
-                        if (tmp == obj) {
-                            fp->overwriteCallee(*fun);
-                            break;
-                        }
-                    } while ((tmp = tmp->getProto()) != NULL);
-                }
-            }
-        }
     }
 
     if (!CallJSPropertyOp(cx, obj->getClass()->delProperty, obj, shape->getUserId(), rval))
         return false;
     if (rval->isFalse())
         return true;
 
     return obj->removeProperty(cx, id) && js_SuppressDeletedProperty(cx, obj, id);
@@ -5686,17 +5519,17 @@ js_DeleteSpecial(JSContext *cx, JSObject
 
 namespace js {
 
 bool
 HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
     JS_ASSERT(id == js_CheckForStringIndex(id));
     if (const Shape *shape = obj->nativeLookup(cx, id)) {
-        if (shape->hasDefaultGetterOrIsMethod() && shape->hasSlot()) {
+        if (shape->hasDefaultGetter() && shape->hasSlot()) {
             *vp = obj->nativeGetSlot(shape->slot());
             return true;
         }
     }
 
     return false;
 }
 
@@ -5706,17 +5539,17 @@ HasDataProperty(JSContext *cx, JSObject 
  * and |obj| as |this|, returning the result in *vp.
  *
  * This is a mini-abstraction for ES5 8.12.8 [[DefaultValue]], either steps 1-2
  * or steps 3-4.
  */
 static bool
 MaybeCallMethod(JSContext *cx, JSObject *obj, jsid id, Value *vp)
 {
-    if (!js_GetMethod(cx, obj, id, JSGET_NO_METHOD_BARRIER, vp))
+    if (!js_GetMethod(cx, obj, id, 0, vp))
         return false;
     if (!js_IsCallable(*vp)) {
         *vp = ObjectValue(*obj);
         return true;
     }
     return Invoke(cx, ObjectValue(*obj), *vp, 0, NULL, vp);
 }
 
@@ -6216,17 +6049,16 @@ DumpProperty(JSObject *obj, const Shape 
     jsid id = shape.propid();
     uint8_t attrs = shape.attributes();
 
     fprintf(stderr, "    ((Shape *) %p) ", (void *) &shape);
     if (attrs & JSPROP_ENUMERATE) fprintf(stderr, "enumerate ");
     if (attrs & JSPROP_READONLY) fprintf(stderr, "readonly ");
     if (attrs & JSPROP_PERMANENT) fprintf(stderr, "permanent ");
     if (attrs & JSPROP_SHARED) fprintf(stderr, "shared ");
-    if (shape.isMethod()) fprintf(stderr, "method ");
 
     if (shape.hasGetterValue())
         fprintf(stderr, "getterValue=%p ", (void *) shape.getterObject());
     else if (!shape.hasDefaultGetter())
         fprintf(stderr, "getterOp=%p ", JS_FUNC_TO_DATA_PTR(void *, shape.getterOp()));
 
     if (shape.hasSetterValue())
         fprintf(stderr, "setterValue=%p ", (void *) shape.setterObject());
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -504,29 +504,18 @@ struct JSObject : public js::ObjectImpl
     };
 
     bool setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag,
                  GenerateShape generateShape = GENERATE_NONE);
 
   public:
     inline bool nativeEmpty() const;
 
-    js::Shape *methodShapeChange(JSContext *cx, const js::Shape &shape);
     bool shadowingShapeChange(JSContext *cx, const js::Shape &shape);
 
-    /*
-     * Read barrier to clone a joined function object stored as a method.
-     * Defined in jsobjinlines.h, but not declared inline per standard style in
-     * order to avoid gcc warnings.
-     */
-    js::Shape *methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp);
-
-    /* Whether method shapes can be added to this object. */
-    inline bool canHaveMethodBarrier() const;
-
     /* Whether there may be indexed properties on this object. */
     inline bool isIndexed() const;
 
     inline uint32_t propertyCount() const;
 
     inline bool hasPropertyTable() const;
 
     inline size_t computedSizeOfThisSlotsElements() const;
@@ -568,18 +557,16 @@ struct JSObject : public js::ObjectImpl
      * Trigger the write barrier on a range of slots that will no longer be
      * reachable.
      */
     inline void prepareSlotRangeForOverwrite(size_t start, size_t end);
     inline void prepareElementRangeForOverwrite(size_t start, size_t end);
 
     void rollbackProperties(JSContext *cx, uint32_t slotSpan);
 
-    inline JSFunction *nativeGetMethod(const js::Shape *shape) const;
-
     inline void nativeSetSlot(unsigned slot, const js::Value &value);
     inline void nativeSetSlotWithType(JSContext *cx, const js::Shape *shape, const js::Value &value);
 
     inline const js::Value &getReservedSlot(unsigned index) const;
     inline js::HeapSlot &getReservedSlotRef(unsigned index);
     inline void initReservedSlot(unsigned index, const js::Value &v);
     inline void setReservedSlot(unsigned index, const js::Value &v);
 
@@ -935,16 +922,18 @@ struct JSObject : public js::ObjectImpl
                 uint32_t slot, unsigned attrs, unsigned flags, int shortid) {
         return putProperty(cx, js_CheckForStringIndex(ATOM_TO_JSID(name)), getter, setter, slot, attrs, flags, shortid);
     }
 
     /* Change the given property into a sibling with the same id in this scope. */
     js::Shape *changeProperty(JSContext *cx, js::Shape *shape, unsigned attrs, unsigned mask,
                               JSPropertyOp getter, JSStrictPropertyOp setter);
 
+    inline bool changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs);
+
     /* Remove the property named by id from this object. */
     bool removeProperty(JSContext *cx, jsid id);
 
     /* Clear the scope, making it empty. */
     void clear(JSContext *cx);
 
     inline JSBool lookupGeneric(JSContext *cx, jsid id, JSObject **objp, JSProperty **propp);
     inline JSBool lookupProperty(JSContext *cx, js::PropertyName *name, JSObject **objp, JSProperty **propp);
@@ -1346,44 +1335,31 @@ js_CheckForStringIndex(jsid id);
  * Find or create a property named by id in obj's scope, with the given getter
  * and setter, slot, attributes, and other members.
  */
 extern js::Shape *
 js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
                      JSPropertyOp getter, JSStrictPropertyOp setter, uint32_t slot,
                      unsigned attrs, unsigned flags, int shortid);
 
-/*
- * Change shape to have the given attrs, getter, and setter in scope, morphing
- * it into a potentially new js::Shape.  Return a pointer to the changed
- * or identical property.
- */
-extern js::Shape *
-js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
-                             js::Shape *shape, unsigned attrs, unsigned mask,
-                             JSPropertyOp getter, JSStrictPropertyOp setter);
-
 extern JSBool
 js_DefineOwnProperty(JSContext *cx, JSObject *obj, jsid id,
                      const js::Value &descriptor, JSBool *bp);
 
 namespace js {
 
 /*
  * Flags for the defineHow parameter of js_DefineNativeProperty.
  */
 const unsigned DNP_CACHE_RESULT = 1;   /* an interpreter call from JSOP_INITPROP */
 const unsigned DNP_DONT_PURGE   = 2;   /* suppress js_PurgeScopeChain */
-const unsigned DNP_SET_METHOD   = 4;   /* DefineNativeProperty,js_SetPropertyHelper
-                                       must pass the js::Shape::METHOD
-                                       flag on to JSObject::{add,put}Property */
-const unsigned DNP_UNQUALIFIED  = 8;   /* Unqualified property set.  Only used in
+const unsigned DNP_UNQUALIFIED  = 4;   /* Unqualified property set.  Only used in
                                        the defineHow argument of
                                        js_SetPropertyHelper. */
-const unsigned DNP_SKIP_TYPE = 0x10;   /* Don't update type information */
+const unsigned DNP_SKIP_TYPE    = 8;   /* Don't update type information */
 
 /*
  * Return successfully added or changed shape or NULL on error.
  */
 extern const Shape *
 DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, const Value &value,
                      PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
                      unsigned flags, int shortid, unsigned defineHow = 0);
@@ -1455,32 +1431,18 @@ FindProperty(JSContext *cx, PropertyName
 extern JSObject *
 FindIdentifierBase(JSContext *cx, JSObject *scopeChain, PropertyName *name);
 
 }
 
 extern JSObject *
 js_FindVariableScope(JSContext *cx, JSFunction **funp);
 
-/*
- * JSGET_CACHE_RESULT is the analogue of JSDNP_CACHE_RESULT for js_GetMethod.
- *
- * JSGET_METHOD_BARRIER (the default, hence 0 but provided for documentation)
- * enables a read barrier that preserves standard function object semantics (by
- * default we assume our caller won't leak a joined callee to script, where it
- * would create hazardous mutable object sharing as well as observable identity
- * according to == and ===.
- *
- * JSGET_NO_METHOD_BARRIER avoids the performance overhead of the method read
- * barrier, which is not needed when invoking a lambda that otherwise does not
- * leak its callee reference (via arguments.callee or its name).
- */
-const unsigned JSGET_METHOD_BARRIER    = 0; // get can leak joined function object
-const unsigned JSGET_NO_METHOD_BARRIER = 1; // call to joined function can't leak
-const unsigned JSGET_CACHE_RESULT      = 2; // from a caching interpreter opcode
+/* JSGET_CACHE_RESULT is the analogue of DNP_CACHE_RESULT for js_GetMethod. */
+const unsigned JSGET_CACHE_RESULT = 1; // from a caching interpreter opcode
 
 /*
  * NB: js_NativeGet and js_NativeSet are called with the scope containing shape
  * (pobj's scope for Get, obj's for Set) locked, and on successful return, that
  * scope is again locked.  But on failure, both functions return false with the
  * scope containing shape unlocked.
  */
 extern JSBool
@@ -1521,24 +1483,16 @@ namespace js {
 inline bool
 GetMethod(JSContext *cx, JSObject *obj, PropertyName *name, unsigned getHow, Value *vp)
 {
     return js_GetMethod(cx, obj, ATOM_TO_JSID(name), getHow, vp);
 }
 
 } /* namespace js */
 
-/*
- * Change attributes for the given native property. The caller must ensure
- * that obj is locked and this function always unlocks obj on return.
- */
-extern JSBool
-js_SetNativeAttributes(JSContext *cx, JSObject *obj, js::Shape *shape,
-                       unsigned attrs);
-
 namespace js {
 
 /*
  * If obj has an already-resolved data property for id, return true and
  * store the property value in *vp. This helper assumes the caller has already
  * called js_CheckForStringIndex.
  */
 extern bool
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -165,16 +165,22 @@ JSObject::setElementAttributes(JSContext
 }
 
 inline JSBool
 JSObject::setSpecialAttributes(JSContext *cx, js::SpecialId sid, unsigned *attrsp)
 {
     return setGenericAttributes(cx, SPECIALID_TO_JSID(sid), attrsp);
 }
 
+inline bool
+JSObject::changePropertyAttributes(JSContext *cx, js::Shape *shape, unsigned attrs)
+{
+    return !!changeProperty(cx, shape, attrs, 0, shape->getter(), shape->setter());
+}
+
 inline JSBool
 JSObject::getGeneric(JSContext *cx, JSObject *receiver, jsid id, js::Value *vp)
 {
     js::GenericIdOp op = getOps()->getGeneric;
     if (op) {
         if (!op(cx, this, receiver, id, vp))
             return false;
     } else {
@@ -260,60 +266,16 @@ JSObject::getParent() const
 }
 
 inline JSObject *
 JSObject::enclosingScope()
 {
     return isScope() ? &asScope().enclosingScope() : getParent();
 }
 
-/*
- * Property read barrier for deferred cloning of compiler-created function
- * objects optimized as typically non-escaping, ad-hoc methods in obj.
- */
-inline js::Shape *
-JSObject::methodReadBarrier(JSContext *cx, const js::Shape &shape, js::Value *vp)
-{
-    JS_ASSERT(nativeContains(cx, shape));
-    JS_ASSERT(shape.isMethod());
-    JS_ASSERT(shape.hasSlot());
-    JS_ASSERT(shape.hasDefaultSetter());
-    JS_ASSERT(!isGlobal());  /* i.e. we are not changing the global shape */
-
-    JSFunction *fun = vp->toObject().toFunction();
-    JS_ASSERT(!fun->isClonedMethod());
-    JS_ASSERT(fun->isNullClosure());
-
-    fun = js::CloneFunctionObject(cx, fun);
-    if (!fun)
-        return NULL;
-    fun->setMethodObj(*this);
-
-    /*
-     * Replace the method property with an ordinary data property. This is
-     * equivalent to this->setProperty(cx, shape.id, vp) except that any
-     * watchpoint on the property is not triggered.
-     */
-    uint32_t slot = shape.slot();
-    js::Shape *newshape = methodShapeChange(cx, shape);
-    if (!newshape)
-        return NULL;
-    JS_ASSERT(!newshape->isMethod());
-    JS_ASSERT(newshape->slot() == slot);
-    vp->setObject(*fun);
-    nativeSetSlot(slot, *vp);
-    return newshape;
-}
-
-inline bool
-JSObject::canHaveMethodBarrier() const
-{
-    return isObject() || isFunction() || isPrimitive() || isDate();
-}
-
 inline bool
 JSObject::isFixedSlot(size_t slot)
 {
     JS_ASSERT(!isDenseArray());
     return slot < numFixedSlots();
 }
 
 inline size_t
@@ -959,32 +921,16 @@ JSObject::isCallable()
 inline JSPrincipals *
 JSObject::principals(JSContext *cx)
 {
     if (JSObjectPrincipalsFinder find = cx->runtime->securityCallbacks->findObjectPrincipals)
         return find(this);
     return cx->compartment ? cx->compartment->principals : NULL;
 }
 
-inline JSFunction *
-JSObject::nativeGetMethod(const js::Shape *shape) const
-{
-    /*
-     * For method shapes, this object must have an uncloned function object in
-     * the shape's slot.
-     */
-    JS_ASSERT(shape->isMethod());
-#ifdef DEBUG
-    JSObject *obj = &nativeGetSlot(shape->slot()).toObject();
-    JS_ASSERT(obj->isFunction() && !obj->toFunction()->isClonedMethod());
-#endif
-
-    return static_cast<JSFunction *>(&nativeGetSlot(shape->slot()).toObject());
-}
-
 inline void
 JSObject::nativeSetSlot(unsigned slot, const js::Value &value)
 {
     JS_ASSERT(isNative());
     JS_ASSERT(slot < slotSpan());
     return setSlot(slot, value);
 }
 
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -307,17 +307,17 @@ static bool
 PreprocessValue(JSContext *cx, JSObject *holder, KeyType key, Value *vp, StringifyContext *scx)
 {
     JSString *keyStr = NULL;
 
     /* Step 2. */
     if (vp->isObject()) {
         Value toJSON;
         jsid id = ATOM_TO_JSID(cx->runtime->atomState.toJSONAtom);
-        if (!js_GetMethod(cx, &vp->toObject(), id, JSGET_NO_METHOD_BARRIER, &toJSON))
+        if (!js_GetMethod(cx, &vp->toObject(), id, 0, &toJSON))
             return false;
 
         if (js_IsCallable(toJSON)) {
             keyStr = KeyStringifier<KeyType>::toString(cx, key);
             if (!keyStr)
                 return false;
 
             InvokeArgsGuard args;
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -4510,17 +4510,16 @@ Decompile(SprintStack *ss, jsbytecode *p
                 PROPAGATE_CALLNESS();
                 lval = PopStr(ss, op, &lvalpc);
                 todo = ss->sprinter.getOffset();
                 SprintOpcode(ss, lval, lvalpc, pc, todo);
                 Sprint(&ss->sprinter, fmt, rval);
                 break;
 
               case JSOP_SETPROP:
-              case JSOP_SETMETHOD:
               {
                 LOAD_ATOM(0);
                 GET_QUOTE_AND_FMT("[%s] %s= ", ".%s %s= ", xval);
                 rval = PopStrDupe(ss, op, &rvalpc);
 
                 /*
                  * Force precedence below the numeric literal opcodes, so that
                  * 42..foo or 10000..toString(16), e.g., decompile with parens
@@ -4781,18 +4780,32 @@ Decompile(SprintStack *ss, jsbytecode *p
                     las.releaseEarly();
                     if (!rval)
                         return NULL;
                     todo = ss->sprinter.put(rval);
                     cx->free_((void *)rval);
                     break;
                 }
 #endif /* JS_HAS_GENERATOR_EXPRS */
-                /* FALL THROUGH */
-
+                else if (sn && SN_TYPE(sn) == SRC_CONTINUE) {
+                    /*
+                     * Local function definitions have a lambda;setlocal;pop
+                     * triple (annotated with SRC_CONTINUE) in the function
+                     * prologue and a nop (annotated with SRC_FUNCDEF) at the
+                     * actual position where the function definition should
+                     * syntactically appear.
+                     */
+                    LOCAL_ASSERT(pc[JSOP_LAMBDA_LENGTH] == JSOP_SETLOCAL);
+                    LOCAL_ASSERT(pc[JSOP_LAMBDA_LENGTH + JSOP_SETLOCAL_LENGTH] == JSOP_POP);
+                    len = JSOP_LAMBDA_LENGTH + JSOP_SETLOCAL_LENGTH + JSOP_POP_LENGTH;
+                    todo = -2;
+                    break;
+                }
+
+                /* Otherwise, this is a lambda expression. */
                 fun = jp->script->getFunction(GET_UINT32_INDEX(pc));
                 {
                     /*
                      * Always parenthesize expression closures. We can't force
                      * saveop to a low-precedence op to arrange for auto-magic
                      * parenthesization without confusing getter/setter code
                      * that checks for JSOP_LAMBDA.
                      */
@@ -5101,17 +5114,16 @@ Decompile(SprintStack *ss, jsbytecode *p
                     goto do_initprop;
                 }
                 maybeComma = isFirst ? "" : ", ";
                 todo = Sprint(&ss->sprinter, "%s%s", lval, maybeComma);
                 SprintOpcode(ss, rval, rvalpc, pc, todo);
                 break;
 
               case JSOP_INITPROP:
-              case JSOP_INITMETHOD:
                 LOAD_ATOM(0);
                 xval = QuoteString(&ss->sprinter, atom, jschar(IsIdentifier(atom) ? 0 : '\''));
                 if (!xval)
                     return NULL;
                 isFirst = IsInitializerOp(ss->opcodes[ss->top - 2]);
                 rval = PopStrDupe(ss, op, &rvalpc);
                 lval = PopStr(ss, op, &lvalpc);
                 /* fall through */
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -564,17 +564,17 @@ class OpcodeCounts
         ACCESS_COUNT
     };
 
     static bool accessOp(JSOp op) {
         /*
          * Access ops include all name, element and property reads, as well as
          * SETELEM and SETPROP (for ElementCounts/PropertyCounts alignment).
          */
-        if (op == JSOP_SETELEM || op == JSOP_SETPROP || op == JSOP_SETMETHOD)
+        if (op == JSOP_SETELEM || op == JSOP_SETPROP)
             return true;
         int format = js_CodeSpec[op].format;
         return !!(format & (JOF_NAME | JOF_GNAME | JOF_ELEM | JOF_PROP))
             && !(format & (JOF_SET | JOF_INCDEC));
     }
 
     enum ElementCounts {
         ELEM_ID_INT = ACCESS_COUNT,
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -359,25 +359,19 @@ OPDEF(JSOP_PICK,        133, "pick",    
 
 /*
  * Exception handling no-op, for more economical byte-coding than SRC_TRYFIN
  * srcnote-annotated JSOP_NOPs and to simply stack balance handling.
  */
 OPDEF(JSOP_TRY,         134,"try",        NULL,       1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_FINALLY,     135,"finally",    NULL,       1,  0,  2,  0,  JOF_BYTE)
 
-OPDEF(JSOP_UNUSED26,    136,"unused20",  NULL,        1,  0,  0,  0,  JOF_BYTE)
-OPDEF(JSOP_UNUSED27,    137,"unused21",  NULL,        1,  0,  0,  0,  JOF_BYTE)
-
-/*
- * Define a local function object as a local variable.
- * The local variable's slot number is the first immediate two-byte operand.
- * The function object's atom index is the second immediate operand.
- */
-OPDEF(JSOP_DEFLOCALFUN, 138,"deflocalfun",NULL,       7,  0,  0,  0,  JOF_SLOTOBJECT|JOF_DECLARING|JOF_TMPSLOT)
+OPDEF(JSOP_UNUSED26,    136,"unused26",  NULL,        1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_UNUSED27,    137,"unused27",  NULL,        1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_UNUSED28,    138,"unused28",  NULL,        1,  0,  0,  0,  JOF_BYTE)
 
 /* Extended jumps. */
 OPDEF(JSOP_UNUSED4,       139,"unused4",  NULL,       1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED5,       140,"unused5",  NULL,       1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED6,       141,"unused6",  NULL,       1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED7,       142,"unused7",  NULL,       1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED8,       143,"unused8",  NULL,       1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED9,       144,"unused9",  NULL,       1,  0,  0,  0,  JOF_BYTE)
@@ -533,25 +527,20 @@ OPDEF(JSOP_LENGTH,        217, "length",
 /*
  * Push a JSVAL_HOLE value onto the stack, representing an omitted property in
  * an array literal (e.g. property 0 in the array [, 1]).  This opcode is used
  * with the JSOP_NEWARRAY opcode.
  */
 OPDEF(JSOP_HOLE,          218, "hole",         NULL,  1,  0,  1,  0,  JOF_BYTE)
 
 OPDEF(JSOP_UNUSED17,      219,"unused17",      NULL,  1,  0,  0,  0,  JOF_BYTE)
-OPDEF(JSOP_UNUSED24,      220,"unused18",      NULL,  1,  0,  0,  0,  JOF_BYTE)
-OPDEF(JSOP_UNUSED25,      221,"unused19",      NULL,  1,  0,  0,  0,  JOF_BYTE)
-
-/*
- * Joined function object as method optimization support.
- */
-OPDEF(JSOP_SETMETHOD,     222,"setmethod",     NULL,  5,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
-OPDEF(JSOP_INITMETHOD,    223,"initmethod",    NULL,  5,  2,  1,  3,  JOF_ATOM|JOF_PROP|JOF_SET|JOF_DETECTING)
-
+OPDEF(JSOP_UNUSED24,      220,"unused24",      NULL,  1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_UNUSED25,      221,"unused25",      NULL,  1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_UNUSED29,      222,"unused29",      NULL,  1,  0,  0,  0,  JOF_BYTE)
+OPDEF(JSOP_UNUSED30,      223,"unused30",      NULL,  1,  0,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED16,      224,"unused16",      NULL,  1,  0,  0,  0,  JOF_BYTE)
 
 /* Pop the stack, convert to a jsid (int or string), and push back. */
 OPDEF(JSOP_TOID,          225, "toid",         NULL,  1,  1,  1,  0,  JOF_BYTE)
 
 /* Push the implicit 'this' value for calls to the associated name. */
 OPDEF(JSOP_IMPLICITTHIS,  226, "implicitthis", "",    5,  0,  1,  0,  JOF_ATOM)
 
--- a/js/src/jspropertytree.cpp
+++ b/js/src/jspropertytree.cpp
@@ -292,17 +292,16 @@ Shape::dump(JSContext *cx, FILE *fp) con
     }
 
     fprintf(fp, "flags %x ", flags);
     if (flags) {
         int first = 1;
         fputs("(", fp);
 #define DUMP_FLAG(name, display) if (flags & name) fputs(&(" " #display)[first], fp), first = 0
         DUMP_FLAG(HAS_SHORTID, has_shortid);
-        DUMP_FLAG(METHOD, method);
         DUMP_FLAG(IN_DICTIONARY, in_dictionary);
 #undef  DUMP_FLAG
         fputs(") ", fp);
     }
 
     fprintf(fp, "shortid %d\n", shortid());
 }
 
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -493,26 +493,19 @@ NormalizeGetterAndSetter(JSContext *cx, 
                          jsid id, unsigned attrs, unsigned flags,
                          PropertyOp &getter,
                          StrictPropertyOp &setter)
 {
     if (setter == JS_StrictPropertyStub) {
         JS_ASSERT(!(attrs & JSPROP_SETTER));
         setter = NULL;
     }
-    if (flags & Shape::METHOD) {
-        JS_ASSERT_IF(getter, getter == JS_PropertyStub);
-        JS_ASSERT(!setter);
-        JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
+    if (getter == JS_PropertyStub) {
+        JS_ASSERT(!(attrs & JSPROP_GETTER));
         getter = NULL;
-    } else {
-        if (getter == JS_PropertyStub) {
-            JS_ASSERT(!(attrs & JSPROP_GETTER));
-            getter = NULL;
-        }
     }
 
     return true;
 }
 
 Shape *
 JSObject::addProperty(JSContext *cx, jsid id,
                       PropertyOp getter, StrictPropertyOp setter,
@@ -803,19 +796,16 @@ JSObject::changeProperty(JSContext *cx, 
     JS_ASSERT(nativeContains(cx, *shape));
 
     attrs |= shape->attrs & mask;
 
     /* Allow only shared (slotless) => unshared (slotful) transition. */
     JS_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
               !(attrs & JSPROP_SHARED));
 
-    /* Don't allow method properties to be changed to have a getter or setter. */
-    JS_ASSERT_IF(shape->isMethod(), !getter && !setter);
-
     types::MarkTypePropertyConfigured(cx, this, shape->propid());
     if (attrs & (JSPROP_GETTER | JSPROP_SETTER))
         types::AddTypePropertyId(cx, this, shape->propid(), types::Type::UnknownType());
 
     if (getter == JS_PropertyStub)
         getter = NULL;
     if (setter == JS_StrictPropertyStub)
         setter = NULL;
@@ -1036,54 +1026,16 @@ JSObject::replaceWithNewEquivalentShape(
     if (newShape == lastProperty())
         oldShape->handoffTableTo(newShape);
 
     if (spp)
         SHAPE_STORE_PRESERVING_COLLISION(spp, newShape);
     return newShape;
 }
 
-Shape *
-JSObject::methodShapeChange(JSContext *cx, const Shape &shape)
-{
-    JS_ASSERT(shape.isMethod());
-
-    if (!inDictionaryMode() && !toDictionaryMode(cx))
-        return NULL;
-
-    Shape *spare = js_NewGCShape(cx);
-    if (!spare)
-        return NULL;
-    new (spare) Shape(shape.base()->unowned(), 0);
-
-#ifdef DEBUG
-    JS_ASSERT(canHaveMethodBarrier());
-    JS_ASSERT(!shape.setter());
-    JS_ASSERT(!shape.hasShortID());
-#endif
-
-    /*
-     * Clear Shape::METHOD from flags as we are despecializing from a
-     * method memoized in the property tree to a plain old function-valued
-     * property.
-     */
-    Shape *result =
-        putProperty(cx, shape.propid(), NULL, NULL, shape.slot(),
-                    shape.attrs,
-                    shape.getFlags() & ~Shape::METHOD,
-                    0);
-    if (!result)
-        return NULL;
-
-    if (result != lastProperty())
-        JS_ALWAYS_TRUE(generateOwnShape(cx, spare));
-
-    return result;
-}
-
 bool
 JSObject::shadowingShapeChange(JSContext *cx, const Shape &shape)
 {
     return generateOwnShape(cx);
 }
 
 bool
 JSObject::clearParent(JSContext *cx)
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -644,53 +644,25 @@ struct Shape : public js::gc::Cell
      * assigned yet. After construction, hasSlot() implies !hasMissingSlot().
      */
     bool hasMissingSlot() const { return maybeSlot() == SHAPE_INVALID_SLOT; }
 
   public:
     /* Public bits stored in shape->flags. */
     enum {
         HAS_SHORTID     = 0x40,
-        METHOD          = 0x80,
-        PUBLIC_FLAGS    = HAS_SHORTID | METHOD
+        PUBLIC_FLAGS    = HAS_SHORTID
     };
 
     bool inDictionary() const   { return (flags & IN_DICTIONARY) != 0; }
     unsigned getFlags() const  { return flags & PUBLIC_FLAGS; }
     bool hasShortID() const { return (flags & HAS_SHORTID) != 0; }
 
-    /*
-     * A shape has a method barrier when some compiler-created "null closure"
-     * function objects (functions that do not use lexical bindings above their
-     * scope, only free variable names) that have a correct JSSLOT_PARENT value
-     * thanks to the COMPILE_N_GO optimization are stored in objects without
-     * cloning.
-     *
-     * The de-facto standard JS language requires each evaluation of such a
-     * closure to result in a unique (according to === and observable effects)
-     * function object. When storing a function to a property, we use method
-     * shapes to speculate that these effects will never be observed: the
-     * property will only be used in ca