Merge services-central with mozilla-central
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Wed, 12 Oct 2011 12:52:55 -0700
changeset 78608 fee22c85ed19173fae01ee3a6371d695ef355edb
parent 78607 72ceb8048b70d9644200e80a568bac6b6afa537c (current diff)
parent 78602 1354c018705372ac81c1f9a014a672c32331bec7 (diff)
child 78609 46a6d0fd13d591805cd4b857450985fbd3895198
child 79063 f15a17ef38dd73dd123a9279b9e0533124ee2c72
push id21317
push userpweitershausen@mozilla.com
push dateWed, 12 Oct 2011 19:53:22 +0000
treeherdermozilla-central@fee22c85ed19 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge services-central with mozilla-central
embedding/components/windowwatcher/src/nsWWJSUtils.cpp
embedding/components/windowwatcher/src/nsWWJSUtils.h
js/src/jsarena.cpp
js/src/jsbit.h
js/src/jshashtable.h
js/src/jstl.h
js/src/jsvector.h
js/src/mfbt/InlineMap.h
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -311,16 +311,20 @@ NotificationController::WillRefresh(mozi
   // Process only currently queued events.
   nsTArray<nsRefPtr<AccEvent> > events;
   events.SwapElements(mEvents);
 
   PRUint32 eventCount = events.Length();
   for (PRUint32 idx = 0; idx < eventCount; idx++) {
     AccEvent* accEvent = events[idx];
     if (accEvent->mEventRule != AccEvent::eDoNotEmit) {
+      nsAccessible* target = accEvent->GetAccessible();
+      if (!target || target->IsDefunct())
+        continue;
+
       // Dispatch the focus event if target is still focused.
       if (accEvent->mEventType == nsIAccessibleEvent::EVENT_FOCUS) {
         FocusMgr()->ProcessFocusEvent(accEvent);
         continue;
       }
 
       mDocument->ProcessPendingEvent(accEvent);
 
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -1725,52 +1725,45 @@ nsDocAccessible::FireDelayedAccessibleEv
     mNotificationController->QueueEvent(aEvent);
 
   return NS_OK;
 }
 
 void
 nsDocAccessible::ProcessPendingEvent(AccEvent* aEvent)
 {
-  nsAccessible* accessible = aEvent->GetAccessible();
-  if (!accessible)
-    return;
-
   PRUint32 eventType = aEvent->GetEventType();
   if (eventType == nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED) {
-    nsCOMPtr<nsIAccessibleText> accessibleText = do_QueryObject(accessible);
+    nsHyperTextAccessible* hyperText = aEvent->GetAccessible()->AsHyperText();
     PRInt32 caretOffset;
-    if (accessibleText &&
-        NS_SUCCEEDED(accessibleText->GetCaretOffset(&caretOffset))) {
+    if (hyperText &&
+        NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) {
 #ifdef DEBUG_A11Y
       PRUnichar chAtOffset;
-      accessibleText->GetCharacterAtOffset(caretOffset, &chAtOffset);
+      hyperText->GetCharacterAtOffset(caretOffset, &chAtOffset);
       printf("\nCaret moved to %d with char %c", caretOffset, chAtOffset);
 #endif
       nsRefPtr<AccEvent> caretMoveEvent =
-          new AccCaretMoveEvent(accessible, caretOffset);
-      if (!caretMoveEvent)
-        return;
-
+        new AccCaretMoveEvent(hyperText, caretOffset);
       nsEventShell::FireEvent(caretMoveEvent);
 
       PRInt32 selectionCount;
-      accessibleText->GetSelectionCount(&selectionCount);
+      hyperText->GetSelectionCount(&selectionCount);
       if (selectionCount) {  // There's a selection so fire selection change as well
         nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED,
-                                accessible);
+                                hyperText);
       }
     }
   }
   else {
     nsEventShell::FireEvent(aEvent);
 
     // Post event processing
     if (eventType == nsIAccessibleEvent::EVENT_HIDE)
-      ShutdownChildrenInSubtree(accessible);
+      ShutdownChildrenInSubtree(aEvent->GetAccessible());
   }
 }
 
 void
 nsDocAccessible::ProcessContentInserted(nsAccessible* aContainer,
                                         const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent)
 {
   // Process the notification if the container accessible is still in tree.
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -738,16 +738,20 @@ void nsAccessNodeWrap::DoATSpecificProce
   TurnOffNewTabSwitchingForJawsAndWE();
 }
 
 nsRefPtrHashtable<nsVoidPtrHashKey, nsDocAccessible> nsAccessNodeWrap::sHWNDCache;
 
 LRESULT CALLBACK
 nsAccessNodeWrap::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
+  // Note, this window's message handling should not invoke any call that
+  // may result in a cross-process ipc call. Doing so may violate RPC
+  // message semantics.
+
   switch (msg) {
     case WM_GETOBJECT:
     {
       if (lParam == OBJID_CLIENT) {
         nsDocAccessible* document = sHWNDCache.GetWeak(static_cast<void*>(hWnd));
         if (document) {
           IAccessible* msaaAccessible = NULL;
           document->GetNativeInterface((void**)&msaaAccessible); // does an addref
--- a/accessible/src/msaa/nsWinUtils.cpp
+++ b/accessible/src/msaa/nsWinUtils.cpp
@@ -41,16 +41,20 @@
 #include "nsWinUtils.h"
 
 #include "nsIWinAccessNode.h"
 #include "nsRootAccessible.h"
 
 #include "nsArrayUtils.h"
 #include "nsIDocShellTreeItem.h"
 
+// Window property used by ipc related code in identifying accessible
+// tab windows.
+const PRUnichar* kPropNameTabContent = L"AccessibleTabWindow";
+
 HRESULT
 nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
                               long *aIA2ArrayLen)
 {
   *aIA2Array = NULL;
   *aIA2ArrayLen = 0;
 
   if (!aGeckoArray)
@@ -144,24 +148,29 @@ nsWinUtils::RegisterNativeWindow(LPCWSTR
   ::RegisterClassW(&wc);
 }
 
 HWND
 nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd,
                                int aX, int aY, int aWidth, int aHeight,
                                bool aIsActive)
 {
-  return ::CreateWindowExW(WS_EX_TRANSPARENT, aWindowClass,
-                           L"NetscapeDispatchWnd",
-                           WS_CHILD | (aIsActive ? WS_VISIBLE : 0),
-                           aX, aY, aWidth, aHeight,
-                           aParentWnd,
-                           NULL,
-                           GetModuleHandle(NULL),
-                           NULL);
+  HWND hwnd = ::CreateWindowExW(WS_EX_TRANSPARENT, aWindowClass,
+                                L"NetscapeDispatchWnd",
+                                WS_CHILD | (aIsActive ? WS_VISIBLE : 0),
+                                aX, aY, aWidth, aHeight,
+                                aParentWnd,
+                                NULL,
+                                GetModuleHandle(NULL),
+                                NULL);
+  if (hwnd) {
+    // Mark this window so that ipc related code can identify it.
+    ::SetPropW(hwnd, kPropNameTabContent, (HANDLE)1);
+  }
+  return hwnd;
 }
 
 void
 nsWinUtils::ShowNativeWindow(HWND aWnd)
 {
   ::ShowWindow(aWnd, SW_SHOW);
 }
 
--- a/accessible/tests/mochitest/treeview.js
+++ b/accessible/tests/mochitest/treeview.js
@@ -35,18 +35,18 @@ nsTreeView.prototype =
   },
   setTree: function setTree(aTree)
   {
     this.mTree = aTree;
   },
   getCellText: function getCellText(aRow, aCol)
   {
     var data = this.getDataForIndex(aRow);
-    if (aCol in data.colsText)
-      return data.colsText[aCol];
+    if (aCol.id in data.colsText)
+      return data.colsText[aCol.id];
 
     return data.text + aCol.id;
   },
   getCellValue: function getCellValue(aRow, aCol)
   {
     var data = this.getDataForIndex(aRow);
     return data.value;
   },
@@ -115,17 +115,17 @@ nsTreeView.prototype =
   isEditable: function isEditable(aRow, aCol)
   {
     return true;
   },
   isSelectable: function isSelectable(aRow, aCol) {},
   setCellText: function setCellText(aRow, aCol, aValue)
   {
     var data = this.getDataForIndex(aRow);
-    data.colsText[aCol] = aValue;
+    data.colsText[aCol.id] = aValue;
   },
   setCellValue: function setCellValue(aRow, aCol, aValue)
   {
     var data = this.getDataForIndex(aRow);
     data.value = aValue;
 
     this.mTree.invalidateCell(aRow, aCol);
   },
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -165,19 +165,18 @@ pref("app.update.silent", false);
 pref("app.update.url", "https://aus3.mozilla.org/update/3/%PRODUCT%/%VERSION%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/update.xml");
 // app.update.url.manual is in branding section
 // app.update.url.details is in branding section
 
 // User-settable override to app.update.url for testing purposes.
 //pref("app.update.url.override", "");
 
 // app.update.interval is in branding section
+// app.update.promptWaitTime is in branding section
 
-// Give the user x seconds to react before showing the big UI. default=12 hours
-pref("app.update.promptWaitTime", 43200);
 // Show the Update Checking/Ready UI when the user was idle for x seconds
 pref("app.update.idletime", 60);
 
 // Whether or not we show a dialog box informing the user that the update was
 // successfully applied. This is off in Firefox by default since we show a 
 // upgrade start page instead! Other apps may wish to show this UI, and supply
 // a whatsNewURL field in their brand.properties that contains a link to a page
 // which tells users what's new in this new update.
--- a/browser/base/content/highlighter.css
+++ b/browser/base/content/highlighter.css
@@ -37,16 +37,19 @@
 }
 
 /*
  * Node Infobar
  */
 
 #highlighter-nodeinfobar-container {
   position: absolute;
+}
+
+#highlighter-nodeinfobar-container:not([locked]) {
   -moz-transition-property: top, left;
   -moz-transition-duration: 0.1s;
   -moz-transition-timing-function: linear;
 }
 
 #highlighter-nodeinfobar {
   display: block;
   white-space: nowrap;
--- a/browser/branding/aurora/pref/firefox-branding.js
+++ b/browser/branding/aurora/pref/firefox-branding.js
@@ -2,16 +2,18 @@
 pref("startup.homepage_override_url","");
 pref("startup.homepage_welcome_url","");
 // The time interval between checks for a new version (in seconds)
 // nightly=8 hours, official=24 hours
 pref("app.update.interval", 28800);
 // The time interval between the downloading of mar file chunks in the
 // background (in seconds)
 pref("app.update.download.backgroundInterval", 60);
+// Give the user x seconds to react before showing the big UI. default=24 hours
+pref("app.update.promptWaitTime", 86400);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
 pref("app.update.url.manual", "http://www.mozilla.com/firefox/channel/");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard. 
 pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
 
 // Release notes and vendor URLs
--- a/browser/branding/nightly/pref/firefox-branding.js
+++ b/browser/branding/nightly/pref/firefox-branding.js
@@ -1,15 +1,17 @@
 pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
 pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
 // The time interval between checks for a new version (in seconds)
 pref("app.update.interval", 7200); // 2 hours
 // The time interval between the downloading of mar file chunks in the
 // background (in seconds)
 pref("app.update.download.backgroundInterval", 60);
+// Give the user x seconds to react before showing the big UI. default=12 hours
+pref("app.update.promptWaitTime", 43200);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
 pref("app.update.url.manual", "http://nightly.mozilla.org/");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard. 
 pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
 
 // Release notes and vendor URLs
--- a/browser/branding/official/pref/firefox-branding.js
+++ b/browser/branding/official/pref/firefox-branding.js
@@ -2,16 +2,18 @@
 pref("startup.homepage_override_url","");
 pref("startup.homepage_welcome_url","http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/firstrun/");
 // Interval: Time between checks for a new version (in seconds)
 // nightly=6 hours, official=24 hours
 pref("app.update.interval", 86400);
 // The time interval between the downloading of mar file chunks in the
 // background (in seconds)
 pref("app.update.download.backgroundInterval", 600);
+// Give the user x seconds to react before showing the big UI. default=24 hours
+pref("app.update.promptWaitTime", 86400);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
 pref("app.update.url.manual", "http://www.firefox.com");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard. 
 pref("app.update.url.details", "http://www.mozilla.com/%LOCALE%/%APP%/releases/");
 
 // Release notes and vendor URLs
--- a/browser/branding/unofficial/pref/firefox-branding.js
+++ b/browser/branding/unofficial/pref/firefox-branding.js
@@ -1,15 +1,17 @@
 pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
 pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
 // The time interval between checks for a new version (in seconds)
 pref("app.update.interval", 86400); // 24 hours
 // The time interval between the downloading of mar file chunks in the
 // background (in seconds)
 pref("app.update.download.backgroundInterval", 60);
+// Give the user x seconds to react before showing the big UI. default=24 hours
+pref("app.update.promptWaitTime", 86400);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
 pref("app.update.url.manual", "http://www.mozilla.org/products/%APP%/");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard. 
 pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
 
 // Release notes and vendor URLs
--- a/browser/config/mozconfigs/linux32/debug
+++ b/browser/config/mozconfigs/linux32/debug
@@ -1,11 +1,10 @@
 ac_add_options --enable-application=browser
 
-ac_add_options --disable-optimize
 ac_add_options --enable-debug
 ac_add_options --enable-libxul
 
 ac_add_options --enable-tests
 ac_add_options --enable-trace-malloc
 
 CC=/tools/gcc-4.5/bin/gcc
 CXX=/tools/gcc-4.5/bin/g++
--- a/browser/config/mozconfigs/linux64/debug
+++ b/browser/config/mozconfigs/linux64/debug
@@ -1,11 +1,10 @@
 ac_add_options --enable-application=browser
 
-ac_add_options --disable-optimize
 ac_add_options --enable-debug
 
 ac_add_options --enable-tests
 ac_add_options --enable-trace-malloc
 
 CC=/tools/gcc-4.5/bin/gcc
 CXX=/tools/gcc-4.5/bin/g++
 # Avoid dependency on libstdc++ 4.5
--- a/browser/config/mozconfigs/macosx32/debug
+++ b/browser/config/mozconfigs/macosx32/debug
@@ -1,14 +1,13 @@
 # Don't use the standard mozconfig. We don't want universal for a debug build. 
 #. $topsrcdir/build/macosx/universal/mozconfig
 
 ac_add_options --with-macos-sdk=/Developer/SDKs/MacOSX10.5.sdk
 
-ac_add_options --disable-optimize
 ac_add_options --enable-debug
 ac_add_options --enable-libxul
 
 ac_add_options --enable-application=browser
 ac_add_options --enable-tests
 ac_add_options --enable-trace-malloc
 
 # For NSS symbols
--- a/browser/config/mozconfigs/macosx64/debug
+++ b/browser/config/mozconfigs/macosx64/debug
@@ -1,9 +1,8 @@
-ac_add_options --disable-optimize
 ac_add_options --enable-debug
 ac_add_options --enable-libxul
 
 ac_add_options --enable-application=browser
 ac_add_options --enable-tests
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-accessibility
 
--- a/browser/config/mozconfigs/win32/debug
+++ b/browser/config/mozconfigs/win32/debug
@@ -1,11 +1,10 @@
 ac_add_options --enable-application=browser
 ac_add_options --enable-jemalloc
-ac_add_options --disable-optimize
 ac_add_options --enable-debug
 ac_add_options --enable-libxul
 ac_add_options --enable-trace-malloc
 ac_add_options --enable-tests
 
 # For NSS symbols
 export MOZ_DEBUG_SYMBOLS=1
 
--- a/browser/config/mozconfigs/win64/debug
+++ b/browser/config/mozconfigs/win64/debug
@@ -1,14 +1,13 @@
 ac_add_options --target=x86_64-pc-mingw32
 ac_add_options --host=x86_64-pc-mingw32
 
 ac_add_options --enable-application=browser
 ac_add_options --enable-jemalloc
-ac_add_options --disable-optimize
 ac_add_options --enable-debug
 ac_add_options --enable-libxul
 ac_add_options --enable-trace-malloc
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 mk_add_options MOZ_MAKE_FLAGS=-j1
--- a/browser/devtools/highlighter/TreePanel.jsm
+++ b/browser/devtools/highlighter/TreePanel.jsm
@@ -1,10 +1,10 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -42,17 +42,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 const Cu = Components.utils;
 
 Cu.import("resource:///modules/domplate.jsm");
 Cu.import("resource:///modules/InsideOutBox.jsm");
 Cu.import("resource:///modules/Services.jsm");
 
-var EXPORTED_SYMBOLS = ["TreePanel"];
+var EXPORTED_SYMBOLS = ["TreePanel", "DOMHelpers"];
 
 const INSPECTOR_URI = "chrome://browser/content/inspector.html";
 
 /**
  * TreePanel
  * A container for the Inspector's HTML Tree Panel widget constructor function.
  * @param aContext nsIDOMWindow (xulwindow)
  * @param aIUI global InspectorUI object
@@ -91,16 +91,18 @@ TreePanel.prototype = {
   _init: function TP__init(aContext, aIUI)
   {
     this.IUI = aIUI;
     this.window = aContext;
     this.document = this.window.document;
 
     domplateUtils.setDOM(this.window);
 
+    this.DOMHelpers = new DOMHelpers(this.window);
+
     let isOpen = this.isOpen.bind(this);
 
     this.registrationObject = {
       id: this.id,
       label: this.IUI.strings.GetStringFromName("htmlPanel.label"),
       tooltiptext: this.IUI.strings.GetStringFromName("htmlPanel.tooltiptext"),
       accesskey: this.IUI.strings.GetStringFromName("htmlPanel.accesskey"),
       context: this,
@@ -134,16 +136,17 @@ TreePanel.prototype = {
     this.treePanelDiv = this.treeBrowserDocument.createElement("div");
     this.treeBrowserDocument.body.appendChild(this.treePanelDiv);
     this.treePanelDiv.ownerPanel = this;
     this.ioBox = new InsideOutBox(this, this.treePanelDiv);
     this.ioBox.createObjectBox(this.IUI.win.document.documentElement);
     this.treeLoaded = true;
     this.treeIFrame.addEventListener("click", this.onTreeClick.bind(this), false);
     this.treeIFrame.addEventListener("dblclick", this.onTreeDblClick.bind(this), false);
+    this.treeIFrame.addEventListener("keypress", this.IUI, false);
     delete this.initializingTreePanel;
     Services.obs.notifyObservers(null,
       this.IUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, null);
     if (this.IUI.selection)
       this.select(this.IUI.selection, true);
   },
 
   /**
@@ -310,103 +313,33 @@ TreePanel.prototype = {
   {
     let tag = domplateUtils.getNodeTag(object);
     if (tag)
       return tag.replace({object: object}, this.treeBrowserDocument);
   },
 
   getParentObject: function TP_getParentObject(node)
   {
-    let parentNode = node ? node.parentNode : null;
-
-    if (!parentNode) {
-      // Documents have no parentNode; Attr, Document, DocumentFragment, Entity,
-      // and Notation. top level windows have no parentNode
-      if (node && node == this.window.Node.DOCUMENT_NODE) {
-        // document type
-        if (node.defaultView) {
-          let embeddingFrame = node.defaultView.frameElement;
-          if (embeddingFrame)
-            return embeddingFrame.parentNode;
-        }
-      }
-      // a Document object without a parentNode or window
-      return null;  // top level has no parent
-    }
-
-    if (parentNode.nodeType == this.window.Node.DOCUMENT_NODE) {
-      if (parentNode.defaultView) {
-        return parentNode.defaultView.frameElement;
-      }
-      // parent is document element, but no window at defaultView.
-      return null;
-    }
-
-    if (!parentNode.localName)
-      return null;
-
-    return parentNode;
+    return this.DOMHelpers.getParentObject(node);
   },
 
   getChildObject: function TP_getChildObject(node, index, previousSibling)
   {
-    if (!node)
-      return null;
-
-    if (node.contentDocument) {
-      // then the node is a frame
-      if (index == 0) {
-        return node.contentDocument.documentElement;  // the node's HTMLElement
-      }
-      return null;
-    }
-
-    if (node instanceof this.window.GetSVGDocument) {
-      let svgDocument = node.getSVGDocument();
-      if (svgDocument) {
-        // then the node is a frame
-        if (index == 0) {
-          return svgDocument.documentElement;  // the node's SVGElement
-        }
-        return null;
-      }
-    }
-
-    let child = null;
-    if (previousSibling)  // then we are walking
-      child = this.getNextSibling(previousSibling);
-    else
-      child = this.getFirstChild(node);
-
-    if (this.showTextNodesWithWhitespace)
-      return child;
-
-    for (; child; child = this.getNextSibling(child)) {
-      if (!domplateUtils.isWhitespaceText(child))
-        return child;
-    }
-
-    return null;  // we have no children worth showing.
+    return this.DOMHelpers.getChildObject(node, index, previousSibling,
+                                        this.showTextNodesWithWhitespace);
   },
 
   getFirstChild: function TP_getFirstChild(node)
   {
-    this.treeWalker = node.ownerDocument.createTreeWalker(node,
-      this.window.NodeFilter.SHOW_ALL, null, false);
-    return this.treeWalker.firstChild();
+    return this.DOMHelpers.getFirstChild(node);
   },
 
   getNextSibling: function TP_getNextSibling(node)
   {
-    let next = this.treeWalker.nextSibling();
-
-    if (!next)
-      delete this.treeWalker;
-
-    return next;
+    return this.DOMHelpers.getNextSibling(node);
   },
 
   /////////////////////////////////////////////////////////////////////
   // Event Handling
 
   /**
    * Handle click events in the html tree panel.
    * @param aEvent
@@ -742,27 +675,32 @@ TreePanel.prototype = {
   {
     if (this.isOpen()) {
       this.close();
     }
 
     domplateUtils.setDOM(null);
 
     delete this.resizer;
-    delete this.treeWalker;
+
+    if (this.DOMHelpers) {
+      this.DOMHelpers.destroy();
+      delete this.DOMHelpers;
+    }
 
     if (this.treePanelDiv) {
       this.treePanelDiv.ownerPanel = null;
       let parent = this.treePanelDiv.parentNode;
       parent.removeChild(this.treePanelDiv);
       delete this.treePanelDiv;
       delete this.treeBrowserDocument;
     }
 
     if (this.treeIFrame) {
+      this.treeIFrame.removeEventListener("keypress", this.IUI, false);
       this.treeIFrame.removeEventListener("dblclick", this.onTreeDblClick, false);
       this.treeIFrame.removeEventListener("click", this.onTreeClick, false);
       let parent = this.treeIFrame.parentNode;
       parent.removeChild(this.treeIFrame);
       delete this.treeIFrame;
     }
 
     if (this.ioBox) {
@@ -772,8 +710,127 @@ TreePanel.prototype = {
 
     if (!this.openInDock) {
       this.container.removeEventListener("popuphiding", this._boundClose, false);
       delete this._boundClose;
     }
   }
 };
 
+
+/**
+ * DOMHelpers
+ * Makes DOM traversal easier. Goes through iframes.
+ *
+ * @constructor
+ * @param nsIDOMWindow aWindow
+ *        The content window, owning the document to traverse.
+ */
+function DOMHelpers(aWindow) {
+  this.window = aWindow;
+};
+
+DOMHelpers.prototype = {
+  getParentObject: function Helpers_getParentObject(node)
+  {
+    let parentNode = node ? node.parentNode : null;
+
+    if (!parentNode) {
+      // Documents have no parentNode; Attr, Document, DocumentFragment, Entity,
+      // and Notation. top level windows have no parentNode
+      if (node && node == this.window.Node.DOCUMENT_NODE) {
+        // document type
+        if (node.defaultView) {
+          let embeddingFrame = node.defaultView.frameElement;
+          if (embeddingFrame)
+            return embeddingFrame.parentNode;
+        }
+      }
+      // a Document object without a parentNode or window
+      return null;  // top level has no parent
+    }
+
+    if (parentNode.nodeType == this.window.Node.DOCUMENT_NODE) {
+      if (parentNode.defaultView) {
+        return parentNode.defaultView.frameElement;
+      }
+      // parent is document element, but no window at defaultView.
+      return null;
+    }
+
+    if (!parentNode.localName)
+      return null;
+
+    return parentNode;
+  },
+
+  getChildObject: function Helpers_getChildObject(node, index, previousSibling,
+                                                showTextNodesWithWhitespace)
+  {
+    if (!node)
+      return null;
+
+    if (node.contentDocument) {
+      // then the node is a frame
+      if (index == 0) {
+        return node.contentDocument.documentElement;  // the node's HTMLElement
+      }
+      return null;
+    }
+
+    if (node instanceof this.window.GetSVGDocument) {
+      let svgDocument = node.getSVGDocument();
+      if (svgDocument) {
+        // then the node is a frame
+        if (index == 0) {
+          return svgDocument.documentElement;  // the node's SVGElement
+        }
+        return null;
+      }
+    }
+
+    let child = null;
+    if (previousSibling)  // then we are walking
+      child = this.getNextSibling(previousSibling);
+    else
+      child = this.getFirstChild(node);
+
+    if (showTextNodesWithWhitespace)
+      return child;
+
+    for (; child; child = this.getNextSibling(child)) {
+      if (!this.isWhitespaceText(child))
+        return child;
+    }
+
+    return null;  // we have no children worth showing.
+  },
+
+  getFirstChild: function Helpers_getFirstChild(node)
+  {
+    let SHOW_ALL = Components.interfaces.nsIDOMNodeFilter.SHOW_ALL;
+    this.treeWalker = node.ownerDocument.createTreeWalker(node,
+      SHOW_ALL, null, false);
+    return this.treeWalker.firstChild();
+  },
+
+  getNextSibling: function Helpers_getNextSibling(node)
+  {
+    let next = this.treeWalker.nextSibling();
+
+    if (!next)
+      delete this.treeWalker;
+
+    return next;
+  },
+
+  isWhitespaceText: function Helpers_isWhitespaceText(node)
+  {
+    return node.nodeType == this.window.Node.TEXT_NODE &&
+                            !/[^\s]/.exec(node.nodeValue);
+  },
+
+  destroy: function Helpers_destroy()
+  {
+    delete this.window;
+    delete this.treeWalker;
+  }
+};
--- a/browser/devtools/highlighter/inspector.jsm
+++ b/browser/devtools/highlighter/inspector.jsm
@@ -882,18 +882,17 @@ InspectorUI.prototype = {
   },
 
   /**
    * Register and initialize any included tools.
    */
   initTools: function IUI_initTools()
   {
     // Style inspector
-    // XXX bug 689164, remove /false &&/ from below when bug 689160 fixed.
-    if (false && Services.prefs.getBoolPref("devtools.styleinspector.enabled") &&
+    if (Services.prefs.getBoolPref("devtools.styleinspector.enabled") &&
         !this.toolRegistered("styleinspector")) {
       let stylePanel = StyleInspector.createPanel(true);
       this.registerTool({
         id: "styleinspector",
         label: StyleInspector.l10n("style.highlighter.button.label"),
         tooltiptext: StyleInspector.l10n("style.highlighter.button.tooltip"),
         accesskey: StyleInspector.l10n("style.highlighter.accesskey"),
         context: stylePanel,
@@ -985,23 +984,27 @@ InspectorUI.prototype = {
       this.store.setValue(this.winID, "isDirty", this.isDirty);
     }
 
     if (this.store.isEmpty()) {
       this.tabbrowser.tabContainer.removeEventListener("TabSelect", this, false);
     }
 
     this.stopInspecting();
+    this.browser.removeEventListener("keypress", this, true);
 
     this.saveToolState(this.winID);
     this.toolsDo(function IUI_toolsHide(aTool) {
       this.unregisterTool(aTool);
     }.bind(this));
 
     if (this.highlighter) {
+      this.highlighter.highlighterContainer.removeEventListener("keypress",
+                                                                this,
+                                                                true);
       this.highlighter.destroy();
       this.highlighter = null;
     }
 
     this.inspectMenuitem.setAttribute("checked", false);
     this.browser = this.win = null; // null out references to browser and window
     this.winID = null;
     this.selection = null;
@@ -1022,44 +1025,56 @@ InspectorUI.prototype = {
   startInspecting: function IUI_startInspecting()
   {
     // if currently editing an attribute value, starting
     // "live inspection" mode closes the editor
     if (this.treePanel && this.treePanel.editingContext)
       this.treePanel.closeEditor();
 
     this.inspectToolbutton.checked = true;
-    this.attachPageListeners();
+    // Attach event listeners to content window and child windows to enable
+    // highlighting and click to stop inspection.
+    this.browser.addEventListener("keypress", this, true);
+    this.highlighter.highlighterContainer.addEventListener("keypress", this, true);
+    this.highlighter.attachInspectListeners();
+
     this.inspecting = true;
     this.toolsDim(true);
     this.highlighter.veilContainer.removeAttribute("locked");
+    this.highlighter.nodeInfo.container.removeAttribute("locked");
   },
 
   /**
    * Stop inspecting webpage, detach page listeners, disable highlighter
    * event listeners.
    * @param aPreventScroll
    *        Prevent scroll in the HTML tree?
    */
   stopInspecting: function IUI_stopInspecting(aPreventScroll)
   {
     if (!this.inspecting) {
       return;
     }
 
     this.inspectToolbutton.checked = false;
-    this.detachPageListeners();
+    // Detach event listeners from content window and child windows to disable
+    // highlighting. We still want to be notified if the user presses "ESCAPE"
+    // to unlock the node, so we don't remove the "keypress" event until
+    // the highlighter is removed.
+    this.highlighter.detachInspectListeners();
+
     this.inspecting = false;
     this.toolsDim(false);
     if (this.highlighter.node) {
       this.select(this.highlighter.node, true, true, !aPreventScroll);
     } else {
       this.select(null, true, true);
     }
     this.highlighter.veilContainer.setAttribute("locked", true);
+    this.highlighter.nodeInfo.container.setAttribute("locked", true);
   },
 
   /**
    * Select an object in the tree view.
    * @param aNode
    *        node to inspect
    * @param forceUpdate
    *        force an update?
@@ -1160,21 +1175,19 @@ InspectorUI.prototype = {
           this.tabbrowser.tabContainer.removeEventListener("TabSelect", this,
                                                          false);
         }
         break;
       case "keypress":
         switch (event.keyCode) {
           case this.chromeWin.KeyEvent.DOM_VK_RETURN:
           case this.chromeWin.KeyEvent.DOM_VK_ESCAPE:
-            if (this.inspecting) {
-              this.stopInspecting();
-              event.preventDefault();
-              event.stopPropagation();
-            }
+            this.toggleInspection();
+            event.preventDefault();
+            event.stopPropagation();
             break;
           case this.chromeWin.KeyEvent.DOM_VK_LEFT:
             let node;
             if (this.selection) {
               node = this.selection.parentNode;
             } else {
               node = this.defaultSelection;
             }
@@ -1234,36 +1247,16 @@ InspectorUI.prototype = {
             event.preventDefault();
             event.stopPropagation();
             break;
         }
         break;
     }
   },
 
-  /**
-   * Attach event listeners to content window and child windows to enable
-   * highlighting and click to stop inspection.
-   */
-  attachPageListeners: function IUI_attachPageListeners()
-  {
-    this.browser.addEventListener("keypress", this, true);
-    this.highlighter.attachInspectListeners();
-  },
-
-  /**
-   * Detach event listeners from content window and child windows
-   * to disable highlighting.
-   */
-  detachPageListeners: function IUI_detachPageListeners()
-  {
-    this.browser.removeEventListener("keypress", this, true);
-    this.highlighter.detachInspectListeners();
-  },
-
   /////////////////////////////////////////////////////////////////////////
   //// Utility Methods
 
   /**
    * inspect the given node, highlighting it on the page and selecting the
    * correct row in the tree panel
    *
    * @param aNode
--- a/browser/devtools/highlighter/test/Makefile.in
+++ b/browser/devtools/highlighter/test/Makefile.in
@@ -57,15 +57,16 @@ include $(topsrcdir)/config/rules.mk
 		browser_inspector_registertools.js \
 		browser_inspector_bug_665880.js \
 		browser_inspector_bug_674871.js \
 		browser_inspector_editor.js \
 		browser_inspector_bug_566084_location_changed.js \
 		browser_inspector_infobar.js \
 		browser_inspector_bug_690361.js \
 		browser_inspector_bug_672902_keyboard_shortcuts.js \
+		browser_inspector_keybindings.js \
 		$(NULL)
 
 # Disabled due to constant failures
 # 		browser_inspector_treePanel_click.js \
 
 libs::	$(_BROWSER_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
--- a/browser/devtools/highlighter/test/browser_inspector_initialization.js
+++ b/browser/devtools/highlighter/test/browser_inspector_initialization.js
@@ -72,32 +72,49 @@ function runInspectorTests()
   Services.obs.addObserver(treePanelTests,
     InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY, false);
 
   ok(InspectorUI.toolbar, "we have the toolbar.");
   ok(!InspectorUI.toolbar.hidden, "toolbar is visible");
   ok(InspectorUI.inspecting, "Inspector is inspecting");
   ok(!InspectorUI.treePanel.isOpen(), "Inspector Tree Panel is not open");
   ok(InspectorUI.highlighter, "Highlighter is up");
+  InspectorUI.inspectNode(doc.body);
+  InspectorUI.stopInspecting();
 
   InspectorUI.treePanel.open();
 }
 
 function treePanelTests()
 {
   Services.obs.removeObserver(treePanelTests,
     InspectorUI.INSPECTOR_NOTIFICATIONS.TREEPANELREADY);
-  Services.obs.addObserver(runContextMenuTest,
-    InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
+  Services.obs.addObserver(stylePanelTests,
+    "StyleInspector-opened", false);
 
   ok(InspectorUI.treePanel.isOpen(), "Inspector Tree Panel is open");
 
   executeSoon(function() {
+    InspectorUI.stylePanel.showTool(doc.body);
+  });
+}
+
+function stylePanelTests()
+{
+  Services.obs.removeObserver(stylePanelTests, "StyleInspector-opened");
+  Services.obs.addObserver(runContextMenuTest,
+    InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
+
+  ok(InspectorUI.stylePanel.isOpen(), "Style Panel is Open");
+  ok(InspectorUI.stylePanel.cssHtmlTree, "Style Panel has a cssHtmlTree");
+
+  executeSoon(function() {
     InspectorUI.closeInspectorUI();
   });
+
 }
 
 function runContextMenuTest()
 {
   Services.obs.removeObserver(runContextMenuTest, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
   Services.obs.addObserver(inspectNodesFromContextTest, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
   salutation = doc.getElementById("salutation");
   ok(salutation, "hello, context menu test!");
@@ -116,19 +133,18 @@ function runContextMenuTest()
 }
 
 function inspectNodesFromContextTest()
 {
   Services.obs.removeObserver(inspectNodesFromContextTest, InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
   Services.obs.addObserver(openInspectorForContextTest, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
   ok(!InspectorUI.inspecting, "Inspector is not actively highlighting");
   is(InspectorUI.selection, salutation, "Inspector is highlighting salutation");
-  ok(!InspectorUI.isTreePanelOpen, "Inspector Tree Panel is closed");
-  // TODO: These tests depend on the style inspector patches.
-  todo(InspectorUI.isStylePanelOpen, "Inspector Style Panel is open");
+  ok(!InspectorUI.treePanel.isOpen(), "Inspector Tree Panel is closed");
+  ok(!InspectorUI.stylePanel.isOpen(), "Inspector Style Panel is closed");
   executeSoon(function() {
     InspectorUI.closeInspectorUI(true);
   });
 }
 
 function openInspectorForContextTest()
 {
   Services.obs.removeObserver(openInspectorForContextTest, InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
new file mode 100644
--- /dev/null
+++ b/browser/devtools/highlighter/test/browser_inspector_keybindings.js
@@ -0,0 +1,81 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+
+function test()
+{
+  waitForExplicitFinish();
+
+  let doc;
+  let node;
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onload() {
+    gBrowser.selectedBrowser.removeEventListener("load", onload, true);
+    doc = content.document;
+    waitForFocus(setupKeyBindingsTest, content);
+  }, true);
+
+  content.location = "data:text/html,<h1>foobar</h1>";
+
+  function setupKeyBindingsTest()
+  {
+    node = doc.querySelector("h1");
+    Services.obs.addObserver(highlightNode,
+      InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED, false);
+    InspectorUI.toggleInspectorUI();
+  }
+
+  function highlightNode()
+  {
+    Services.obs.removeObserver(highlightNode,
+      InspectorUI.INSPECTOR_NOTIFICATIONS.OPENED);
+
+    executeSoon(function() {
+      Services.obs.addObserver(lockNode,
+        InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
+
+      InspectorUI.inspectNode(node);
+    });
+  }
+
+  function lockNode()
+  {
+    Services.obs.removeObserver(lockNode,
+      InspectorUI.INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
+
+    EventUtils.synthesizeKey("VK_ESCAPE", { });
+
+    executeSoon(isTheNodeLocked);
+  }
+
+  function isTheNodeLocked()
+  {
+    is(InspectorUI.selection, node, "selection matches node");
+    ok(!InspectorUI.inspecting, "the node is locked");
+    unlockNode();
+  }
+
+  function unlockNode() {
+    EventUtils.synthesizeKey("VK_ESCAPE", { });
+
+    executeSoon(isTheNodeUnlocked);
+  }
+
+  function isTheNodeUnlocked()
+  {
+    ok(InspectorUI.inspecting, "the node is unlocked");
+
+    Services.obs.addObserver(finishUp,
+      InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED, false);
+    InspectorUI.closeInspectorUI();
+  }
+
+  function finishUp() {
+    Services.obs.removeObserver(finishUp,
+                                InspectorUI.INSPECTOR_NOTIFICATIONS.CLOSED);
+    doc = node = null;
+    gBrowser.removeCurrentTab();
+    finish();
+  }
+}
--- a/browser/devtools/styleinspector/CssHtmlTree.jsm
+++ b/browser/devtools/styleinspector/CssHtmlTree.jsm
@@ -323,16 +323,44 @@ CssHtmlTree.prototype = {
         CssHtmlTree.propertyNames.push(prop);
       }
     }
 
     CssHtmlTree.propertyNames.sort();
     CssHtmlTree.propertyNames.push.apply(CssHtmlTree.propertyNames,
       mozProps.sort());
   },
+
+  /**
+   * Destructor for CssHtmlTree.
+   */
+  destroy: function CssHtmlTree_destroy()
+  {
+    delete this.viewedElement;
+
+    // Nodes used in templating
+    delete this.root;
+    delete this.path;
+    delete this.templateRoot;
+    delete this.templatePath;
+    delete this.propertyContainer;
+    delete this.templateProperty;
+    delete this.panel;
+
+    // The document in which we display the results (csshtmltree.xhtml).
+    delete this.styleDocument;
+
+    // The element that we're inspecting, and the document that it comes from.
+    delete this.propertyViews;
+    delete this.getRTLAttr;
+    delete this.styleWin;
+    delete this.cssLogic;
+    delete this.doc;
+    delete this.win;
+  },
 };
 
 /**
  * A container to give easy access to property data from the template engine.
  *
  * @constructor
  * @param {CssHtmlTree} aTree the CssHtmlTree instance we are working with.
  * @param {string} aName the CSS property name for which this PropertyView
--- a/browser/devtools/styleinspector/StyleInspector.jsm
+++ b/browser/devtools/styleinspector/StyleInspector.jsm
@@ -61,35 +61,34 @@ var StyleInspector = {
    * @param {Boolean} aPreserveOnHide Prevents destroy from being called
    * onpopuphide. USE WITH CAUTION: When this value is set to true then you are
    * responsible to manually call destroy from outside the style inspector.
    */
   createPanel: function SI_createPanel(aPreserveOnHide)
   {
     let win = Services.wm.getMostRecentWindow("navigator:browser");
     let popupSet = win.document.getElementById("mainPopupSet");
-    let ns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-    let panel = win.document.createElementNS(ns, "panel");
+    let panel = win.document.createElement("panel");
 
     panel.setAttribute("class", "styleInspector");
     panel.setAttribute("orient", "vertical");
     panel.setAttribute("ignorekeys", "true");
     panel.setAttribute("noautofocus", "true");
     panel.setAttribute("noautohide", "true");
     panel.setAttribute("titlebar", "normal");
     panel.setAttribute("close", "true");
     panel.setAttribute("label", StyleInspector.l10n("panelTitle"));
     panel.setAttribute("width", 350);
     panel.setAttribute("height", win.screen.height / 2);
 
     let vbox = win.document.createElement("vbox");
     vbox.setAttribute("flex", "1");
     panel.appendChild(vbox);
 
-    let iframe = win.document.createElementNS(ns, "iframe");
+    let iframe = win.document.createElement("iframe");
     iframe.setAttribute("flex", "1");
     iframe.setAttribute("tooltip", "aHTMLTooltip");
     iframe.setAttribute("src", "chrome://browser/content/csshtmltree.xhtml");
     iframe.addEventListener("load", SI_iframeOnload, true);
     vbox.appendChild(iframe);
 
     let hbox = win.document.createElement("hbox");
     hbox.setAttribute("class", "resizerbox");
@@ -140,18 +139,18 @@ var StyleInspector = {
     function SI_popupHidden() {
       if (panel.preserveOnHide) {
         Services.obs.notifyObservers(null, "StyleInspector-closed", null);
       } else {
         panel.destroy();
       }
     }
 
-    panel.addEventListener("popupshown", SI_popupShown);
-    panel.addEventListener("popuphidden", SI_popupHidden);
+    panel.addEventListener("popupshown", SI_popupShown, false);
+    panel.addEventListener("popuphidden", SI_popupHidden, false);
     panel.preserveOnHide = !!aPreserveOnHide;
 
     /**
      * Check if the style inspector is open
      */
     panel.isOpen = function SI_isOpen()
     {
       return this.state && this.state == "open";
@@ -171,25 +170,31 @@ var StyleInspector = {
       }
     };
 
     /**
      * Destroy the style panel, remove listeners etc.
      */
     panel.destroy = function SI_destroy()
     {
-      if (!this.cssLogic)
-        return;
       if (this.isOpen())
         this.hideTool();
-      this.cssLogic = null;
-      this.cssHtmlTree = null;
-      this.removeEventListener("popupshown", SI_popupShown);
-      this.removeEventListener("popuphidden", SI_popupHidden);
-      this.parentNode.removeChild(this);
+      if (panel.cssHtmlTree)
+        panel.cssHtmlTree.destroy();
+      if (iframe) {
+        iframe.parentNode.removeChild(iframe);
+        iframe = null;
+      }
+
+      delete panel.cssLogic;
+      delete panel.cssHtmlTree;
+      panel.removeEventListener("popupshown", SI_popupShown, false);
+      panel.removeEventListener("popuphidden", SI_popupHidden, false);
+      panel.parentNode.removeChild(panel);
+      panel = null;
       Services.obs.notifyObservers(null, "StyleInspector-closed", null);
     };
 
     /**
      * Dim or undim a panel by setting or removing a dimmed attribute.
      *
      * @param aState
      *        true = dim, false = undim
--- a/browser/devtools/styleinspector/test/browser/browser_bug683672.js
+++ b/browser/devtools/styleinspector/test/browser/browser_bug683672.js
@@ -15,16 +15,17 @@ function test()
 {
   waitForExplicitFinish();
   addTab(TEST_URI);
   browser.addEventListener("load", tabLoaded, true);
 }
 
 function tabLoaded()
 {
+  browser.removeEventListener("load", tabLoaded, true);
   ok(window.StyleInspector, "StyleInspector exists");
   ok(StyleInspector.isEnabled, "style inspector preference is enabled");
   stylePanel = StyleInspector.createPanel();
   Services.obs.addObserver(runTests, "StyleInspector-opened", false);
   stylePanel.openPopup();
 }
 
 function runTests()
--- a/browser/locales/en-US/chrome/overrides/appstrings.properties
+++ b/browser/locales/en-US/chrome/overrides/appstrings.properties
@@ -42,16 +42,17 @@ connectionFailure=Firefox can't establis
 netInterrupt=The connection to %S was interrupted while the page was loading.
 netTimeout=The server at %S is taking too long to respond.
 redirectLoop=Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
 ## LOCALIZATION NOTE (confirmRepostPrompt): In this item, don't translate "%S"
 confirmRepostPrompt=To display this page, %S must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.
 resendButton.label=Resend
 unknownSocketType=Firefox doesn't know how to communicate with the server.
 netReset=The connection to the server was reset while the page was loading.
+notCached=This document is no longer available.
 netOffline=Firefox is currently in offline mode and can't browse the Web.
 isprinting=The document cannot change while Printing or in Print Preview.
 deniedPortAccess=This address uses a network port which is normally used for purposes other than Web browsing. Firefox has canceled the request for your protection.
 proxyResolveFailure=Firefox is configured to use a proxy server that can't be found.
 proxyConnectFailure=Firefox is configured to use a proxy server that is refusing connections.
 contentEncodingError=The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.
 unsafeContentType=The page you are trying to view cannot be shown because it is contained in a file type that may not be safe to open. Please contact the website owners to inform them of this problem.
 externalProtocolTitle=External Protocol Request
--- a/browser/locales/en-US/chrome/overrides/netError.dtd
+++ b/browser/locales/en-US/chrome/overrides/netError.dtd
@@ -47,16 +47,19 @@
   <li>Make sure that you're using forward slashes (i.e.
     <strong>/</strong>).</li>
 </ul>
 ">
 
 <!ENTITY netInterrupt.title "The connection was interrupted">
 <!ENTITY netInterrupt.longDesc "&sharedLongDesc;">
 
+<!ENTITY notCached.title "Document Expired">
+<!ENTITY notCached.longDesc "<p>The requested document is not available in Firefox's cache.</p><ul><li>As a security precuation, Firefox does not automatically re-request sensitive documents.</li><li>Click Try Again to re-request the document from the website.</li></ul>">
+
 <!ENTITY netOffline.title "Offline mode">
 <!ENTITY netOffline.longDesc2 "
 <ul>
   <li>Press &quot;Try Again&quot; to switch to online mode and reload the page.</li>
 </ul>
 ">
 
 <!ENTITY contentEncodingError.title "Content Encoding Error">
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -280,18 +280,20 @@ class DeviceManagerADB(DeviceManager):
     return self.getFile(remoteFile)
 
   # copy file from device (remoteFile) to host (localFile)
   # external function
   # returns:
   #  success: output of pullfile, string
   #  failure: None
   def getFile(self, remoteFile, localFile = 'tmpfile_dm_adb'):
+    # TODO: add debug flags and allow for printing stdout
+    # self.runCmd(["pull", remoteFile, localFile])
     try:
-      self.checkCmd(["pull",  remoteFile, localFile])
+      self.runCmd(["pull",  remoteFile, localFile]).stdout.read()
       f = open(localFile)
       ret = f.read()
       f.close()
       return ret;      
     except:
       return None
 
   # copy directory structure from device (remoteDir) to host (localDir)
--- a/configure.in
+++ b/configure.in
@@ -7122,27 +7122,16 @@ MOZ_ARG_ENABLE_BOOL(tracevis,
 [  --enable-tracevis       Enable TraceVis tracing tool (default=no)],
     MOZ_TRACEVIS=1,
     MOZ_TRACEVIS= )
 if test -n "$MOZ_TRACEVIS"; then
     AC_DEFINE(MOZ_TRACEVIS)
 fi
 
 dnl ========================================================
-dnl = Use GCTimer
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(gctimer,
-[  --enable-gctimer        Enable GC timer (default=no)],
-    MOZ_GCTIMER=1,
-    MOZ_GCTIMER= )
-if test -n "$MOZ_GCTIMER"; then
-    AC_DEFINE(MOZ_GCTIMER)
-fi
-
-dnl ========================================================
 dnl ETW - Event Tracing for Windows
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(ETW,
 [  --enable-ETW            Enable ETW (Event Tracing for Windows) event reporting
                           (needs Windows Vista+ SDK)],
     MOZ_ETW=1,
     MOZ_ETW= )
 if test -n "$MOZ_ETW"; then
@@ -7400,16 +7389,33 @@ AC_SUBST(MOZ_DEMANGLE_SYMBOLS)
 dnl ========================================================
 dnl = Support for gcc stack unwinding (from gcc 3.3)
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     MOZ_CHECK_HEADER(unwind.h, AC_CHECK_FUNCS(_Unwind_Backtrace))
 fi
 
 dnl ========================================================
+dnl JIT observers
+dnl ========================================================
+
+MOZ_ARG_WITH_STRING(jitreport-granularity,
+[  --jitreport-granularity=N
+                           Default granularity at which to report JIT code
+                           to external tools
+                             0 - no info
+                             1 - code ranges for whole functions only
+                             2 - per-line information
+                             3 - per-op information],
+  JITREPORT_GRANULARITY=$withval,
+  JITREPORT_GRANULARITY=3)
+
+AC_DEFINE_UNQUOTED(JS_DEFAULT_JITREPORT_GRANULARITY, $JITREPORT_GRANULARITY)
+
+dnl ========================================================
 dnl =
 dnl = Misc. Options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Misc. Options)
 
 dnl ========================================================
 dnl update xterm title
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -121,18 +121,18 @@ class Loader;
 
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID      \
-{ 0xd76bcf5f, 0xd02f, 0x459a, \
- { 0xb1, 0x23, 0x8e, 0x2c, 0x9a, 0x0d, 0x84, 0x68 } }
+{ 0x448c396a, 0x013c, 0x47b8, \
+ { 0x95, 0xf4, 0x56, 0x68, 0x0f, 0x5f, 0x12, 0xf8 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Document states
 
 // RTL locale: specific to the XUL localedir attribute
 #define NS_DOCUMENT_STATE_RTL_LOCALE              NS_DEFINE_EVENT_STATE_MACRO(0)
@@ -1316,27 +1316,27 @@ public:
   virtual void EnumerateExternalResources(nsSubDocEnumFunc aCallback,
                                           void* aData) = 0;
 
   /**
    * Return whether the document is currently showing (in the sense of
    * OnPageShow() having been called already and OnPageHide() not having been
    * called yet.
    */
-  bool IsShowing() { return mIsShowing; }
+  bool IsShowing() const { return mIsShowing; }
   /**
    * Return whether the document is currently visible (in the sense of
    * OnPageHide having been called and OnPageShow not yet having been called)
    */
-  bool IsVisible() { return mVisible; }
+  bool IsVisible() const { return mVisible; }
   /**
    * Return true when this document is active, i.e., the active document
    * in a content viewer.
    */
-  bool IsActive() { return mDocumentContainer && !mRemovedFromDocShell; }
+  bool IsActive() const { return mDocumentContainer && !mRemovedFromDocShell; }
 
   void RegisterFreezableElement(nsIContent* aContent);
   bool UnregisterFreezableElement(nsIContent* aContent);
   typedef void (* FreezableElementEnumerator)(nsIContent*, void*);
   void EnumerateFreezableElements(FreezableElementEnumerator aEnumerator,
                                   void* aData);
 
 #ifdef MOZ_SMIL
@@ -1568,16 +1568,18 @@ public:
 #define DEPRECATED_OPERATION(_op) e##_op,
   enum DeprecatedOperations {
 #include "nsDeprecatedOperationList.h"
     eDeprecatedOperationCount
   };
 #undef DEPRECATED_OPERATION
   void WarnOnceAbout(DeprecatedOperations aOperation);
 
+  virtual void PostVisibilityUpdateEvent() = 0;
+
 private:
   PRUint64 mWarnedAbout;
 
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
     //     releasing it) happens in the nsDocument destructor. We'd prefer to
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1521,16 +1521,17 @@ nsDOMImplementation::CreateHTMLDocument(
 
   // NOTE! nsDocument::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 
 nsDocument::nsDocument(const char* aContentType)
   : nsIDocument()
   , mAnimatingImages(PR_TRUE)
   , mIsFullScreen(PR_FALSE)
+  , mVisibilityState(eHidden)
 {
   SetContentTypeInternal(nsDependentCString(aContentType));
   
 #ifdef PR_LOGGING
   if (!gDocumentLeakPRLog)
     gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
 
   if (gDocumentLeakPRLog)
@@ -3832,16 +3833,23 @@ nsDocument::SetScriptGlobalObject(nsIScr
 
     MaybeRescheduleAnimationFrameNotifications();
   }
 
   // Remember the pointer to our window (or lack there of), to avoid
   // having to QI every time it's asked for.
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mScriptGlobalObject);
   mWindow = window;
+
+  // Set our visibility state, but do not fire the event.  This is correct
+  // because either we're coming out of bfcache (in which case IsVisible() will
+  // still test false at this point and no state change will happen) or we're
+  // doing the initial document load and don't want to fire the event for this
+  // change.
+  mVisibilityState = GetVisibilityState();
 }
 
 nsIScriptGlobalObject*
 nsDocument::GetScriptHandlingObjectInternal() const
 {
   NS_ASSERTION(!mScriptGlobalObject,
                "Do not call this when mScriptGlobalObject is set!");
 
@@ -7317,16 +7325,18 @@ nsDocument::OnPageShow(bool aPersisted,
     mAnimationController->OnPageShow();
   }
 #endif
 
   if (aPersisted) {
     SetImagesNeedAnimating(PR_TRUE);
   }
 
+  UpdateVisibilityState();
+
   nsCOMPtr<nsIDOMEventTarget> target = aDispatchStartTarget;
   if (!target) {
     target = do_QueryInterface(GetWindow());
   }
   DispatchPageTransition(target, NS_LITERAL_STRING("pageshow"), aPersisted);
 }
 
 static bool
@@ -7378,16 +7388,19 @@ nsDocument::OnPageHide(bool aPersisted,
   // Now send out a PageHide event.
   nsCOMPtr<nsIDOMEventTarget> target = aDispatchStartTarget;
   if (!target) {
     target = do_QueryInterface(GetWindow());
   }
   DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
 
   mVisible = PR_FALSE;
+
+  UpdateVisibilityState();
+  
   EnumerateExternalResources(NotifyPageHide, &aPersisted);
   EnumerateFreezableElements(NotifyActivityChanged, nsnull);
 }
 
 void
 nsDocument::WillDispatchMutationEvent(nsINode* aTarget)
 {
   NS_ASSERTION(mSubtreeModifiedDepth != 0 ||
@@ -8653,8 +8666,66 @@ nsDocument::SizeOf() const
     return nsINode::SetOn##name_(cx, v);                                  \
   }
 #define TOUCH_EVENT EVENT
 #define DOCUMENT_ONLY_EVENT EVENT
 #include "nsEventNameList.h"
 #undef DOCUMENT_ONLY_EVENT
 #undef TOUCH_EVENT
 #undef EVENT
+
+void
+nsDocument::UpdateVisibilityState()
+{
+  VisibilityState oldState = mVisibilityState;
+  mVisibilityState = GetVisibilityState();
+  if (oldState != mVisibilityState) {
+    nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
+                                         NS_LITERAL_STRING("mozvisibilitychange"),
+                                         false, false);
+  }
+}
+
+nsDocument::VisibilityState
+nsDocument::GetVisibilityState() const
+{
+  // We have to check a few pieces of information here:
+  // 1)  Are we in bfcache (!IsVisible())?  If so, nothing else matters.
+  // 2)  Do we have an outer window?  If not, we're hidden.  Note that we don't
+  //     want to use GetWindow here because it does weird groveling for windows
+  //     in some cases.
+  // 3)  Is our outer window background?  If so, we're hidden.
+  // Otherwise, we're visible.
+  if (!IsVisible() || !mWindow || !mWindow->GetOuterWindow() ||
+      mWindow->GetOuterWindow()->IsBackground()) {
+    return eHidden;
+  }
+
+  return eVisible;
+}
+
+/* virtual */ void
+nsDocument::PostVisibilityUpdateEvent()
+{
+  nsCOMPtr<nsIRunnable> event =
+    NS_NewRunnableMethod(this, &nsDocument::UpdateVisibilityState);
+  NS_DispatchToMainThread(event);
+}
+
+NS_IMETHODIMP
+nsDocument::GetMozHidden(bool* aHidden)
+{
+  *aHidden = mVisibilityState != eVisible;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocument::GetMozVisibilityState(nsAString& aState)
+{
+  // This needs to stay in sync with the VisibilityState enum.
+  static const char states[][8] = {
+    "hidden",
+    "visible"
+  };
+  PR_STATIC_ASSERT(NS_ARRAY_LENGTH(states) == eVisibilityStateCount);
+  aState.AssignASCII(states[mVisibilityState]);
+  return NS_OK;
+}
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -943,16 +943,22 @@ public:
 
   virtual void ResetFullScreenElement();
   virtual Element* GetFullScreenElement();
   virtual void RequestFullScreen(Element* aElement);
   virtual void CancelFullScreen();
   virtual void UpdateFullScreenStatus(bool aIsFullScreen);
   virtual bool IsFullScreenDoc();
 
+  // This method may fire a DOM event; if it does so it will happen
+  // synchronously.
+  void UpdateVisibilityState();
+  // Posts an event to call UpdateVisibilityState
+  virtual void PostVisibilityUpdateEvent();
+
 protected:
   friend class nsNodeUtils;
 
   /**
    * Check that aId is not empty and log a message to the console
    * service if it is.
    * @returns PR_TRUE if aId looks correct, PR_FALSE otherwise.
    */
@@ -1145,16 +1151,24 @@ protected:
   nsCOMPtr<nsIContent> mFirstBaseNodeWithHref;
 
   nsEventStates mDocumentState;
   nsEventStates mGotDocumentState;
 
   nsRefPtr<nsDOMNavigationTiming> mTiming;
 private:
   friend class nsUnblockOnloadEvent;
+  // This needs to stay in sync with the list in GetMozVisibilityState.
+  enum VisibilityState {
+    eHidden = 0,
+    eVisible,
+    eVisibilityStateCount
+  };
+  // Recomputes the visibility state but doesn't set the new value.
+  VisibilityState GetVisibilityState() const;
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
   nsresult CheckFrameOptions();
   nsresult InitCSP();
 
   /**
@@ -1225,16 +1239,18 @@ private:
 
   nsCString mScrollToRef;
   PRUint8 mScrolledToRefAlready : 1;
   PRUint8 mChangeScrollPosWhenScrollingToRef : 1;
 
   // Tracking for images in the document.
   nsDataHashtable< nsPtrHashKey<imgIRequest>, PRUint32> mImageTracker;
 
+  VisibilityState mVisibilityState;
+
 #ifdef DEBUG
 protected:
   bool mWillReparent;
 #endif
 };
 
 #define NS_DOCUMENT_INTERFACE_TABLE_BEGIN(_class)                             \
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                            \
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -511,16 +511,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug675166.html \
 		test_bug682554.html \
 		test_bug682592.html \
 		bug682592-subframe.html \
 		bug682592-subframe-ref.html \
 		test_bug684671.html \
 		test_bug685798.html \
 		test_bug686449.xhtml \
+		test_bug690056.html \
 		test_bug692434.html \
 		file_bug692434.xml \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug690056.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=690056
+-->
+<head>
+  <title>Test for Bug 690056</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=690056">Mozilla Bug 690056</a>
+<p id="display">
+  <iframe id="x"></iframe>
+  <iframe style="display: none" id="y"></iframe>
+</p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 690056 **/
+SimpleTest.waitForExplicitFinish();
+is(document.mozHidden, false, "Document should not be hidden during load");
+is(document.mozVisibilityState, "visible",
+   "Document should be visible during load");
+
+addLoadEvent(function() {
+  var doc = document.implementation.createDocument("", "", null);
+  is(doc.mozHidden, true, "Data documents should be hidden");
+  is(doc.mozVisibilityState, "hidden", "Data documents really should be hidden");
+
+  is(document.mozHidden, false, "Document should not be hidden onload");
+  is(document.mozVisibilityState, "visible",
+     "Document should be visible onload");
+
+  is($("x").contentDocument.mozHidden, false,
+     "Subframe document should not be hidden onload");
+  is($("x").contentDocument.mozVisibilityState, "visible",
+     "Subframe document should be visible onload");
+  is($("y").contentDocument.mozHidden, false,
+     "display:none subframe document should not be hidden onload");
+  is($("y").contentDocument.mozVisibilityState, "visible",
+     "display:none subframe document should be visible onload");
+  
+  SimpleTest.finish();
+});
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/xslt/src/xslt/txStylesheetCompiler.h
+++ b/content/xslt/src/xslt/txStylesheetCompiler.h
@@ -72,18 +72,18 @@ public:
     nsRefPtr<txNamespaceMap> mMappings;
     nsTArray<PRInt32> mInstructionNamespaces;
     PRInt32 mDepth;
 };
 
 class txACompileObserver
 {
 public:
-    virtual void AddRef() = 0;
-    virtual void Release() = 0;
+    NS_IMETHOD_(nsrefcnt) AddRef() = 0;
+    NS_IMETHOD_(nsrefcnt) Release() = 0;
 
     virtual nsresult loadURI(const nsAString& aUri,
                              const nsAString& aReferrerUri,
                              txStylesheetCompiler* aCompiler) = 0;
     virtual void onDoneCompiling(txStylesheetCompiler* aCompiler,
                                  nsresult aResult,
                                  const PRUnichar *aErrorText = nsnull,
                                  const PRUnichar *aParam = nsnull) = 0;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3969,20 +3969,22 @@ nsDocShell::DisplayLoadError(nsresult aE
             error.AssignLiteral("unknownSocketType");
             break;
         case NS_ERROR_NET_RESET:
             // Doc failed to load because the server kept reseting the connection
             // before we could read any data from it
             error.AssignLiteral("netReset");
             break;
         case NS_ERROR_DOCUMENT_NOT_CACHED:
-            // Doc failed to load because we are offline and the cache does not
-            // contain a copy of the document.
+            // Doc failed to load because the cache does not contain a copy of
+            // the document.
+            error.AssignLiteral("notCached");
+            break;
         case NS_ERROR_OFFLINE:
-            // Doc failed to load because we are offline
+            // Doc failed to load because we are offline.
             error.AssignLiteral("netOffline");
             break;
         case NS_ERROR_DOCUMENT_IS_PRINTMODE:
             // Doc navigation attempted while Printing or Print Preview
             error.AssignLiteral("isprinting");
             break;
         case NS_ERROR_PORT_ACCESS_NOT_ALLOWED:
             // Port blocked for security reasons
@@ -4877,16 +4879,20 @@ nsDocShell::SetIsActive(bool aIsActive)
   GetPresShell(getter_AddRefs(pshell));
   if (pshell)
     pshell->SetIsActive(aIsActive);
 
   // Tell the window about it
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mScriptGlobal);
   if (win) {
       win->SetIsBackground(!aIsActive);
+      nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
+      if (doc) {
+          doc->PostVisibilityUpdateEvent();
+      }
   }
 
   // Recursively tell all of our children
   PRInt32 n = mChildList.Count();
   for (PRInt32 i = 0; i < n; ++i) {
       nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(ChildAt(i));
       if (docshell)
         docshell->SetIsActive(aIsActive);
@@ -6361,119 +6367,27 @@ nsDocShell::EndPageLoad(nsIWebProgress *
                  aStatus == NS_ERROR_UNKNOWN_SOCKET_TYPE ||
                  aStatus == NS_ERROR_NET_INTERRUPT ||
                  aStatus == NS_ERROR_NET_RESET ||
                  aStatus == NS_ERROR_OFFLINE ||
                  aStatus == NS_ERROR_MALWARE_URI ||
                  aStatus == NS_ERROR_PHISHING_URI ||
                  aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE ||
                  aStatus == NS_ERROR_REMOTE_XUL ||
+                 aStatus == NS_ERROR_OFFLINE ||
                  NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) {
             DisplayLoadError(aStatus, url, nsnull, aChannel);
         }
         else if (aStatus == NS_ERROR_DOCUMENT_NOT_CACHED) {
-            /* A document that was requested to be fetched *only* from
-             * the cache is not in cache. May be this is one of those 
-             * postdata results. Throw a  dialog to the user,
-             * saying that the page has expired from cache and ask if 
-             * they wish to refetch the page from the net. Do this only
-             * if the request is a form post.
-             */
-            nsCAutoString method;
-            if (httpChannel)
-                httpChannel->GetRequestMethod(method);
-            if (method.Equals("POST") && !NS_IsOffline()) {
-                bool repost;
-                rv = ConfirmRepost(&repost);
-                if (NS_FAILED(rv)) return rv;
-                // If the user pressed cancel in the dialog, return. Don't try
-                // to load the page without the post data.
-                if (!repost)
-                    return NS_OK;
-
-                // The user wants to repost the data to the server.
-                // If the page was loaded due to a back/forward/go
-                // operation, update the session history index.
-                // This is similar to the updating done in
-                // nsDocShell::OnNewURI() for regular pages
-                nsCOMPtr<nsISHistory> rootSH=mSessionHistory;
-                if (!mSessionHistory) {
-                    nsCOMPtr<nsIDocShellTreeItem> root;
-                    //Get the root docshell
-                    GetSameTypeRootTreeItem(getter_AddRefs(root));
-                    if (root) {
-                        // QI root to nsIWebNavigation
-                        nsCOMPtr<nsIWebNavigation> rootAsWebnav =
-                            do_QueryInterface(root);
-                        if (rootAsWebnav) {
-                            // Get the handle to SH from the root docshell
-                            rootAsWebnav->GetSessionHistory(getter_AddRefs(rootSH));
-                        }
-                    }
-                }  // mSessionHistory
-
-                if (rootSH && (mLoadType & LOAD_CMD_HISTORY)) {
-                    nsCOMPtr<nsISHistoryInternal> shInternal =
-                        do_QueryInterface(rootSH);
-                    if (shInternal) {
-                        rootSH->GetIndex(&mPreviousTransIndex);
-                        shInternal->UpdateIndex();
-                        rootSH->GetIndex(&mLoadedTransIndex);
-#ifdef DEBUG_PAGE_CACHE
-                        printf("Previous index: %d, Loaded index: %d\n\n",
-                               mPreviousTransIndex, mLoadedTransIndex);
-#endif
-                    }
-                }
-
-                // Make it look like we really did honestly finish loading the
-                // history page we were loading, since the "reload" load we're
-                // about to kick off will reload our current history entry.
-                // This is a bit of a hack, and if the force-load fails I think
-                // we'll end up being confused about what page we're on... but
-                // we would anyway, since we've updated the session history
-                // index above.
-                SetHistoryEntry(&mOSHE, loadingSHE);
-
-                // The user does want to repost the data to the server.
-                // Initiate a new load again.
-
-                // Get the postdata if any from the channel.
-                nsCOMPtr<nsIInputStream> inputStream;
-                nsCOMPtr<nsIURI> referrer;
-                if (httpChannel) {
-                    httpChannel->GetReferrer(getter_AddRefs(referrer));
-                    nsCOMPtr<nsIUploadChannel> uploadChannel =
-                        do_QueryInterface(aChannel);
-                    if (uploadChannel) {
-                        uploadChannel->GetUploadStream(getter_AddRefs(inputStream));
-                    }
-                }
-                nsCOMPtr<nsISeekableStream> postDataSeekable =
-                    do_QueryInterface(inputStream);
-                if (postDataSeekable) {
-                    postDataSeekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
-                }
-                InternalLoad(url,                               // URI
-                             referrer,                          // Referring URI
-                             nsnull,                            // Owner
-                             INTERNAL_LOAD_FLAGS_INHERIT_OWNER, // Inherit owner
-                             nsnull,                            // No window target
-                             nsnull,                            // No type hint
-                             inputStream,                       // Post data stream
-                             nsnull,                            // No headers stream
-                             LOAD_RELOAD_BYPASS_PROXY_AND_CACHE,// Load type
-                             nsnull,                            // No SHEntry
-                             PR_TRUE,                           // first party site
-                             nsnull,                            // No nsIDocShell
-                             nsnull);                           // No nsIRequest
-            }
-            else {
-                DisplayLoadError(aStatus, url, nsnull, aChannel);
-            }
+            // Non-caching channels will simply return NS_ERROR_OFFLINE.
+            // Caching channels would have to look at their flags to work
+            // out which error to return. Or we can fix up the error here.
+            if (!(mLoadType & LOAD_CMD_HISTORY))
+                aStatus = NS_ERROR_OFFLINE;
+            DisplayLoadError(aStatus, url, nsnull, aChannel);
         }
   } // if we have a host
 
   return NS_OK;
 }
 
 
 //*****************************************************************************
--- a/docshell/resources/content/netError.xhtml
+++ b/docshell/resources/content/netError.xhtml
@@ -318,16 +318,17 @@
         <h1 id="et_fileNotFound">&fileNotFound.title;</h1>
         <h1 id="et_malformedURI">&malformedURI.title;</h1>
         <h1 id="et_protocolNotFound">&protocolNotFound.title;</h1>
         <h1 id="et_connectionFailure">&connectionFailure.title;</h1>
         <h1 id="et_netTimeout">&netTimeout.title;</h1>
         <h1 id="et_redirectLoop">&redirectLoop.title;</h1>
         <h1 id="et_unknownSocketType">&unknownSocketType.title;</h1>
         <h1 id="et_netReset">&netReset.title;</h1>
+        <h1 id="et_notCached">&notCached.title;</h1>
         <h1 id="et_netOffline">&netOffline.title;</h1>
         <h1 id="et_netInterrupt">&netInterrupt.title;</h1>
         <h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
         <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
         <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
         <h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
         <h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
         <h1 id="et_nssFailure2">&nssFailure2.title;</h1>
@@ -343,16 +344,17 @@
         <div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
         <div id="ed_malformedURI">&malformedURI.longDesc;</div>
         <div id="ed_protocolNotFound">&protocolNotFound.longDesc;</div>
         <div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
         <div id="ed_netTimeout">&netTimeout.longDesc;</div>
         <div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
         <div id="ed_unknownSocketType">&unknownSocketType.longDesc;</div>
         <div id="ed_netReset">&netReset.longDesc;</div>
+        <div id="ed_notCached">&notCached.longDesc;</div>
         <div id="ed_netOffline">&netOffline.longDesc2;</div>
         <div id="ed_netInterrupt">&netInterrupt.longDesc;</div>
         <div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div>
         <div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc;</div>
         <div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div>
         <div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
         <div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
         <div id="ed_nssFailure2">&nssFailure2.longDesc;</div>
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -115,16 +115,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bug454235.xul \
 		bug454235-subframe.xul \
 		test_bug456980.xul \
 		test_bug662200.xul \
 		bug662200_window.xul \
 		662200a.html \
 		662200b.html \
 		662200c.html \
+		test_bug690056.xul \
+		bug690056_window.xul \
 		$(NULL)
 
 _DOCSHELL_SUBHARNESS = \
     docshell_helpers.js \
     generic.html \
     $(NULL)
 
 libs:: $(_HTTP_FILES)
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/bug690056_window.xul
@@ -0,0 +1,176 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="690056Test"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        width="600"
+        height="600"
+        onload="setTimeout(nextTest,0);"
+        title="bug 6500056 test">
+
+  <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+  <script type="application/javascript" src="docshell_helpers.js" />
+  <script type="application/javascript"><![CDATA[
+    var tests = testIterator();
+
+    function nextTest() {
+      tests.next();
+    }
+
+    // Makes sure that we fire the visibilitychange events
+    function testIterator() {
+      // Enable bfcache
+      enableBFCache(8);
+
+      // Load something for a start
+      doPageNavigation({
+        uri: 'data:text/html,<title>initial load</title>',
+        onNavComplete: nextTest
+      });
+      yield;
+
+      // Now load a new page
+      doPageNavigation({
+        uri: 'data:text/html,<title>new load</title>',
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "initial load",
+                            persisted: true },
+                          { type: "mozvisibilitychange",
+                            title: "initial load",
+                            visibilityState: "hidden",
+                            hidden: true },
+                          // No visibilitychange events fired for initial pageload
+                          { type: "pageshow",
+                            title: "new load",
+                            persisted: false }, // false on initial load
+                        ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      // Now go back
+      doPageNavigation({
+        back: true,
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "new load",
+                            persisted: true },
+                          { type: "mozvisibilitychange",
+                            title: "new load",
+                            visibilityState: "hidden",
+                            hidden: true },
+                          { type: "mozvisibilitychange",
+                            title: "initial load",
+                            visibilityState: "visible",
+                            hidden: false },
+                          { type: "pageshow",
+                            title: "initial load",
+                            persisted: true },
+                        ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      // And forward
+      doPageNavigation({
+        forward: true,
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "initial load",
+                            persisted: true },
+                          { type: "mozvisibilitychange",
+                            title: "initial load",
+                            visibilityState: "hidden",
+                            hidden: true },
+                          { type: "mozvisibilitychange",
+                            title: "new load",
+                            visibilityState: "visible",
+                            hidden: false },
+                          { type: "pageshow",
+                            title: "new load",
+                            persisted: true },
+                        ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      function generateDetector(state, hidden, title, name) {
+        var detector = function (event) {
+          is(event.target.mozHidden, hidden,
+             name + " hidden value does not match");
+          is(event.target.mozVisibilityState, state,
+             name + " state value does not match");
+          is(event.target.title, title,
+             name + " title value does not match");
+          document.getElementById("content")
+                  .removeEventListener("mozvisibilitychange",
+                                       detector,
+                                       true);
+          nextTest();
+        }
+
+        document.getElementById("content")
+                .addEventListener("mozvisibilitychange", detector, true);
+      }
+      
+      generateDetector("hidden", true, "new load", "Going hidden");
+        
+      // Now flip our docshell to not active
+      document.getElementById("content").docShellIsActive = false;
+      yield;
+
+      // And navigate back; there should be no visibility state transitions
+      doPageNavigation({
+        back: true,
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "new load",
+                            persisted: true },
+                          { type: "pageshow",
+                            title: "initial load",
+                            persisted: true },
+                        ],
+        unexpectedEvents: [ "mozvisibilitychange" ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      generateDetector("visible", false, "initial load", "Going visible");
+
+      // Now set the docshell active again
+      document.getElementById("content").docShellIsActive = true;
+      yield;
+
+      // And forward
+      doPageNavigation({
+        forward: true,
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "initial load",
+                            persisted: true },
+                          { type: "mozvisibilitychange",
+                            title: "initial load",
+                            visibilityState: "hidden",
+                            hidden: true },
+                          { type: "mozvisibilitychange",
+                            title: "new load",
+                            visibilityState: "visible",
+                            hidden: false },
+                          { type: "pageshow",
+                            title: "new load",
+                            persisted: true },
+                        ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      // Tell the framework the test is finished.  Include the final 'yield' 
+      // statement to prevent a StopIteration exception from being thrown.
+      finish();
+      yield;      
+    }
+  ]]></script>
+
+  <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
\ No newline at end of file
--- a/docshell/test/chrome/docshell_helpers.js
+++ b/docshell/test/chrome/docshell_helpers.js
@@ -13,16 +13,18 @@ for each (var name in imports) {
 const NAV_NONE = 0;
 const NAV_BACK = 1;
 const NAV_FORWARD = 2;
 const NAV_URI = 3;
 const NAV_RELOAD = 4;
 
 var gExpectedEvents;          // an array of events which are expected to
                               // be triggered by this navigation
+var gUnexpectedEvents;        // an array of event names which are NOT expected
+                              // to be triggered by this navigation
 var gFinalEvent;              // true if the last expected event has fired
 var gUrisNotInBFCache = [];   // an array of uri's which shouldn't be stored
                               // in the bfcache
 var gNavType = NAV_NONE;      // defines the most recent navigation type
                               // executed by doPageNavigation
 var gOrigMaxTotalViewers =    // original value of max_total_viewers,
   undefined;                  // to be restored at end of test
 
@@ -90,16 +92,18 @@ function doPageNavigation(params) {
   let back = params.back ? params.back : false;
   let forward = params.forward ? params.forward : false;
   let reload = params.reload ? params.reload : false;
   let uri = params.uri ? params.uri : false;
   let eventsToListenFor = typeof(params.eventsToListenFor) != "undefined" ?
     params.eventsToListenFor : ["pageshow"];
   gExpectedEvents = typeof(params.eventsToListenFor) == "undefined" || 
     eventsToListenFor.length == 0 ? undefined : params.expectedEvents; 
+  gUnexpectedEvents = typeof(params.eventsToListenFor) == "undefined" || 
+    eventsToListenFor.length == 0 ? undefined : params.unexpectedEvents; 
   let preventBFCache = (typeof[params.preventBFCache] == "undefined") ? 
     false : params.preventBFCache;
   let waitOnly = (typeof(params.waitForEventsOnly) == "boolean" 
     && params.waitForEventsOnly);
   
   // Do some sanity checking on arguments.  
   if (back && forward)
     throw "Can't specify both back and forward";
@@ -124,16 +128,20 @@ function doPageNavigation(params) {
   for each (let anEventType in eventsToListenFor) {
     let eventFound = false;
     if ( (anEventType == "pageshow") && (!gExpectedEvents) )
       eventFound = true;
     for each (let anExpectedEvent in gExpectedEvents) {
       if (anExpectedEvent.type == anEventType)
         eventFound = true;
     }
+    for each (let anExpectedEventType in gUnexpectedEvents) {
+      if (anExpectedEventType == anEventType)
+        eventFound = true;
+    }
     if (!eventFound)
       throw "Event type " + anEventType + " is specified in " +
         "eventsToListenFor, but not in expectedEvents";
   }
   
   // If the test explicitly sets .eventsToListenFor to [], don't wait for any 
   // events.
   gFinalEvent = eventsToListenFor.length == 0 ? true : false;
@@ -255,17 +263,22 @@ function pageEventListener(event) {
   if ( (event.type == "pageshow") && 
     (gNavType == NAV_BACK || gNavType == NAV_FORWARD) ) {
     let uri = TestWindow.getBrowser().currentURI.spec;
     if (uri in gUrisNotInBFCache) {
       ok(!event.persisted, "pageshow event has .persisted = false, even " +
        "though it was loaded with .preventBFCache previously\n");
     }
   }
-  
+
+  if (typeof(gUnexpectedEvents) != "undefined") {
+    is(gUnexpectedEvents.indexOf(event.type), -1,
+       "Should not get unexpected event " + event.type);
+  }  
+
   // If no expected events were specified, mark the final event as having been 
   // triggered when a pageshow event is fired; this will allow 
   // doPageNavigation() to return.
   if ((typeof(gExpectedEvents) == "undefined") && event.type == "pageshow")
   {
     setTimeout(function() { gFinalEvent = true; }, 0);
     return;
   }
@@ -296,16 +309,28 @@ function pageEventListener(event) {
   }  
   
   if (typeof(expected.persisted) != "undefined") {
     is(event.persisted, expected.persisted, 
       "The persisted property of the " + event.type + " event on page " +
       event.originalTarget.location + " had an unexpected value"); 
   }
 
+  if ("visibilityState" in expected) {
+    is(event.originalTarget.mozVisibilityState, expected.visibilityState,
+       "The visibilityState property of the document on page " +
+       event.originalTarget.location + " had an unexpected value");
+  }
+
+  if ("hidden" in expected) {
+    is(event.originalTarget.mozHidden, expected.hidden,
+       "The hidden property of the document on page " +
+       event.originalTarget.location + " had an unexpected value");
+  }
+
   // If we're out of expected events, let doPageNavigation() return.
   if (gExpectedEvents.length == 0)
     setTimeout(function() { gFinalEvent = true; }, 0);
 }
 
 /**
  * End a test.  
  */
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/test_bug690056.xul
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=690056
+-->
+<window title="Mozilla Bug 690056"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=690056"
+     target="_blank">Mozilla Bug 690056</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 690056 **/
+SimpleTest.waitForExplicitFinish();
+window.open("bug690056_window.xul", "bug690056",
+            "chrome,width=600,height=600");
+  ]]>
+  </script>
+</window>
--- a/dom/base/ConsoleAPI.js
+++ b/dom/base/ConsoleAPI.js
@@ -202,17 +202,17 @@ ConsoleAPI.prototype = {
     let args = Array.prototype.slice.call(aArguments);
     let format = args.shift();
     // Format specification regular expression.
     let pattern = /%(\d*).?(\d*)[a-zA-Z]/g;
     let processed = format.replace(pattern, function CA_PA_substitute(spec) {
       switch (spec[spec.length-1]) {
         case "o":
         case "s":
-          return args.shift().toString();
+          return String(args.shift());
         case "d":
         case "i":
           return parseInt(args.shift());
         case "f":
           return parseFloat(args.shift());
         default:
           return spec;
       };
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -92,31 +92,39 @@ public:
 
   virtual void ActivateOrDeactivate(bool aActivate) = 0;
 
   // this is called GetTopWindowRoot to avoid conflicts with nsIDOMWindow::GetWindowRoot
   virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() = 0;
 
   virtual void SetActive(bool aActive)
   {
+    NS_PRECONDITION(IsOuterWindow(),
+                    "active state is only maintained on outer windows");
     mIsActive = aActive;
   }
 
   bool IsActive()
   {
+    NS_PRECONDITION(IsOuterWindow(),
+                    "active state is only maintained on outer windows");
     return mIsActive;
   }
 
   virtual void SetIsBackground(bool aIsBackground)
   {
+    NS_PRECONDITION(IsOuterWindow(),
+                    "background state is only maintained on outer windows");
     mIsBackground = aIsBackground;
   }
 
   bool IsBackground()
   {
+    NS_PRECONDITION(IsOuterWindow(),
+                    "background state is only maintained on outer windows");
     return mIsBackground;
   }
 
   nsIDOMEventTarget* GetChromeEventHandler() const
   {
     return mChromeEventHandler;
   }
 
--- a/dom/interfaces/core/nsIDOMDocument.idl
+++ b/dom/interfaces/core/nsIDOMDocument.idl
@@ -61,17 +61,17 @@ interface nsIDOMLocation;
  * cannot exist outside the context of a Document, the nsIDOMDocument 
  * interface also contains the factory methods needed to create these 
  * objects.
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[scriptable, uuid(3f845f32-cb34-459c-8f79-2dfaa3088bbf)]
+[scriptable, uuid(CD4CD7C3-C688-4E50-9A72-4A00EABE66AB)]
 interface nsIDOMDocument : nsIDOMNode
 {
   readonly attribute nsIDOMDocumentType         doctype;
   readonly attribute nsIDOMDOMImplementation    implementation;
   readonly attribute nsIDOMElement              documentElement;
   nsIDOMElement                 createElement(in DOMString tagName)
                                   raises(DOMException);
   nsIDOMDocumentFragment        createDocumentFragment();
@@ -406,9 +406,15 @@ interface nsIDOMDocument : nsIDOMNode
 
   /**
    * Inline event handler for readystatechange events.
    */
   [implicit_jscontext] attribute jsval onreadystatechange;
 
   [implicit_jscontext] attribute jsval onmouseenter;
   [implicit_jscontext] attribute jsval onmouseleave;
+
+  /**
+   * Visibility API implementation.
+   */
+  readonly attribute boolean mozHidden;
+  readonly attribute DOMString mozVisibilityState;
 };
--- a/dom/interfaces/core/nsIDOMXMLDocument.idl
+++ b/dom/interfaces/core/nsIDOMXMLDocument.idl
@@ -33,17 +33,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMDocument.idl"
 
-[scriptable, uuid(9f566fd8-8bd7-49eb-be8b-16fb50d00d32)]
+[scriptable, uuid(BB4D4D76-3802-4191-88E2-933BA609C4E1)]
 interface nsIDOMXMLDocument : nsIDOMDocument
 {
   // DOM Level 3 Load & Save, DocumentLS
   // http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS
   /**
    * Whether to load synchronously or asynchronously.
    * The default is async==true.
    */
--- a/dom/interfaces/html/nsIDOMHTMLDocument.idl
+++ b/dom/interfaces/html/nsIDOMHTMLDocument.idl
@@ -42,17 +42,17 @@
 /**
  * The nsIDOMHTMLDocument interface is the interface to a [X]HTML
  * document object.
  *
  * @see <http://www.whatwg.org/html/>
  */
 interface nsISelection;
 
-[scriptable, uuid(280857b8-c52c-455e-8b47-c56ad96614f7)]
+[scriptable, uuid(C94A5F14-F79F-4054-A93C-E8FF35623460)]
 interface nsIDOMHTMLDocument : nsIDOMDocument
 {
   readonly attribute DOMString            URL;
            attribute DOMString            domain;
            attribute DOMString            cookie;
   // returns "BackCompat" if we're in quirks mode,
   // or "CSS1Compat" if we're in strict mode
   readonly attribute DOMString            compatMode;
--- a/dom/interfaces/svg/nsIDOMSVGDocument.idl
+++ b/dom/interfaces/svg/nsIDOMSVGDocument.idl
@@ -34,15 +34,15 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMDocument.idl"
 
 interface nsIDOMSVGSVGElement;
 
-[scriptable, uuid(78ebe55f-631f-4b3b-9eba-c3689ff5ccbc)]
+[scriptable, uuid(B3806DF6-7ED4-4426-84E6-545EEFE5AA9A)]
 interface nsIDOMSVGDocument : nsIDOMDocument
 {
   readonly attribute DOMString domain;
   readonly attribute DOMString URL;
   readonly attribute nsIDOMSVGSVGElement rootElement;
 };
--- a/dom/locales/en-US/chrome/appstrings.properties
+++ b/dom/locales/en-US/chrome/appstrings.properties
@@ -41,16 +41,17 @@ protocolNotFound=%S is not a registered 
 connectionFailure=The connection was refused when attempting to contact %S.
 netInterrupt=The connection to %S has terminated unexpectedly. Some data may have been transferred.
 netTimeout=The operation timed out when attempting to contact %S.
 redirectLoop=Redirection limit for this URL exceeded.  Unable to load the requested page.  This may be caused by cookies that are blocked.
 confirmRepostPrompt=To display this page, the application must send information that will repeat any action (such as a search or order confirmation) that was performed earlier.
 resendButton.label=Resend
 unknownSocketType=This document cannot be displayed unless you install the Personal Security Manager (PSM). Download and install PSM and try again, or contact your system administrator.
 netReset=The document contains no data.
+notCached=This document is no longer available.
 netOffline=This document cannot be displayed while offline. To go online, uncheck Work Offline from the File menu.
 isprinting=The document cannot change while Printing or in Print Preview.
 deniedPortAccess=Access to the port number given has been disabled for security reasons.
 proxyResolveFailure=The proxy server you have configured could not be found. Please check your proxy settings and try again.
 proxyConnectFailure=The connection was refused when attempting to contact the proxy server you have configured. Please check your proxy settings and try again.
 contentEncodingError=The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.
 unsafeContentType=The page you are trying to view cannot be shown because it is contained in a file type that may not be safe to open. Please contact the website owners to inform them of this problem.
 externalProtocolTitle=External Protocol Request
--- a/dom/locales/en-US/chrome/netError.dtd
+++ b/dom/locales/en-US/chrome/netError.dtd
@@ -19,16 +19,19 @@
 <!ENTITY generic.longDesc "<p>Additional information about this problem or error is currently unavailable.</p>">
 
 <!ENTITY malformedURI.title "Invalid Address">
 <!ENTITY malformedURI.longDesc "<p>The provided address is not in a recognized format. Please check the location bar for mistakes and try again.</p>">
 
 <!ENTITY netInterrupt.title "Data Transfer Interrupted">
 <!ENTITY netInterrupt.longDesc "<p>The browser connected successfully, but the connection was interrupted while transferring information.  Please try again.</p><ul><li>Are you unable to browse other sites? Check the computer's network connection.</li><li>Still having trouble? Consult your network administrator or Internet provider for assistance.</li></ul>">
 
+<!ENTITY notCached.title "Document Expired">
+<!ENTITY notCached.longDesc "<p>The requested document is not available in the browser's cache.</p><ul><li>As a security precuation, the browser does not automatically re-request sensitive documents.</li><li>Click Try Again to re-request the document from the website.</li></ul>">
+
 <!ENTITY netOffline.title "Offline Mode">
 <!ENTITY netOffline.longDesc2 "<p>The browser is operating in its offline mode and cannot connect to the requested item.</p><ul><li>Is the computer connected to an active network?</li><li>Press &quot;Try Again&quot; to switch to online mode and reload the page.</li></ul>">
 
 <!ENTITY contentEncodingError.title "Content Encoding Error">
 <!ENTITY contentEncodingError.longDesc "<p>The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.</p><ul><li>Please contact the website owners to inform them of this problem.</li></ul>">
 
 <!ENTITY unsafeContentType.title "Unsafe File Type">
 <!ENTITY unsafeContentType.longDesc "
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -155,19 +155,16 @@ NPObjWrapper_GetProperty(JSContext *cx, 
 static JSBool
 NPObjWrapper_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                           jsval *statep, jsid *idp);
 
 static JSBool
 NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
                         JSObject **objp);
 
-static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
-
 static void
 NPObjWrapper_Finalize(JSContext *cx, JSObject *obj);
 
 static JSBool
 NPObjWrapper_Call(JSContext *cx, uintN argc, jsval *vp);
 
 static JSBool
 NPObjWrapper_Construct(JSContext *cx, uintN argc, jsval *vp);
@@ -178,17 +175,17 @@ CreateNPObjectMember(NPP npp, JSContext 
 
 static JSClass sNPObjectJSWrapperClass =
   {
     NPRUNTIME_JSCLASS_NAME,
     JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
     NPObjWrapper_AddProperty, NPObjWrapper_DelProperty,
     NPObjWrapper_GetProperty, NPObjWrapper_SetProperty,
     (JSEnumerateOp)NPObjWrapper_newEnumerate,
-    (JSResolveOp)NPObjWrapper_NewResolve, NPObjWrapper_Convert,
+    (JSResolveOp)NPObjWrapper_NewResolve, JS_ConvertStub,
     NPObjWrapper_Finalize, nsnull, nsnull, NPObjWrapper_Call,
     NPObjWrapper_Construct, nsnull, nsnull
   };
 
 typedef struct NPObjectMemberPrivate {
     JSObject *npobjWrapper;
     jsval fieldValue;
     NPIdentifier methodName;
@@ -1678,28 +1675,16 @@ NPObjWrapper_NewResolve(JSContext *cx, J
 
     return fnc != nsnull;
   }
 
   // no property or method
   return JS_TRUE;
 }
 
-static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
-{
-  // The sole reason we implement this hook is to prevent the JS
-  // engine from calling valueOf() on NPObject's. Some NPObject's may
-  // actually implement a method named valueOf, but it's unlikely to
-  // behave as the JS engine expects it to. IOW, this is an empty hook
-  // that overrides what the default hook does.
-
-  return JS_TRUE;
-}
-
 static void
 NPObjWrapper_Finalize(JSContext *cx, JSObject *obj)
 {
   NPObject *npobj = (NPObject *)::JS_GetPrivate(cx, obj);
   if (npobj) {
     if (sNPObjWrappers.ops) {
       PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_REMOVE);
     }
@@ -2190,16 +2175,19 @@ NPObjectMember_Convert(JSContext *cx, JS
 
   switch (type) {
   case JSTYPE_VOID:
   case JSTYPE_STRING:
   case JSTYPE_NUMBER:
   case JSTYPE_BOOLEAN:
   case JSTYPE_OBJECT:
     *vp = memberPrivate->fieldValue;
+    if (!JSVAL_IS_PRIMITIVE(*vp)) {
+      return JS_ConvertStub(cx, JSVAL_TO_OBJECT(*vp), type, vp);
+    }
     return JS_TRUE;
   case JSTYPE_FUNCTION:
     // Leave this to NPObjectMember_Call.
     return JS_TRUE;
   default:
     NS_ERROR("illegal operation on JSObject prototype object");
     return JS_FALSE;
   }
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -41,16 +41,17 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = dom/plugins/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _MOCHITEST_FILES = \
   utils.js \
+  test_defaultValue.html \
   test_getauthenticationinfo.html \
   test_npobject_getters.html \
   test_npruntime_npnevaluate.html \
   test_npruntime_npninvoke.html \
   test_npruntime_npninvokedefault.html \
   test_npruntime_identifiers.html \
   npruntime_identifiers_subpage.html \
   loremipsum.txt \
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_defaultValue.html
@@ -0,0 +1,36 @@
+<html>
+  <head>
+    <title>NPObject [[DefaultValue]] implementation</title>
+
+    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  </head>
+
+  <body onload="run()">
+
+    <embed id="plugin" type="application/x-test" wmode="window"></embed>
+
+    <script class="testbody" type="application/javascript">
+      SimpleTest.waitForExplicitFinish();
+
+      function run() {
+        var plugin = document.getElementById("plugin");
+        var pluginProto = Object.getPrototypeOf(plugin);
+
+        plugin.propertyAndMethod = {};
+        plugin.propertyAndMethod + "baz";
+        ok(true, "|plugin.propertyAndMethod + \"baz\"| shouldn't assert");
+        pluginProto.propertyAndMethod = {};
+        pluginProto.propertyAndMethod + "quux";
+        ok(true, "|pluginProto.propertyAndMethod + \"quux\"| shouldn't assert");
+
+        plugin + "foo";
+        ok(true, "|plugin + \"foo\"| shouldn't assert");
+        pluginProto + "bar";
+        ok(true, "|pluginProto + \"bar\"| shouldn't assert");
+
+        SimpleTest.finish();
+      }
+    </script>
+  </body>
+</html>
--- a/dom/plugins/test/mochitest/test_npruntime_identifiers.html
+++ b/dom/plugins/test/mochitest/test_npruntime_identifiers.html
@@ -4,29 +4,25 @@
   <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>
 
-  <iframe id="subframe" src="npruntime_identifiers_subpage.html"></iframe>
-
   <script class="testbody" type="application/javascript">
   ////
   // This test exercises NP identifiers by querying the reflector to make sure
   // that identifiers are translated to values correctly.
   
   SimpleTest.waitForExplicitFinish();
 
   var testsRun = 0;
 
-  document.getElementById('subframe').addEventListener('load', doTest, false);
-
   function doTest() {
     SpecialPowers.gc();
 
     var reflector = document.getElementById("subframe").contentDocument.getElementById("plugin1").getReflector();
 
     var i, prop, randomnumber;
 
     for (i = 0; i < 20; ++i) {
@@ -51,10 +47,13 @@
     if (testsRun == 3) {
       SimpleTest.finish();
     }
     else {
       document.getElementById('subframe').contentWindow.location.reload(true);
     }
   }
   </script>
+
+  <iframe id="subframe" src="npruntime_identifiers_subpage.html" onload="doTest()"></iframe>
+
 </body>
 </html>
--- a/dom/tests/browser/browser_ConsoleAPITests.js
+++ b/dom/tests/browser/browser_ConsoleAPITests.js
@@ -215,16 +215,20 @@ function observeConsoleTest() {
   win.console.log("%d, %s, %l");
   expect("log", "%a %b %c");
   win.console.log("%a %b %c");
   expect("log", "%a %b %c", "a", "b");
   win.console.log("%a %b %c", "a", "b");
   expect("log", "2, a, %l", 3);
   win.console.log("%d, %s, %l", 2, "a", 3);
 
+  // bug #692550 handle null and undefined
+  expect("log", "null, undefined");
+  win.console.log("%s, %s", null, undefined);
+
   expect("dir", win.toString());
   win.console.dir(win);
 
   expect("error", "arg");
   win.console.error("arg");
 }
 
 function consoleAPISanityTest() {
--- a/dom/workers/ListenerManager.cpp
+++ b/dom/workers/ListenerManager.cpp
@@ -35,17 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "ListenerManager.h"
 
 #include "jsapi.h"
 #include "jscntxt.h"
-#include "jsvector.h"
+#include "js/Vector.h"
 
 #include "Events.h"
 
 using mozilla::dom::workers::events::ListenerManager;
 
 namespace {
 
 struct Listener;
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -74,16 +74,17 @@ abstract public class GeckoApp
     public static final String ACTION_ALERT_CLICK = "org.mozilla.gecko.ACTION_ALERT_CLICK";
     public static final String ACTION_ALERT_CLEAR = "org.mozilla.gecko.ACTION_ALERT_CLEAR";
     public static final String ACTION_WEBAPP      = "org.mozilla.gecko.WEBAPP";
     public static final String ACTION_DEBUG       = "org.mozilla.gecko.DEBUG";
     public static final String ACTION_BOOKMARK    = "org.mozilla.gecko.BOOKMARK";
 
     public static AbsoluteLayout mainLayout;
     public static GeckoSurfaceView surfaceView;
+    public static SurfaceView cameraView;
     public static GeckoApp mAppContext;
     public static boolean mFullscreen = false;
     public static File sGREDir = null;
     static Thread mLibLoadThread = null;
     public Handler mMainHandler;
     private IntentFilter mConnectivityFilter;
     private BroadcastReceiver mConnectivityReceiver;
 
@@ -372,27 +373,36 @@ abstract public class GeckoApp
 
         if (sGREDir == null)
             sGREDir = new File(this.getApplicationInfo().dataDir);
 
         getWindow().setFlags(mFullscreen ?
                              WindowManager.LayoutParams.FLAG_FULLSCREEN : 0,
                              WindowManager.LayoutParams.FLAG_FULLSCREEN);
 
+        if (cameraView == null) {
+            cameraView = new SurfaceView(this);
+            cameraView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
+        }
+
         if (surfaceView == null)
             surfaceView = new GeckoSurfaceView(this);
         else
             mainLayout.removeAllViews();
 
         mainLayout = new AbsoluteLayout(this);
         mainLayout.addView(surfaceView,
                            new AbsoluteLayout.LayoutParams(AbsoluteLayout.LayoutParams.MATCH_PARENT, // level 8
                                                            AbsoluteLayout.LayoutParams.MATCH_PARENT,
                                                            0,
                                                            0));
+
+        // Some phones (eg. nexus S) need at least a 8x16 preview size
+        mainLayout.addView(cameraView, new AbsoluteLayout.LayoutParams(8, 16, 0, 0));
+
         setContentView(mainLayout,
                        new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
                                                   ViewGroup.LayoutParams.FILL_PARENT));
 
         mConnectivityFilter = new IntentFilter();
         mConnectivityFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         mConnectivityReceiver = new GeckoConnectivityReceiver();
 
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -1526,17 +1526,17 @@ public class GeckoAppShell
     }
     
     public static android.hardware.Camera sCamera = null;
     
     static native void cameraCallbackBridge(byte[] data);
 
     static int kPreferedFps = 25;
     static byte[] sCameraBuffer = null;
- 
+
     static int[] initCamera(String aContentType, int aCamera, int aWidth, int aHeight) {
         Log.i("GeckoAppJava", "initCamera(" + aContentType + ", " + aWidth + "x" + aHeight + ") on thread " + Thread.currentThread().getId());
 
         // [0] = 0|1 (failure/success)
         // [1] = width
         // [2] = height
         // [3] = fps
         int[] result = new int[4];
@@ -1580,16 +1580,24 @@ public class GeckoAppShell
                 android.hardware.Camera.Size size = sit.next();
                 if (Math.abs(size.width * size.height - aWidth * aHeight) < sizeDelta) {
                     sizeDelta = Math.abs(size.width * size.height - aWidth * aHeight);
                     params.setPreviewSize(size.width, size.height);
                     bufferSize = size.width * size.height;
                 }
             }
 
+            try {
+                sCamera.setPreviewDisplay(GeckoApp.cameraView.getHolder());
+            } catch(IOException e) {
+                Log.e("GeckoAppJava", "Error setPreviewDisplay:", e);
+            } catch(RuntimeException e) {
+                Log.e("GeckoAppJava", "Error setPreviewDisplay:", e);
+            }
+
             sCamera.setParameters(params);
             sCameraBuffer = new byte[(bufferSize * 12) / 8];
             sCamera.addCallbackBuffer(sCameraBuffer);
             sCamera.setPreviewCallbackWithBuffer(new android.hardware.Camera.PreviewCallback() {
                 public void onPreviewFrame(byte[] data, android.hardware.Camera camera) {
                     cameraCallbackBridge(data);
                     if (sCamera != null)
                         sCamera.addCallbackBuffer(sCameraBuffer);
--- a/embedding/components/windowwatcher/src/Makefile.in
+++ b/embedding/components/windowwatcher/src/Makefile.in
@@ -41,26 +41,26 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= embedcomponents
 LIBRARY_NAME	= windowwatcher_s
 LIBXUL_LIBRARY	= 1
 
-
 CPPSRCS		= \
-                  nsWWJSUtils.cpp \
                   nsWindowWatcher.cpp  \
                   nsAutoWindowStateHelper.cpp \
                   $(NULL)
 
 ifdef MOZ_XUL
 CPPSRCS		+= nsDialogParamBlock.cpp \
 		   $(NULL)
 endif
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
+# For nsJSUtils
+LOCAL_INCLUDES += -I$(topsrcdir)/dom/base
+
 include $(topsrcdir)/config/rules.mk
-
deleted file mode 100644
--- a/embedding/components/windowwatcher/src/nsWWJSUtils.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/* This file is a small subset of nsJSUtils utility functions,
-   from the dom directory.
-*/
-
-#include "nsCOMPtr.h"
-#include "nsIScriptContext.h"
-#include "nsIScriptGlobalObject.h"
-#include "nsWWJSUtils.h"
-#include "nsIXPConnect.h"
-#include "nsDOMJSUtils.h"
-
-nsIScriptGlobalObject *
-nsWWJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj)
-{
-  nsISupports* supports;
-  JSClass* clazz;
-  JSObject* parent;
-  JSObject* glob = aObj; // starting point for search
-
-  if (!glob)
-    return nsnull;
-
-  while (nsnull != (parent = JS_GetParent(aContext, glob)))
-    glob = parent;
-
-  clazz = JS_GET_CLASS(aContext, glob);
-
-  if (!clazz ||
-      !(clazz->flags & JSCLASS_HAS_PRIVATE) ||
-      !(clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) ||
-      !(supports = (nsISupports*) JS_GetPrivate(aContext, glob))) {
-    return nsnull;
-  }
- 
-  nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(supports));
-  NS_ENSURE_TRUE(wrapper, nsnull);
-
-  nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper));
-
-  // This will return a pointer to something we're about to release,
-  // but that's ok here.
-  return sgo;
-}
-
-nsIScriptContext *
-nsWWJSUtils::GetDynamicScriptContext(JSContext *aContext)
-{
-  return GetScriptContextFromJSContext(aContext);
-}
-
-nsIScriptGlobalObject *
-nsWWJSUtils::GetDynamicScriptGlobal(JSContext* aContext)
-{
-  nsIScriptContext *scriptCX = GetDynamicScriptContext(aContext);
-  if (!scriptCX)
-    return nsnull;
-  return scriptCX->GetGlobalObject();
-}
-
-nsIScriptContext *
-nsWWJSUtils::GetStaticScriptContext(JSContext* aContext,
-                                    JSObject* aObj)
-{
-  nsIScriptGlobalObject *nativeGlobal = GetStaticScriptGlobal(aContext, aObj);
-  if (!nativeGlobal)    
-    return nsnull;
-  return nativeGlobal->GetContext();
-}  
-
deleted file mode 100644
--- a/embedding/components/windowwatcher/src/nsWWJSUtils.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2001
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nsWWJSUtils_h__
-#define nsWWJSUtils_h__
-
-/**
- * Utility functions copied from nsJSUtils in dom/src/base.
- */
-
-#include "nsISupports.h"
-#include "jsapi.h"
-
-class nsIScriptContext;
-class nsIScriptGlobalObject;
-
-class nsWWJSUtils {
-public:
-  static nsIScriptGlobalObject *GetStaticScriptGlobal(JSContext* aContext,
-                                                      JSObject* aObj);
-
-  static nsIScriptContext *GetStaticScriptContext(JSContext* aContext,
-                                                  JSObject* aObj);
-
-  static nsIScriptGlobalObject *GetDynamicScriptGlobal(JSContext *aContext);
-
-  static nsIScriptContext *GetDynamicScriptContext(JSContext *aContext);
-};
-
-#endif /* nsWWJSUtils_h__ */
--- a/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
+++ b/embedding/components/windowwatcher/src/nsWindowWatcher.cpp
@@ -39,17 +39,17 @@
 
 //#define USEWEAKREFS // (haven't quite figured that out yet)
 
 #include "nsWindowWatcher.h"
 #include "nsAutoWindowStateHelper.h"
 
 #include "nsCRT.h"
 #include "nsNetUtil.h"
-#include "nsWWJSUtils.h"
+#include "nsJSUtils.h"
 #include "plstr.h"
 
 #include "nsIBaseWindow.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellLoadInfo.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocumentLoader.h"
@@ -311,17 +311,17 @@ nsresult JSContextAutoPopper::Push(JSCon
     // Get the safe context if we're not provided one.
     if (!cx && NS_FAILED(mService->GetSafeJSContext(&cx))) {
       cx = nsnull;
     }
 
     // Save cx in mContext to indicate need to pop.
     if (cx && NS_SUCCEEDED(mService->Push(cx))) {
       mContext = cx;
-      mContextKungFuDeathGrip = nsWWJSUtils::GetDynamicScriptContext(cx);
+      mContextKungFuDeathGrip = nsJSUtils::GetDynamicScriptContext(cx);
     }
   }
   return mContext ? NS_OK : NS_ERROR_FAILURE;
 }
 
 /****************************************************************
  *********************** nsWindowWatcher ************************
  ****************************************************************/
@@ -920,17 +920,17 @@ nsWindowWatcher::OpenWindowJSInternal(ns
 
     // get the calling context off the JS context stack
     nsCOMPtr<nsIJSContextStack> stack = do_GetService(sJSStackContractID);
 
     JSContext* ccx = nsnull;
 
     // get its document, if any
     if (stack && NS_SUCCEEDED(stack->Peek(&ccx)) && ccx) {
-      nsIScriptGlobalObject *sgo = nsWWJSUtils::GetDynamicScriptGlobal(ccx);
+      nsIScriptGlobalObject *sgo = nsJSUtils::GetDynamicScriptGlobal(ccx);
 
       nsCOMPtr<nsPIDOMWindow> w(do_QueryInterface(sgo));
       if (w) {
         /* use the URL from the *extant* document, if any. The usual accessor
            GetDocument will synchronously create an about:blank document if
            it has no better answer, and we only care about a real document.
            Also using GetDocument to force document creation seems to
            screw up focus in the hidden window; see bug 36016.
@@ -1369,17 +1369,17 @@ nsWindowWatcher::URIfromURL(const char *
 {
   nsCOMPtr<nsIDOMWindow> baseWindow;
 
   /* build the URI relative to the calling JS Context, if any.
      (note this is the same context used to make the security check
      in nsGlobalWindow.cpp.) */
   JSContext *cx = GetJSContextFromCallStack();
   if (cx) {
-    nsIScriptContext *scriptcx = nsWWJSUtils::GetDynamicScriptContext(cx);
+    nsIScriptContext *scriptcx = nsJSUtils::GetDynamicScriptContext(cx);
     if (scriptcx) {
       baseWindow = do_QueryInterface(scriptcx->GetGlobalObject());
     }
   }
 
   // failing that, build it relative to the parent window, if possible
   if (!baseWindow)
     baseWindow = aParent;
@@ -1712,17 +1712,17 @@ nsWindowWatcher::GetCallerTreeItem(nsIDo
   if (stack) {
     stack->Peek(&cx);
   }
 
   nsIDocShellTreeItem* callerItem = nsnull;
 
   if (cx) {
     nsCOMPtr<nsIWebNavigation> callerWebNav =
-      do_GetInterface(nsWWJSUtils::GetDynamicScriptGlobal(cx));
+      do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
 
     if (callerWebNav) {
       CallQueryInterface(callerWebNav, &callerItem);
     }
   }
 
   if (!callerItem) {
     NS_IF_ADDREF(callerItem = aParentItem);
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -142,18 +142,16 @@ ThebesLayerBufferOGL::RenderTo(const nsI
   }
 
   PRInt32 passes = mTexImageOnWhite ? 2 : 1;
   for (PRInt32 pass = 1; pass <= passes; ++pass) {
     LayerProgram *program;
 
     if (passes == 2) {
       ComponentAlphaTextureLayerProgram *alphaProgram;
-      NS_ASSERTION(!mTexImage->IsRGB() && !mTexImageOnWhite->IsRGB(),
-                   "Only BGR image surported with component alpha (currently!)");
       if (pass == 1) {
         alphaProgram = aManager->GetComponentAlphaPass1LayerProgram();
         gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_ONE_MINUS_SRC_COLOR,
                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
       } else {
         alphaProgram = aManager->GetComponentAlphaPass2LayerProgram();
         gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE,
                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -770,17 +770,16 @@ TiledTextureImage::DirectUpdate(gfxASurf
         if (tileRegion.IsEmpty())
             continue;
         tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
         result &= mImages[i]->DirectUpdate(aSurf,
                                            tileRegion,
                                            aFrom + nsIntPoint(xPos, yPos));
     }
     mShaderType = mImages[0]->GetShaderProgramType();
-    mIsRGBFormat = mImages[0]->IsRGB();
     mTextureState = Valid;
     return result;
 }
 
 void
 TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
 {
     if (mTextureState != Valid) {
@@ -883,17 +882,16 @@ void
 TiledTextureImage::EndUpdate()
 {
     NS_ASSERTION(mInUpdate, "EndUpdate not in update");
     if (!mUpdateSurface) { // update was to a single TextureImage
         mImages[mCurrentImage]->EndUpdate();
         mInUpdate = PR_FALSE;
         mTextureState = Valid;
         mShaderType = mImages[mCurrentImage]->GetShaderProgramType();
-        mIsRGBFormat = mImages[mCurrentImage]->IsRGB();
         return;
     }
 
     // upload tiles from temp surface
     for (unsigned i = 0; i < mImages.Length(); i++) {
         int xPos = (i % mColumns) * mTileSize;
         int yPos = (i / mColumns) * mTileSize;
         nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize());
@@ -911,17 +909,16 @@ TiledTextureImage::EndUpdate()
         ctx->SetSource(mUpdateSurface, gfxPoint(-xPos, -yPos));
         ctx->Paint();
         mImages[i]->EndUpdate();
     }
 
     mUpdateSurface = nsnull;
     mInUpdate = PR_FALSE;
     mShaderType = mImages[0]->GetShaderProgramType();
-    mIsRGBFormat = mImages[0]->IsRGB();
     mTextureState = Valid;
 }
 
 void TiledTextureImage::BeginTileIteration()
 {
     mCurrentImage = 0;
 }
 
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -316,18 +316,16 @@ public:
     virtual already_AddRefed<gfxASurface> GetBackingSurface()
     { return NULL; }
 
     const nsIntSize& GetSize() const { return mSize; }
     ContentType GetContentType() const { return mContentType; }
     virtual bool InUpdate() const = 0;
     GLenum GetWrapMode() const { return mWrapMode; }
 
-    bool IsRGB() const { return mIsRGBFormat; }
-
     void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
 
 protected:
     friend class GLContext;
 
     /**
      * After the ctor, the TextureImage is invalid.  Implementations
      * must allocate resources successfully before returning the new
@@ -335,29 +333,27 @@ protected:
      * clients must not be given partially-constructed TextureImages.
      */
     TextureImage(const nsIntSize& aSize,
                  GLenum aWrapMode, ContentType aContentType,
                  bool aIsRGB = false)
         : mSize(aSize)
         , mWrapMode(aWrapMode)
         , mContentType(aContentType)
-        , mIsRGBFormat(aIsRGB)
     {}
 
     /**
      * Applies this TextureImage's filter, assuming that its texture is
      * the currently bound texture.
      */
     virtual void ApplyFilter() = 0;
 
     nsIntSize mSize;
     GLenum mWrapMode;
     ContentType mContentType;
-    bool mIsRGBFormat;
     ShaderProgramType mShaderType;
     gfxPattern::GraphicsFilter mFilter;
 };
 
 /**
  * BasicTextureImage is the baseline TextureImage implementation ---
  * it updates its texture by allocating a scratch buffer for the
  * client to draw into, then using glTexSubImage2D() to upload the new
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -1202,17 +1202,17 @@ public:
             }
             Resize(aSize);
         } else {
             // Convert RGB24 to either ARGB32 on mobile.  We can't
             // generate GL_RGB data, so we'll always have an alpha byte
             // for RGB24.  No easy way to upload that to GL.
             // 
             // Note that if we start using RGB565 here, we'll need to
-            // watch for a) setting mIsRGBFormat to TRUE; and b) getting
+            // watch for a) setting the correct format; and b) getting
             // the stride right.
             if (mUpdateFormat == gfxASurface::ImageFormatRGB24) {
                 mUpdateFormat = gfxASurface::ImageFormatARGB32;
             }
             // We currently always use BGRA type textures
             mShaderType = BGRALayerProgramType;
         }
     }
@@ -1270,19 +1270,16 @@ public:
                 mUpdateSurface = GetLockSurface();
             } else {
                 mUpdateSurface = mBackingSurface;
             }
 
             return mUpdateSurface;
         }
 
-        // if we get this far, then we're using Cairo's byte order
-        mIsRGBFormat = PR_FALSE;
-
         //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
 
         mUpdateSurface =
             new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
                                 mUpdateFormat);
 
         mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
 
@@ -1641,17 +1638,16 @@ public:
 
             if (!BindTexImage()) {
                 printf_stderr("ProviderEGL Failed to bind teximage: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
                 return PR_FALSE;
             }
         }
 
         mBackingSurface = xsurface;
-        mIsRGBFormat = PR_TRUE;
 #endif
 
         return mBackingSurface != nsnull;
     }
 
 protected:
     typedef gfxASurface::gfxImageFormat ImageFormat;
 
--- a/gfx/thebes/gfx3DMatrix.cpp
+++ b/gfx/thebes/gfx3DMatrix.cpp
@@ -796,20 +796,31 @@ gfxRect gfx3DMatrix::ProjectRectBounds(c
     max_y = max(points[i].y, max_y);
   }
 
   return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
 }
 
 gfxPoint3D gfx3DMatrix::GetNormalVector() const
 {
-    // Define a plane in transformed space as the transformations
-    // of 3 points on the z=0 screen plane.
-    gfxPoint3D a = Transform3D(gfxPoint3D(0, 0, 0));
-    gfxPoint3D b = Transform3D(gfxPoint3D(0, 1, 0));
-    gfxPoint3D c = Transform3D(gfxPoint3D(1, 0, 0));
+  // Define a plane in transformed space as the transformations
+  // of 3 points on the z=0 screen plane.
+  gfxPoint3D a = Transform3D(gfxPoint3D(0, 0, 0));
+  gfxPoint3D b = Transform3D(gfxPoint3D(0, 1, 0));
+  gfxPoint3D c = Transform3D(gfxPoint3D(1, 0, 0));
+
+  // Convert to two vectors on the surface of the plane.
+  gfxPoint3D ab = b - a;
+  gfxPoint3D ac = c - a;
 
-    // Convert to two vectors on the surface of the plane.
-    gfxPoint3D ab = b - a;
-    gfxPoint3D ac = c - a;
+  return ac.CrossProduct(ab);
+}
 
-    return ac.CrossProduct(ab);
+bool gfx3DMatrix::IsBackfaceVisible() const
+{
+  // Inverse()._33 < 0;
+  gfxFloat det = Determinant();
+  float _33 = _12*_24*_41 - _14*_22*_41 +
+              _14*_21*_42 - _11*_24*_42 -
+              _12*_21*_44 + _11*_22*_44;
+  return (_33 * det) < 0;
 }
+
--- a/gfx/thebes/gfx3DMatrix.h
+++ b/gfx/thebes/gfx3DMatrix.h
@@ -302,16 +302,22 @@ public:
 
   /**
    * Returns a unit vector that is perpendicular to the plane formed
    * by transform the screen plane (z=0) by this matrix.
    */
   gfxPoint3D GetNormalVector() const;
 
   /**
+   * Returns true if a plane transformed by this matrix will
+   * have it's back face visible.
+   */
+  bool IsBackfaceVisible() const;
+
+  /**
    * Check if matrix is singular (no inverse exists).
    */
   bool IsSingular() const;
 
   /**
    * Create a translation matrix.
    *
    * \param aX Translation on X-axis.
--- a/ipc/glue/WindowsMessageLoop.cpp
+++ b/ipc/glue/WindowsMessageLoop.cpp
@@ -96,16 +96,20 @@ using namespace mozilla::ipc::windows;
  * modal UI related api calls block an RPC in-call in the child. To prevent
  * windows from freezing, and to allow concurrent processing of critical
  * events (such as painting), we spin a native event dispatch loop while
  * these in-calls are blocked.
  */
 
 // pulled from widget's nsAppShell
 extern const PRUnichar* kAppShellEventId;
+#if defined(ACCESSIBILITY)
+// pulled from accessibility's win utils
+extern const PRUnichar* kPropNameTabContent;
+#endif
 
 namespace {
 
 const wchar_t kOldWndProcProp[] = L"MozillaIPCOldWndProc";
 
 // This isn't defined before Windows XP.
 enum { WM_XP_THEMECHANGED = 0x031A };
 
@@ -374,16 +378,24 @@ WindowIsDeferredWindow(HWND hWnd)
 
   PRUnichar buffer[256] = { 0 };
   int length = GetClassNameW(hWnd, (wchar_t*)buffer, sizeof(buffer) - 1);
   if (length <= 0) {
     NS_WARNING("Failed to get class name!");
     return false;
   }
 
+#if defined(ACCESSIBILITY)
+  // Tab content creates a window that responds to accessible WM_GETOBJECT
+  // calls. This window can safely be ignored.
+  if (::GetPropW(hWnd, kPropNameTabContent)) {
+    return false;
+  }
+#endif
+
   // Common mozilla windows we must defer messages to.
   nsDependentString className(buffer, length);
   if (StringBeginsWith(className, NS_LITERAL_STRING("Mozilla")) ||
       StringBeginsWith(className, NS_LITERAL_STRING("Gecko")) ||
       className.EqualsLiteral("nsToolkitClass") ||
       className.EqualsLiteral("nsAppShell:EventWindowClass")) {
     return true;
   }
--- a/js/jetpack/JetpackActorCommon.cpp
+++ b/js/jetpack/JetpackActorCommon.cpp
@@ -32,20 +32,20 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "base/basictypes.h"
-#include "jscntxt.h"
 
 #include "jsapi.h"
-#include "jshashtable.h"
+#include "jscntxt.h"
+#include "js/HashTable.h"
 
 #include "mozilla/jetpack/JetpackActorCommon.h"
 #include "mozilla/jetpack/PJetpack.h"
 #include "mozilla/jetpack/PHandleParent.h"
 #include "mozilla/jetpack/PHandleChild.h"
 #include "mozilla/jetpack/Handle.h"
 
 #include "nsJSUtils.h"
rename from js/src/jshashtable.h
rename to js/public/HashTable.h
--- a/js/src/jshashtable.h
+++ b/js/public/HashTable.h
@@ -38,19 +38,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 ***** */
 
 #ifndef jshashtable_h_
 #define jshashtable_h_
 
-#include "jsalloc.h"
-#include "jstl.h"
-#include "jsutil.h"
+#include "TemplateLib.h"
+#include "Utility.h"
 
 namespace js {
 
 /* Integral types for all hash functions. */
 typedef uint32 HashNumber;
 
 /*****************************************************************************/
 
new file mode 100644
--- /dev/null
+++ b/js/public/TemplateLib.h
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Luke Wagner <luke@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef js_template_lib_h__
+#define js_template_lib_h__
+
+#include "mozilla/Types.h"
+#include "jsstdint.h"
+
+/*
+ * Library of reusable template meta-functions (that is, functions on types and
+ * compile-time values). Meta-functions are placed inside the 'tl' namespace to
+ * avoid conflict with non-meta functions that logically have the same name
+ * (e.g., js::tl::Min vs. js::Min).
+ */
+
+namespace js {
+namespace tl {
+
+/* Compute min/max/clamp. */
+template <size_t i, size_t j> struct Min {
+    static const size_t result = i < j ? i : j;
+};
+template <size_t i, size_t j> struct Max {
+    static const size_t result = i > j ? i : j;
+};
+template <size_t i, size_t min, size_t max> struct Clamp {
+    static const size_t result = i < min ? min : (i > max ? max : i);
+};
+
+/* Compute x^y. */
+template <size_t x, size_t y> struct Pow {
+    static const size_t result = x * Pow<x, y - 1>::result;
+};
+template <size_t x> struct Pow<x,0> {
+    static const size_t result = 1;
+};
+
+/* Compute floor(log2(i)). */
+template <size_t i> struct FloorLog2 {
+    static const size_t result = 1 + FloorLog2<i / 2>::result;
+};
+template <> struct FloorLog2<0> { /* Error */ };
+template <> struct FloorLog2<1> { static const size_t result = 0; };
+
+/* Compute ceiling(log2(i)). */
+template <size_t i> struct CeilingLog2 {
+    static const size_t result = FloorLog2<2 * i - 1>::result;
+};
+
+/* Round up to the nearest power of 2. */
+template <size_t i> struct RoundUpPow2 {
+    static const size_t result = 1u << CeilingLog2<i>::result;
+};
+template <> struct RoundUpPow2<0> {
+    static const size_t result = 1;
+};
+
+/* Compute the number of bits in the given unsigned type. */
+template <class T> struct BitSize {
+    static const size_t result = sizeof(T) * JS_BITS_PER_BYTE;
+};
+
+/* Allow Assertions by only including the 'result' typedef if 'true'. */
+template <bool> struct StaticAssert {};
+template <> struct StaticAssert<true> { typedef int result; };
+
+/* Boolean test for whether two types are the same. */
+template <class T, class U> struct IsSameType {
+    static const bool result = false;
+};
+template <class T> struct IsSameType<T,T> {
+    static const bool result = true;
+};
+
+/*
+ * Produce an N-bit mask, where N <= BitSize<size_t>::result.  Handle the
+ * language-undefined edge case when N = BitSize<size_t>::result.
+ */
+template <size_t N> struct NBitMask {
+    typedef typename StaticAssert<N < BitSize<size_t>::result>::result _;
+    static const size_t result = (size_t(1) << N) - 1;
+};
+template <> struct NBitMask<BitSize<size_t>::result> {
+    static const size_t result = size_t(-1);
+};
+
+/*
+ * For the unsigned integral type size_t, compute a mask M for N such that
+ * for all X, !(X & M) implies X * N will not overflow (w.r.t size_t)
+ */
+template <size_t N> struct MulOverflowMask {
+    static const size_t result =
+        ~NBitMask<BitSize<size_t>::result - CeilingLog2<N>::result>::result;
+};
+template <> struct MulOverflowMask<0> { /* Error */ };
+template <> struct MulOverflowMask<1> { static const size_t result = 0; };
+
+/*
+ * Generate a mask for T such that if (X & sUnsafeRangeSizeMask), an X-sized
+ * array of T's is big enough to cause a ptrdiff_t overflow when subtracting
+ * a pointer to the end of the array from the beginning.
+ */
+template <class T> struct UnsafeRangeSizeMask {
+    /*
+     * The '2' factor means the top bit is clear, sizeof(T) converts from
+     * units of elements to bytes.
+     */
+    static const size_t result = MulOverflowMask<2 * sizeof(T)>::result;
+};
+
+/* Return T stripped of any const-ness. */
+template <class T> struct StripConst          { typedef T result; };
+template <class T> struct StripConst<const T> { typedef T result; };
+
+/*
+ * Traits class for identifying POD types. Until C++0x, there is no automatic
+ * way to detect PODs, so for the moment it is done manually.
+ */
+template <class T> struct IsPodType                 { static const bool result = false; };
+template <> struct IsPodType<char>                  { static const bool result = true; };
+template <> struct IsPodType<signed char>           { static const bool result = true; };
+template <> struct IsPodType<unsigned char>         { static const bool result = true; };
+template <> struct IsPodType<short>                 { static const bool result = true; };
+template <> struct IsPodType<unsigned short>        { static const bool result = true; };
+template <> struct IsPodType<int>                   { static const bool result = true; };
+template <> struct IsPodType<unsigned int>          { static const bool result = true; };
+template <> struct IsPodType<long>                  { static const bool result = true; };
+template <> struct IsPodType<unsigned long>         { static const bool result = true; };
+template <> struct IsPodType<long long>             { static const bool result = true; };
+template <> struct IsPodType<unsigned long long>    { static const bool result = true; };
+template <> struct IsPodType<float>                 { static const bool result = true; };
+template <> struct IsPodType<double>                { static const bool result = true; };
+template <> struct IsPodType<wchar_t>               { static const bool result = true; };
+template <typename T> struct IsPodType<T *>         { static const bool result = true; };
+
+/* Return the size/end of an array without using macros. */
+template <class T, size_t N> inline T *ArraySize(T (&)[N]) { return N; }
+template <class T, size_t N> inline T *ArrayEnd(T (&arr)[N]) { return arr + N; }
+
+template <bool cond, typename T, T v1, T v2> struct If        { static const T result = v1; };
+template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T result = v2; };
+
+} /* namespace tl */
+} /* namespace js */
+
+#endif  /* js_template_lib_h__ */
new file mode 100644
--- /dev/null
+++ b/js/public/Utility.h
@@ -0,0 +1,945 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=99 ft=cpp:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla SpiderMonkey JavaScript code.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef js_utility_h__
+#define js_utility_h__
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "mozilla/Util.h"
+
+#ifdef __cplusplus
+
+/* The public JS engine namespace. */
+namespace JS {}
+
+/* The mozilla-shared reusable template/utility namespace. */
+namespace mozilla {}
+
+/* The private JS engine namespace. */
+namespace js {
+
+/* The private namespace is a superset of the public/shared namespaces. */
+using namespace JS;
+using namespace mozilla;
+
+}  /* namespace js */
+#endif  /* __cplusplus */
+
+JS_BEGIN_EXTERN_C
+
+/*
+ * Pattern used to overwrite freed memory. If you are accessing an object with
+ * this pattern, you probably have a dangling pointer.
+ */
+#define JS_FREE_PATTERN 0xDA
+
+/* JS_ASSERT */
+#ifdef DEBUG
+# define JS_ASSERT(expr)                                                      \
+    ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+# define JS_ASSERT_IF(cond, expr)                                             \
+    ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+# define JS_NOT_REACHED(reason)                                               \
+    JS_Assert(reason, __FILE__, __LINE__)
+# define JS_ALWAYS_TRUE(expr) JS_ASSERT(expr)
+# define JS_ALWAYS_FALSE(expr) JS_ASSERT(!(expr))
+# ifdef JS_THREADSAFE
+#  define JS_THREADSAFE_ASSERT(expr) JS_ASSERT(expr)
+# else
+#  define JS_THREADSAFE_ASSERT(expr) ((void) 0)
+# endif
+#else
+# define JS_ASSERT(expr)         ((void) 0)
+# define JS_ASSERT_IF(cond,expr) ((void) 0)
+# define JS_NOT_REACHED(reason)
+# define JS_ALWAYS_TRUE(expr)    ((void) (expr))
+# define JS_ALWAYS_FALSE(expr)    ((void) (expr))
+# define JS_THREADSAFE_ASSERT(expr) ((void) 0)
+#endif
+
+/*
+ * JS_STATIC_ASSERT
+ *
+ * A compile-time assert. "cond" must be a constant expression. The macro can
+ * be used only in places where an "extern" declaration is allowed.
+ */
+#ifdef __SUNPRO_CC
+/*
+ * Sun Studio C++ compiler has a bug
+ * "sizeof expression not accepted as size of array parameter"
+ * It happens when js_static_assert() function is declared inside functions.
+ * The bug number is 6688515. It is not public yet.
+ * Therefore, for Sun Studio, declare js_static_assert as an array instead.
+ */
+# define JS_STATIC_ASSERT(cond) extern char js_static_assert[(cond) ? 1 : -1]
+#else
+# ifdef __COUNTER__
+#  define JS_STATIC_ASSERT_GLUE1(x,y) x##y
+#  define JS_STATIC_ASSERT_GLUE(x,y) JS_STATIC_ASSERT_GLUE1(x,y)
+#  define JS_STATIC_ASSERT(cond)                                            \
+        typedef int JS_STATIC_ASSERT_GLUE(js_static_assert, __COUNTER__)[(cond) ? 1 : -1]
+# else
+#  define JS_STATIC_ASSERT(cond) extern void js_static_assert(int arg[(cond) ? 1 : -1])
+# endif
+#endif
+
+#define JS_STATIC_ASSERT_IF(cond, expr) JS_STATIC_ASSERT(!(cond) || (expr))
+
+/*
+ * Abort the process in a non-graceful manner. This will cause a core file,
+ * call to the debugger or other moral equivalent as well as causing the
+ * entire process to stop.
+ */
+extern JS_PUBLIC_API(void) JS_Abort(void);
+
+/*
+ * Custom allocator support for SpiderMonkey
+ */
+#if defined JS_USE_CUSTOM_ALLOCATOR
+# include "jscustomallocator.h"
+#else
+# ifdef DEBUG
+/*
+ * In order to test OOM conditions, when the shell command-line option
+ * |-A NUM| is passed, we fail continuously after the NUM'th allocation.
+ */
+extern JS_PUBLIC_DATA(JSUint32) OOM_maxAllocations; /* set from shell/js.cpp */
+extern JS_PUBLIC_DATA(JSUint32) OOM_counter; /* data race, who cares. */
+#  define JS_OOM_POSSIBLY_FAIL() \
+    do \
+    { \
+        if (OOM_counter++ >= OOM_maxAllocations) { \
+            return NULL; \
+        } \
+    } while (0)
+
+# else
+#  define JS_OOM_POSSIBLY_FAIL() do {} while(0)
+# endif
+
+/*
+ * SpiderMonkey code should not be calling these allocation functions directly.
+ * Instead, all calls should go through JSRuntime, JSContext or OffTheBooks.
+ * However, js_free() can be called directly.
+ */
+static JS_INLINE void* js_malloc(size_t bytes)
+{
+    JS_OOM_POSSIBLY_FAIL();
+    return malloc(bytes);
+}
+
+static JS_INLINE void* js_calloc(size_t bytes)
+{
+    JS_OOM_POSSIBLY_FAIL();
+    return calloc(bytes, 1);
+}
+
+static JS_INLINE void* js_realloc(void* p, size_t bytes)
+{
+    JS_OOM_POSSIBLY_FAIL();
+    return realloc(p, bytes);
+}
+
+static JS_INLINE void js_free(void* p)
+{
+    free(p);
+}
+#endif/* JS_USE_CUSTOM_ALLOCATOR */
+
+/*
+ * Replace bit-scanning code sequences with CPU-specific instructions to
+ * speedup calculations of ceiling/floor log2.
+ *
+ * With GCC 3.4 or later we can use __builtin_clz for that, see bug 327129.
+ *
+ * SWS: Added MSVC intrinsic bitscan support.  See bugs 349364 and 356856.
+ */
+#if defined(_WIN32) && (_MSC_VER >= 1300) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
+
+unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask);
+unsigned char _BitScanReverse(unsigned long * Index, unsigned long Mask);
+# pragma intrinsic(_BitScanForward,_BitScanReverse)
+
+__forceinline static int
+__BitScanForward32(unsigned int val)
+{
+    unsigned long idx;
+
+    _BitScanForward(&idx, (unsigned long)val);
+    return (int)idx;
+}
+__forceinline static int
+__BitScanReverse32(unsigned int val)
+{
+    unsigned long idx;
+
+    _BitScanReverse(&idx, (unsigned long)val);
+    return (int)(31-idx);
+}
+# define js_bitscan_ctz32(val)  __BitScanForward32(val)
+# define js_bitscan_clz32(val)  __BitScanReverse32(val)
+# define JS_HAS_BUILTIN_BITSCAN32
+
+#if defined(_M_AMD64) || defined(_M_X64)
+unsigned char _BitScanForward64(unsigned long * Index, unsigned __int64 Mask);
+unsigned char _BitScanReverse64(unsigned long * Index, unsigned __int64 Mask);
+# pragma intrinsic(_BitScanForward64,_BitScanReverse64)
+
+__forceinline static int
+__BitScanForward64(unsigned __int64 val)
+{
+    unsigned long idx;
+
+    _BitScanForward64(&idx, val);
+    return (int)idx;
+}
+__forceinline static int
+__BitScanReverse64(unsigned __int64 val)
+{
+    unsigned long idx;
+
+    _BitScanReverse64(&idx, val);
+    return (int)(63-idx);
+}
+# define js_bitscan_ctz64(val)  __BitScanForward64(val)
+# define js_bitscan_clz64(val)  __BitScanReverse64(val)
+# define JS_HAS_BUILTIN_BITSCAN64
+#endif
+#elif (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+
+# define js_bitscan_ctz32(val)  __builtin_ctz(val)
+# define js_bitscan_clz32(val)  __builtin_clz(val)
+# define JS_HAS_BUILTIN_BITSCAN32
+# if (JS_BYTES_PER_WORD == 8)
+#  define js_bitscan_ctz64(val)  __builtin_ctzll(val)
+#  define js_bitscan_clz64(val)  __builtin_clzll(val)
+#  define JS_HAS_BUILTIN_BITSCAN64
+# endif
+
+#endif
+
+/*
+** Macro version of JS_CeilingLog2: Compute the log of the least power of
+** 2 greater than or equal to _n. The result is returned in _log2.
+*/
+#ifdef JS_HAS_BUILTIN_BITSCAN32
+/*
+ * Use intrinsic function or count-leading-zeros to calculate ceil(log2(_n)).
+ * The macro checks for "n <= 1" and not "n != 0" as js_bitscan_clz32(0) is
+ * undefined.
+ */
+# define JS_CEILING_LOG2(_log2,_n)                                            \
+    JS_BEGIN_MACRO                                                            \
+        unsigned int j_ = (unsigned int)(_n);                                 \
+        (_log2) = (j_ <= 1 ? 0 : 32 - js_bitscan_clz32(j_ - 1));              \
+    JS_END_MACRO
+#else
+# define JS_CEILING_LOG2(_log2,_n)                                            \
+    JS_BEGIN_MACRO                                                            \
+        JSUint32 j_ = (JSUint32)(_n);                                         \
+        (_log2) = 0;                                                          \
+        if ((j_) & ((j_)-1))                                                  \
+            (_log2) += 1;                                                     \
+        if ((j_) >> 16)                                                       \
+            (_log2) += 16, (j_) >>= 16;                                       \
+        if ((j_) >> 8)                                                        \
+            (_log2) += 8, (j_) >>= 8;                                         \
+        if ((j_) >> 4)                                                        \
+            (_log2) += 4, (j_) >>= 4;                                         \
+        if ((j_) >> 2)                                                        \
+            (_log2) += 2, (j_) >>= 2;                                         \
+        if ((j_) >> 1)                                                        \
+            (_log2) += 1;                                                     \
+    JS_END_MACRO
+#endif
+
+/*
+** Macro version of JS_FloorLog2: Compute the log of the greatest power of
+** 2 less than or equal to _n. The result is returned in _log2.
+**
+** This is equivalent to finding the highest set bit in the word.
+*/
+#ifdef JS_HAS_BUILTIN_BITSCAN32
+/*
+ * Use js_bitscan_clz32 or count-leading-zeros to calculate floor(log2(_n)).
+ * Since js_bitscan_clz32(0) is undefined, the macro set the loweset bit to 1
+ * to ensure 0 result when _n == 0.
+ */
+# define JS_FLOOR_LOG2(_log2,_n)                                              \
+    JS_BEGIN_MACRO                                                            \
+        (_log2) = 31 - js_bitscan_clz32(((unsigned int)(_n)) | 1);            \
+    JS_END_MACRO
+#else
+# define JS_FLOOR_LOG2(_log2,_n)                                              \
+    JS_BEGIN_MACRO                                                            \
+        JSUint32 j_ = (JSUint32)(_n);                                         \
+        (_log2) = 0;                                                          \
+        if ((j_) >> 16)                                                       \
+            (_log2) += 16, (j_) >>= 16;                                       \
+        if ((j_) >> 8)                                                        \
+            (_log2) += 8, (j_) >>= 8;                                         \
+        if ((j_) >> 4)                                                        \
+            (_log2) += 4, (j_) >>= 4;                                         \
+        if ((j_) >> 2)                                                        \
+            (_log2) += 2, (j_) >>= 2;                                         \
+        if ((j_) >> 1)                                                        \
+            (_log2) += 1;                                                     \
+    JS_END_MACRO
+#endif
+
+/*
+ * Internal function.
+ * Compute the log of the least power of 2 greater than or equal to n. This is
+ * a version of JS_CeilingLog2 that operates on unsigned integers with
+ * CPU-dependant size.
+ */
+#define JS_CEILING_LOG2W(n) ((n) <= 1 ? 0 : 1 + JS_FLOOR_LOG2W((n) - 1))
+
+/*
+ * Internal function.
+ * Compute the log of the greatest power of 2 less than or equal to n.
+ * This is a version of JS_FloorLog2 that operates on unsigned integers with
+ * CPU-dependant size and requires that n != 0.
+ */
+#define JS_FLOOR_LOG2W(n) (JS_ASSERT((n) != 0), js_FloorLog2wImpl(n))
+
+#if JS_BYTES_PER_WORD == 4
+# ifdef JS_HAS_BUILTIN_BITSCAN32
+#  define js_FloorLog2wImpl(n)                                                \
+    ((size_t)(JS_BITS_PER_WORD - 1 - js_bitscan_clz32(n)))
+# else
+#  define js_FloorLog2wImpl(n) ((size_t)JS_FloorLog2(n))
+# endif
+#elif JS_BYTES_PER_WORD == 8
+# ifdef JS_HAS_BUILTIN_BITSCAN64
+#  define js_FloorLog2wImpl(n)                                                \
+    ((size_t)(JS_BITS_PER_WORD - 1 - js_bitscan_clz64(n)))
+# else
+extern size_t js_FloorLog2wImpl(size_t n);
+# endif
+#else
+# error "NOT SUPPORTED"
+#endif
+
+JS_END_EXTERN_C
+
+#ifdef __cplusplus
+#include <new>
+
+/*
+ * User guide to memory management within SpiderMonkey:
+ *
+ * Quick tips:
+ *
+ *   Allocation:
+ *   - Prefer to allocate using JSContext:
+ *       cx->{malloc_,realloc_,calloc_,new_,array_new}
+ *
+ *   - If no JSContext is available, use a JSRuntime:
+ *       rt->{malloc_,realloc_,calloc_,new_,array_new}
+ *
+ *   - As a last resort, use unaccounted allocation ("OffTheBooks"):
+ *       js::OffTheBooks::{malloc_,realloc_,calloc_,new_,array_new}
+ *
+ *   Deallocation:
+ *   - When the deallocation occurs on a slow path, use:
+ *       Foreground::{free_,delete_,array_delete}
+ *
+ *   - Otherwise deallocate on a background thread using a JSContext:
+ *       cx->{free_,delete_,array_delete}
+ *
+ *   - If no JSContext is available, use a JSRuntime:
+ *       rt->{free_,delete_,array_delete}
+ *
+ *   - As a last resort, use UnwantedForeground deallocation:
+ *       js::UnwantedForeground::{free_,delete_,array_delete}
+ *
+ * General tips:
+ *
+ *   - Mixing and matching these allocators is allowed (you may free memory
+ *     allocated by any allocator, with any deallocator).
+ *
+ *   - Never, ever use normal C/C++ memory management:
+ *       malloc, free, new, new[], delete, operator new, etc.
+ *
+ *   - Never, ever use low-level SpiderMonkey allocators:
+ *       js_malloc(), js_free(), js_calloc(), js_realloc()
+ *     Their use is reserved for the other memory managers.
+ *
+ *   - Classes which have private constructors or destructors should have
+ *     JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR added to their
+ *     declaration.
+ *
+ * Details:
+ *
+ *   Using vanilla new/new[] is unsafe in SpiderMonkey because they throw on
+ *   failure instead of returning NULL, which is what SpiderMonkey expects.
+ *   (Even overriding them is unsafe, as the system's C++ runtime library may
+ *   throw, which we do not support. We also can't just use the 'nothrow'
+ *   variant of new/new[], because we want to mediate *all* allocations
+ *   within SpiderMonkey, to satisfy any embedders using
+ *   JS_USE_CUSTOM_ALLOCATOR.)
+ *
+ *   JSContexts and JSRuntimes keep track of memory allocated, and use this
+ *   accounting to schedule GC. OffTheBooks does not. We'd like to remove
+ *   OffTheBooks allocations as much as possible (bug 636558).
+ *
+ *   On allocation failure, a JSContext correctly reports an error, which a
+ *   JSRuntime and OffTheBooks does not.
+ *
+ *   A JSContext deallocates in a background thread. A JSRuntime might
+ *   deallocate in the background in the future, but does not now. Foreground
+ *   deallocation is preferable on slow paths. UnwantedForeground deallocations
+ *   occur where we have no JSContext or JSRuntime, and the deallocation is not
+ *   on a slow path. We want to remove UnwantedForeground deallocations (bug
+ *   636561).
+ *
+ *   JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR makes the allocation
+ *   classes friends with your class, giving them access to private
+ *   constructors and destructors.
+ *
+ *   |make check| does a source level check on the number of uses OffTheBooks,
+ *   UnwantedForeground, js_malloc, js_free etc, to prevent regressions. If you
+ *   really must add one, update Makefile.in, and run |make check|.
+ *
+ *   |make check| also statically prevents the use of vanilla new/new[].
+ */
+
+#define JS_NEW_BODY(allocator, t, parms)                                       \
+    void *memory = allocator(sizeof(t));                                       \
+    return memory ? new(memory) t parms : NULL;
+
+/*
+ * Given a class which should provide new_() methods, add
+ * JS_DECLARE_NEW_METHODS (see JSContext for a usage example). This
+ * adds new_()s with up to 12 parameters. Add more versions of new_ below if
+ * you need more than 12 parameters.
+ *
+ * Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
+ * or the build will break.
+ */
+#define JS_DECLARE_NEW_METHODS(ALLOCATOR, QUALIFIERS)\
+    template <class T>\
+    QUALIFIERS T *new_() {\
+        JS_NEW_BODY(ALLOCATOR, T, ())\
+    }\
+\
+    template <class T, class P1>\
+    QUALIFIERS T *new_(P1 p1) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1))\
+    }\
+\
+    template <class T, class P1, class P2>\
+    QUALIFIERS T *new_(P1 p1, P2 p2) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2))\
+    }\
+\
+    template <class T, class P1, class P2, class P3>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4, class P5>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4, class P5, class P6>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11))\
+    }\
+\
+    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>\
+    QUALIFIERS T *new_(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10, P11 p11, P12 p12) {\
+        JS_NEW_BODY(ALLOCATOR, T, (p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12))\
+    }\
+    static const int JSMinAlignment = 8;\
+    template <class T>\
+    QUALIFIERS T *array_new(size_t n) {\
+        /* The length is stored just before the vector memory. */\
+        uint64 numBytes64 = uint64(JSMinAlignment) + uint64(sizeof(T)) * uint64(n);\
+        size_t numBytes = size_t(numBytes64);\
+        if (numBytes64 != numBytes) {\
+            JS_ASSERT(0);   /* we want to know if this happens in debug builds */\
+            return NULL;\
+        }\
+        void *memory = ALLOCATOR(numBytes);\
+        if (!memory)\
+            return NULL;\
+        *(size_t *)memory = n;\
+        memory = (void*)(uintptr_t(memory) + JSMinAlignment);\
+        return new(memory) T[n];\
+    }\
+
+
+#define JS_DECLARE_DELETE_METHODS(DEALLOCATOR, QUALIFIERS)\
+    template <class T>\
+    QUALIFIERS void delete_(T *p) {\
+        if (p) {\
+            p->~T();\
+            DEALLOCATOR(p);\
+        }\
+    }\
+\
+    template <class T>\
+    QUALIFIERS void array_delete(T *p) {\
+        if (p) {\
+            void* p0 = (void *)(uintptr_t(p) - js::OffTheBooks::JSMinAlignment);\
+            size_t n = *(size_t *)p0;\
+            for (size_t i = 0; i < n; i++)\
+                (p + i)->~T();\
+            DEALLOCATOR(p0);\
+        }\
+    }
+
+
+/*
+ * In general, all allocations should go through a JSContext or JSRuntime, so
+ * that the garbage collector knows how much memory has been allocated. In
+ * cases where it is difficult to use a JSContext or JSRuntime, OffTheBooks can
+ * be used, though this is undesirable.
+ */
+namespace js {
+
+class OffTheBooks {
+public:
+    JS_DECLARE_NEW_METHODS(::js_malloc, JS_ALWAYS_INLINE static)
+
+    static JS_INLINE void* malloc_(size_t bytes) {
+        return ::js_malloc(bytes);
+    }
+
+    static JS_INLINE void* calloc_(size_t bytes) {
+        return ::js_calloc(bytes);
+    }
+
+    static JS_INLINE void* realloc_(void* p, size_t bytes) {
+        return ::js_realloc(p, bytes);
+    }
+};
+
+/*
+ * We generally prefer deallocating using JSContext because it can happen in
+ * the background. On slow paths, we may prefer foreground allocation.
+ */
+class Foreground {
+public:
+    /* See parentheses comment above. */
+    static JS_ALWAYS_INLINE void free_(void* p) {
+        ::js_free(p);
+    }
+
+    JS_DECLARE_DELETE_METHODS(::js_free, JS_ALWAYS_INLINE static)
+};
+
+class UnwantedForeground : public Foreground {
+};
+
+} /* namespace js */
+
+/*
+ * Note lack of ; in JSRuntime below. This is intentional so "calling" this
+ * looks "normal".
+ */
+#define JS_DECLARE_ALLOCATION_FRIENDS_FOR_PRIVATE_CONSTRUCTOR \
+    friend class js::OffTheBooks;\
+    friend class js::Foreground;\
+    friend class js::UnwantedForeground;\
+    friend struct ::JSContext;\
+    friend struct ::JSRuntime
+
+/*
+ * The following classes are designed to cause assertions to detect
+ * inadvertent use of guard objects as temporaries.  In other words,
+ * when we have a guard object whose only purpose is its constructor and
+ * destructor (and is never otherwise referenced), the intended use
+ * might be:
+ *     JSAutoTempValueRooter tvr(cx, 1, &val);
+ * but is is easy to accidentally write:
+ *     JSAutoTempValueRooter(cx, 1, &val);
+ * which compiles just fine, but runs the destructor well before the
+ * intended time.
+ *
+ * They work by adding (#ifdef DEBUG) an additional parameter to the
+ * guard object's constructor, with a default value, so that users of
+ * the guard object's API do not need to do anything.  The default value
+ * of this parameter is a temporary object.  C++ (ISO/IEC 14882:1998),
+ * section 12.2 [class.temporary], clauses 4 and 5 seem to assume a
+ * guarantee that temporaries are destroyed in the reverse of their
+ * construction order, but I actually can't find a statement that that
+ * is true in the general case (beyond the two specific cases mentioned
+ * there).  However, it seems to be true.
+ *
+ * These classes are intended to be used only via the macros immediately
+ * below them:
+ *   JS_DECL_USE_GUARD_OBJECT_NOTIFIER declares (ifdef DEBUG) a member
+ *     variable, and should be put where a declaration of a private
+ *     member variable would be placed.
+ *   JS_GUARD_OBJECT_NOTIFIER_PARAM should be placed at the end of the
+ *     parameters to each constructor of the guard object; it declares
+ *     (ifdef DEBUG) an additional parameter.
+ *   JS_GUARD_OBJECT_NOTIFIER_INIT is a statement that belongs in each
+ *     constructor.  It uses the parameter declared by
+ *     JS_GUARD_OBJECT_NOTIFIER_PARAM.
+ */
+#ifdef DEBUG
+class JS_FRIEND_API(JSGuardObjectNotifier)
+{
+private:
+    bool* mStatementDone;
+public:
+    JSGuardObjectNotifier() : mStatementDone(NULL) {}
+
+    ~JSGuardObjectNotifier() {
+        *mStatementDone = true;
+    }
+
+    void setStatementDone(bool *aStatementDone) {
+        mStatementDone = aStatementDone;
+    }
+};
+
+class JS_FRIEND_API(JSGuardObjectNotificationReceiver)
+{
+private:
+    bool mStatementDone;
+public:
+    JSGuardObjectNotificationReceiver() : mStatementDone(false) {}
+
+    ~JSGuardObjectNotificationReceiver() {
+        /*
+         * Assert that the guard object was not used as a temporary.
+         * (Note that this assert might also fire if Init is not called
+         * because the guard object's implementation is not using the
+         * above macros correctly.)
+         */
+        JS_ASSERT(mStatementDone);
+    }
+
+    void Init(const JSGuardObjectNotifier &aNotifier) {
+        /*
+         * aNotifier is passed as a const reference so that we can pass a
+         * temporary, but we really intend it as non-const
+         */
+        const_cast<JSGuardObjectNotifier&>(aNotifier).
+            setStatementDone(&mStatementDone);
+    }
+};
+
+#define JS_DECL_USE_GUARD_OBJECT_NOTIFIER \
+    JSGuardObjectNotificationReceiver _mCheckNotUsedAsTemporary;
+#define JS_GUARD_OBJECT_NOTIFIER_PARAM \
+    , const JSGuardObjectNotifier& _notifier = JSGuardObjectNotifier()
+#define JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT \
+    , const JSGuardObjectNotifier& _notifier
+#define JS_GUARD_OBJECT_NOTIFIER_PARAM0 \
+    const JSGuardObjectNotifier& _notifier = JSGuardObjectNotifier()
+#define JS_GUARD_OBJECT_NOTIFIER_INIT \
+    JS_BEGIN_MACRO _mCheckNotUsedAsTemporary.Init(_notifier); JS_END_MACRO
+
+#else /* defined(DEBUG) */
+
+#define JS_DECL_USE_GUARD_OBJECT_NOTIFIER
+#define JS_GUARD_OBJECT_NOTIFIER_PARAM
+#define JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT
+#define JS_GUARD_OBJECT_NOTIFIER_PARAM0
+#define JS_GUARD_OBJECT_NOTIFIER_INIT JS_BEGIN_MACRO JS_END_MACRO
+
+#endif /* !defined(DEBUG) */
+
+namespace js {
+
+/*
+ * "Move" References
+ *
+ * Some types can be copied much more efficiently if we know the original's
+ * value need not be preserved --- that is, if we are doing a "move", not a
+ * "copy". For example, if we have:
+ *
+ *   Vector<T> u;
+ *   Vector<T> v(u);
+ *
+ * the constructor for v must apply a copy constructor to each element of u ---
+ * taking time linear in the length of u. However, if we know we will not need u
+ * any more once v has been initialized, then we could initialize v very
+ * efficiently simply by stealing u's dynamically allocated buffer and giving it
+ * to v --- a constant-time operation, regardless of the size of u.
+ *
+ * Moves often appear in container implementations. For example, when we append
+ * to a vector, we may need to resize its buffer. This entails moving each of
+ * its extant elements from the old, smaller buffer to the new, larger buffer.
+ * But once the elements have been migrated, we're just going to throw away the
+ * old buffer; we don't care if they still have their values. So if the vector's
+ * element type can implement "move" more efficiently than "copy", the vector
+ * resizing should by all means use a "move" operation. Hash tables also need to
+ * be resized.
+ *
+ * The details of the optimization, and whether it's worth applying, vary from
+ * one type to the next. And while some constructor calls are moves, many really
+ * are copies, and can't be optimized this way. So we need:
+ *
+ * 1) a way for a particular invocation of a copy constructor to say that it's
+ *    really a move, and that the value of the original isn't important
+ *    afterwards (althought it must still be safe to destroy); and
+ *
+ * 2) a way for a type (like Vector) to announce that it can be moved more
+ *    efficiently than it can be copied, and provide an implementation of that
+ *    move operation.
+ *
+ * The Move(T &) function takes a reference to a T, and returns an MoveRef<T>
+ * referring to the same value; that's 1). An MoveRef<T> is simply a reference
+ * to a T, annotated to say that a copy constructor applied to it may move that
+ * T, instead of copying it. Finally, a constructor that accepts an MoveRef<T>
+ * should perform a more efficient move, instead of a copy, providing 2).
+ *
+ * So, where we might define a copy constructor for a class C like this:
+ *
+ *   C(const C &rhs) { ... copy rhs to this ... }
+ *
+ * we would declare a move constructor like this:
+ *
+ *   C(MoveRef<C> rhs) { ... move rhs to this ... }
+ *
+ * And where we might perform a copy like this:
+ *
+ *   C c2(c1);
+ *
+ * we would perform a move like this:
+ *
+ *   C c2(Move(c1))
+ *
+ * Note that MoveRef<T> implicitly converts to T &, so you can pass an
+ * MoveRef<T> to an ordinary copy constructor for a type that doesn't support a
+ * special move constructor, and you'll just get a copy. This means that
+ * templates can use Move whenever they know they won't use the original value
+ * any more, even if they're not sure whether the type at hand has a specialized
+ * move constructor. If it doesn't, the MoveRef<T> will just convert to a T &,
+ * and the ordinary copy constructor will apply.
+ *
+ * A class with a move constructor can also provide a move assignment operator,
+ * which runs this's destructor, and then applies the move constructor to
+ * *this's memory. A typical definition:
+ *
+ *   C &operator=(MoveRef<C> rhs) {
+ *     this->~C();
+ *     new(this) C(rhs);
+ *     return *this;
+ *   }
+ *
+ * With that in place, one can write move assignments like this:
+ *
+ *   c2 = Move(c1);
+ *
+ * This destroys c1, moves c1's value to c2, and leaves c1 in an undefined but
+ * destructible state.
+ *
+ * This header file defines MoveRef and Move in the js namespace. It's up to
+ * individual containers to annotate moves as such, by calling Move; and it's up
+ * to individual types to define move constructors.
+ *
+ * One hint: if you're writing a move constructor where the type has members
+ * that should be moved themselves, it's much nicer to write this:
+ *
+ *   C(MoveRef<C> c) : x(c->x), y(c->y) { }
+ *
+ * than the equivalent:
+ *
+ *   C(MoveRef<C> c) { new(&x) X(c->x); new(&y) Y(c->y); }
+ *
+ * especially since GNU C++ fails to notice that this does indeed initialize x
+ * and y, which may matter if they're const.
+ */
+template<typename T>
+class MoveRef {
+  public:
+    typedef T Referent;
+    explicit MoveRef(T &t) : pointer(&t) { }
+    T &operator*()  const { return *pointer; }
+    T *operator->() const { return  pointer; }
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+    /*
+     * If MoveRef is used in a rvalue position (which is expected), we can
+     * end up in a situation where, without this ifdef, we would try to pass
+     * a T& to a move constructor, which fails. It is not clear if the compiler
+     * should instead use the copy constructor, but for now this lets us build
+     * with clang. See bug 689066 and llvm.org/pr11003 for the details.
+     * Note: We can probably remove MoveRef completely once we are comfortable
+     * using c++11.
+     */
+    operator T&& ()  const { return static_cast<T&&>(*pointer); }
+#else
+    operator T& ()   const { return *pointer; }
+#endif
+  private:
+    T *pointer;
+};
+
+template<typename T>
+MoveRef<T> Move(T &t) { return MoveRef<T>(t); }
+
+template<typename T>
+MoveRef<T> Move(const T &t) { return MoveRef<T>(const_cast<T &>(t)); }
+
+/* Useful for implementing containers that assert non-reentrancy */
+class ReentrancyGuard
+{
+    /* ReentrancyGuard is not copyable. */
+    ReentrancyGuard(const ReentrancyGuard &);
+    void operator=(const ReentrancyGuard &);
+
+#ifdef DEBUG
+    bool &entered;
+#endif
+  public:
+    template <class T>
+#ifdef DEBUG
+    ReentrancyGuard(T &obj)
+      : entered(obj.entered)
+#else
+    ReentrancyGuard(T &/*obj*/)
+#endif
+    {
+#ifdef DEBUG
+        JS_ASSERT(!entered);
+        entered = true;
+#endif
+    }
+    ~ReentrancyGuard()
+    {
+#ifdef DEBUG
+        entered = false;
+#endif
+    }
+};
+
+/*
+ * Round x up to the nearest power of 2.  This function assumes that the most
+ * significant bit of x is not set, which would lead to overflow.
+ */
+JS_ALWAYS_INLINE size_t
+RoundUpPow2(size_t x)
+{
+    return size_t(1) << JS_CEILING_LOG2W(x);
+}
+
+} /* namespace js */
+
+#endif /* defined(__cplusplus) */
+
+/*
+ * This signature is for malloc_usable_size-like functions used to measure
+ * memory usage.  A return value of zero indicates that the size is unknown,
+ * and so a fall-back computation should be done for the size.
+ */
+typedef size_t(*JSUsableSizeFun)(void *p);
+
+/* sixgill annotation defines */
+#ifndef HAVE_STATIC_ANNOTATIONS
+# define HAVE_STATIC_ANNOTATIONS
+# ifdef XGILL_PLUGIN
+#  define STATIC_PRECONDITION(COND)         __attribute__((precondition(#COND)))
+#  define STATIC_PRECONDITION_ASSUME(COND)  __attribute__((precondition_assume(#COND)))
+#  define STATIC_POSTCONDITION(COND)        __attribute__((postcondition(#COND)))
+#  define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
+#  define STATIC_INVARIANT(COND)            __attribute__((invariant(#COND)))
+#  define STATIC_INVARIANT_ASSUME(COND)     __attribute__((invariant_assume(#COND)))
+#  define STATIC_PASTE2(X,Y) X ## Y
+#  define STATIC_PASTE1(X,Y) STATIC_PASTE2(X,Y)
+#  define STATIC_ASSERT(COND)                        \
+  JS_BEGIN_MACRO                                     \
+    __attribute__((assert_static(#COND), unused))    \
+    int STATIC_PASTE1(assert_static_, __COUNTER__);  \
+  JS_END_MACRO
+#  define STATIC_ASSUME(COND)                        \
+  JS_BEGIN_MACRO                                     \
+    __attribute__((assume_static(#COND), unused))    \
+    int STATIC_PASTE1(assume_static_, __COUNTER__);  \
+  JS_END_MACRO
+#  define STATIC_ASSERT_RUNTIME(COND)                       \
+  JS_BEGIN_MACRO                                            \
+    __attribute__((assert_static_runtime(#COND), unused))   \
+    int STATIC_PASTE1(assert_static_runtime_, __COUNTER__); \
+  JS_END_MACRO
+# else /* XGILL_PLUGIN */
+#  define STATIC_PRECONDITION(COND)          /* nothing */
+#  define STATIC_PRECONDITION_ASSUME(COND)   /* nothing */
+#  define STATIC_POSTCONDITION(COND)         /* nothing */
+#  define STATIC_POSTCONDITION_ASSUME(COND)  /* nothing */
+#  define STATIC_INVARIANT(COND)             /* nothing */
+#  define STATIC_INVARIANT_ASSUME(COND)      /* nothing */
+#  define STATIC_ASSERT(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
+#  define STATIC_ASSUME(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
+#  define STATIC_ASSERT_RUNTIME(COND)  JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
+# endif /* XGILL_PLUGIN */
+# define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
+#endif /* HAVE_STATIC_ANNOTATIONS */
+
+#endif /* js_utility_h__ */
rename from js/src/jsvector.h
rename to js/public/Vector.h
--- a/js/src/jsvector.h
+++ b/js/public/Vector.h
@@ -36,29 +36,30 @@
  * 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 jsvector_h_
 #define jsvector_h_
 
-#include "jsalloc.h"
-#include "jstl.h"
-#include "jsprvtd.h"
-#include "jsutil.h"
+#include "TemplateLib.h"
+#include "Utility.h"
 
 /* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4345)
 #endif
 
 namespace js {
 
+template <class T, size_t N, class AllocPolicy>
+class Vector;
+
 /*
  * This template class provides a default implementation for vector operations
  * when the element type is not known to be a POD, as judged by IsPodType.
  */
 template <class T, size_t N, class AP, bool IsPod>
 struct VectorImpl
 {
     /* Destroys constructed objects in the range [begin, end). */
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -90,17 +90,24 @@ endif
 # JS shell would like to link to the static library.
 
 ifdef JS_SHARED_LIBRARY
 FORCE_SHARED_LIB = 1
 endif
 FORCE_STATIC_LIB = 1
 DIST_INSTALL = 1
 
-VPATH		= $(srcdir)
+VPATH		= \
+		$(srcdir) \
+		$(srcdir)/builtin \
+		$(srcdir)/ds \
+		$(srcdir)/frontend \
+		$(srcdir)/gc \
+		$(srcdir)/vm \
+		$(NULL)
 
 CPPSRCS		= \
 		jsalloc.cpp \
 		jsanalyze.cpp \
 		jsapi.cpp \
 		jsarray.cpp \
 		jsatom.cpp \
 		jsbool.cpp \
@@ -158,31 +165,31 @@ CPPSRCS		= \
 		GlobalObject.cpp \
 		Stack.cpp \
 		String.cpp \
 		ParseMaps.cpp \
 		LifoAlloc.cpp \
 		RegExpObject.cpp \
 		RegExpStatics.cpp \
 		RegExp.cpp \
+		Statistics.cpp \
 		Unicode.cpp \
 		$(NULL)
 
 # Changes to internal header files, used externally, massively slow down
 # browser builds.  Don't add new files here unless you know what you're
 # doing!
 INSTALLED_HEADERS = \
 		js-config.h \
 		jsautocfg.h \
 		$(CURDIR)/jsautokw.h \
 		js.msg \
 		jsalloc.h \
 		jsapi.h \
 		jsatom.h \
-		jsbit.h \
 		jsclass.h \
 		jsclist.h \
 		jsclone.h \
 		jscntxt.h \
 		jscompat.h \
 		jscrashreport.h \
 		jsdate.h \
 		jsdbgapi.h \
@@ -197,76 +204,91 @@ INSTALLED_HEADERS = \
 		jsinttypes.h \
 		jslock.h \
 		json.h \
 		jsopcode.tbl \
 		jsopcode.h \
 		jsotypes.h \
 		jsproxy.h \
 		jsprf.h \
-		jsprobes.h \
 		jspropertycache.h \
 		jspropertytree.h \
 		jsproto.tbl \
 		jsprvtd.h \
 		jspubtd.h \
 		jsreflect.h \
 		jsscan.h \
 		jsstaticcheck.h \
 		jsstdint.h \
 		jsstr.h \
 		jstracer.h \
 		jstypedarray.h \
 		jstypes.h \
 		jsutil.h \
-		jsvector.h \
-		jstl.h \
-		jshashtable.h \
 		jsversion.h \
 		jswrapper.h \
 		jsxdrapi.h \
 		jsval.h \
 		prmjtime.h \
 		$(NULL)
 
 ######################################################
-# BEGIN include sources for the engine subdirectories
+# BEGIN exported headers that are only exported
+#       because of inclusion by an INSTALLED_HEADER
 #
-VPATH		+= \
-		$(srcdir)/builtin \
-		$(srcdir)/ds \
-		$(srcdir)/frontend \
-		$(srcdir)/vm \
-		$(NULL)
-
-EXPORTS_NAMESPACES = vm ds
+EXPORTS_NAMESPACES += vm ds gc
 
 EXPORTS_vm = \
 		String.h \
 		StackSpace.h \
 		Unicode.h  \
 		$(NULL)
 
 EXPORTS_ds = \
-		LifoAlloc.h
+		LifoAlloc.h \
+		$(NULL)
+
+EXPORTS_gc = \
+		Statistics.h \
+		$(NULL)
+
+######################################################
+# BEGIN include exported headers from the JS engine
+#
+#       Ultimately, after cleansing INSTALLED_HEADERS,
+#       these will be the ONLY headers exported by
+#       the js engine
+#
+VPATH		+= \
+		$(srcdir)/../public \
+		$(NULL)
+
+EXPORTS_NAMESPACES += js
+
+EXPORTS_js = \
+		HashTable.h \
+		TemplateLib.h \
+		Utility.h \
+		Vector.h \
+		$(NULL)
 
 ###############################################
 # BEGIN include sources for low-level code shared with Gecko
 #
 VPATH		+= \
 		$(srcdir)/../../mfbt \
 		$(NULL)
 
 EXPORTS_NAMESPACES += mozilla
 
 EXPORTS_mozilla = \
 		RangedPtr.h \
-		RefPtr.h	\
-		Types.h		\
-		Util.h          \
+		RefPtr.h \
+		Types.h	\
+		Util.h \
 		$(NULL)
 
 ifdef ENABLE_TRACEJIT
 VPATH		+= \
 		$(srcdir)/tracejit \
 		$(srcdir)/nanojit \
 
 INSTALLED_HEADERS += \
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -32,17 +32,17 @@
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER && (WTF_CPU_X86 || WTF_CPU_X86_64)
 
 #include "AssemblerBuffer.h"
 #include "jsstdint.h"
 #include "assembler/wtf/Assertions.h"
-#include "jsvector.h"
+#include "js/Vector.h"
 
 #include "methodjit/Logging.h"
 #define IPFX  "        %s"
 #define ISPFX "        "
 #ifdef JS_METHODJIT_SPEW
 # define MAYBE_PAD (isOOLPath ? ">  " : "")
 # define PRETTY_PRINT_OFFSET(os) (((os)<0)?"-":""), (((os)<0)?-(os):(os))
 # define FIXME_INSN_PRINTING                                \
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -23,23 +23,24 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
 #ifndef ExecutableAllocator_h
 #define ExecutableAllocator_h
 
 #include <stddef.h> // for ptrdiff_t
 #include <limits>
-#include "assembler/wtf/Assertions.h"
 
+#include "jsalloc.h"
 #include "jsapi.h"
-#include "jshashtable.h"
 #include "jsprvtd.h"
-#include "jsvector.h"
-#include "jslock.h"
+
+#include "assembler/wtf/Assertions.h"
+#include "js/HashTable.h"
+#include "js/Vector.h"
 
 #if WTF_CPU_SPARC
 #ifdef linux  // bugzilla 502369
 static void sync_instruction_memory(caddr_t v, u_int len)
 {
     caddr_t end = v + len;
     caddr_t p = v;
     while (p < end) {
@@ -160,20 +161,22 @@ private:
     
     size_t available() const { 
         JS_ASSERT(m_end >= m_freePtr);
         return m_end - m_freePtr;
     }
 };
 
 class ExecutableAllocator {
+    typedef void (*DestroyCallback)(void* addr, size_t size);
     enum ProtectionSetting { Writable, Executable };
+    DestroyCallback destroyCallback;
 
 public:
-    ExecutableAllocator()
+    ExecutableAllocator() : destroyCallback(NULL)
     {
         if (!pageSize) {
             pageSize = determinePageSize();
             /*
              * On Windows, VirtualAlloc effectively allocates in 64K chunks.
              * (Technically, it allocates in page chunks, but the starting
              * address is always a multiple of 64K, so each allocation uses up
              * 64K of address space.)  So a size less than that would be
@@ -216,22 +219,28 @@ public:
         // (found, or created if necessary) a pool that had enough space.
         void *result = (*poolp)->alloc(n, type);
         JS_ASSERT(result);
         return result;
     }
 
     void releasePoolPages(ExecutablePool *pool) {
         JS_ASSERT(pool->m_allocation.pages);
+        if (destroyCallback)
+            destroyCallback(pool->m_allocation.pages, pool->m_allocation.size);
         systemRelease(pool->m_allocation);
         m_pools.remove(m_pools.lookup(pool));   // this asserts if |pool| is not in m_pools
     }
 
     void getCodeStats(size_t& method, size_t& regexp, size_t& unused) const;
 
+    void setDestroyCallback(DestroyCallback destroyCallback) {
+        this->destroyCallback = destroyCallback;
+    }
+
 private:
     static size_t pageSize;
     static size_t largeAllocSize;
 
     static const size_t OVERSIZE_ALLOCATION = size_t(-1);
 
     static size_t roundUpAllocationSize(size_t request, size_t granularity)
     {
--- a/js/src/assembler/wtf/SegmentedVector.h
+++ b/js/src/assembler/wtf/SegmentedVector.h
@@ -25,17 +25,17 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef SegmentedVector_h
 #define SegmentedVector_h
 
 #include "jsprvtd.h"
-#include "jsvector.h"
+#include "js/Vector.h"
 
 namespace WTF {
 
     // An iterator for SegmentedVector. It supports only the pre ++ operator
     template <typename T, size_t SegmentSize> class SegmentedVector;
     template <typename T, size_t SegmentSize> class SegmentedVectorIterator {
     private:
         friend class SegmentedVector<T, SegmentSize>;
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -34,17 +34,16 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "jsinfer.h"
-#include "jstl.h"
 
 #include "builtin/RegExp.h"
 
 #include "vm/RegExpObject-inl.h"
 #include "vm/RegExpStatics-inl.h"
 
 using namespace js;
 using namespace js::types;
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -4416,38 +4416,16 @@ MOZ_ARG_ENABLE_BOOL(tracevis,
 if test -n "$MOZ_TRACEVIS"; then
     AC_DEFINE(MOZ_TRACEVIS)
     if test -z "$ENABLE_TRACEJIT"; then
        AC_MSG_ERROR([--enable-tracevis is incompatible with --disable-tracejit])
     fi
 fi
 
 dnl ========================================================
-dnl = Use GCTimer
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(gctimer,
-[  --enable-gctimer        Enable GC timer (default=no)],
-    MOZ_GCTIMER=1,
-    MOZ_GCTIMER= )
-if test -n "$MOZ_GCTIMER"; then
-    AC_DEFINE(MOZ_GCTIMER)
-fi
-
-dnl ========================================================
-dnl = Don't enable GC-TestPilot plumbing
-dnl ========================================================
-JSGC_TESTPILOT=1
-MOZ_ARG_DISABLE_BOOL(gctestpilot,
-[  --disable-gctestpilot    Disable GC TestPilot study hooks],
-    JSGC_TESTPILOT= )
-if test -n "$JSGC_TESTPILOT"; then
-    AC_DEFINE(JSGC_TESTPILOT)
-fi
-
-dnl ========================================================
 dnl = Use Valgrind
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(valgrind,
 [  --enable-valgrind       Enable Valgrind integration hooks (default=no)],
     MOZ_VALGRIND=1,
     MOZ_VALGRIND= )
 if test -n "$MOZ_VALGRIND"; then
     AC_CHECK_HEADER([valgrind/valgrind.h], [],
@@ -4654,16 +4632,33 @@ AC_SUBST(MOZ_DEMANGLE_SYMBOLS)
 dnl ========================================================
 dnl = Support for gcc stack unwinding (from gcc 3.3)
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     AC_CHECK_HEADER(unwind.h, AC_CHECK_FUNCS(_Unwind_Backtrace))
 fi
 
 dnl ========================================================
+dnl JIT observers
+dnl ========================================================
+
+MOZ_ARG_WITH_STRING(jitreport-granularity,
+[  --jitreport-granularity=N
+                           Default granularity at which to report JIT code
+                           to external tools
+                             0 - no info
+                             1 - code ranges for whole functions only
+                             2 - per-line information
+                             3 - per-op information],
+  JITREPORT_GRANULARITY=$withval,
+  JITREPORT_GRANULARITY=3)
+
+AC_DEFINE_UNQUOTED(JS_DEFAULT_JITREPORT_GRANULARITY, $JITREPORT_GRANULARITY)
+
+dnl ========================================================
 dnl =
 dnl = Misc. Options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Misc. Options)
 
 dnl ========================================================
 dnl update xterm title
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -36,20 +36,21 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef CTYPES_H
 #define CTYPES_H
 
 #include "jscntxt.h"
 #include "jsapi.h"
-#include "jshashtable.h"
 #include "prlink.h"
 #include "ffi.h"
 
+#include "js/HashTable.h"
+
 namespace js {
 namespace ctypes {
 
 /*******************************************************************************
 ** Utility classes
 *******************************************************************************/
 
 template<class T>
rename from js/src/mfbt/InlineMap.h
rename to js/src/ds/InlineMap.h
--- a/js/src/mfbt/InlineMap.h
+++ b/js/src/ds/InlineMap.h
@@ -36,17 +36,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef InlineMap_h__
 #define InlineMap_h__
 
-#include "jshashtable.h"
+#include "js/HashTable.h"
 
 namespace js {
 
 /*
  * A type can only be used as an InlineMap key if zero is an invalid key value
  * (and thus may be used as a tombstone value by InlineMap).
  */
 template <typename T> struct ZeroIsReserved         { static const bool result = false; };
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -60,24 +60,49 @@ BumpChunk::new_(size_t chunkSize)
      * We assume that the alignment of sAlign is less than that of
      * the underlying memory allocator -- creating a new BumpChunk should
      * always satisfy the sAlign alignment constraint.
      */
     JS_ASSERT(AlignPtr(result->bump) == result->bump);
     return result;
 }
 
+void
+BumpChunk::delete_(BumpChunk *chunk)
+{
+#ifdef DEBUG
+        memset(chunk, 0xcd, sizeof(*chunk) + chunk->bumpSpaceSize);
+#endif
+        js_free(chunk);
+}
+
+bool
+BumpChunk::canAlloc(size_t n)
+{
+    char *aligned = AlignPtr(bump);
+    char *bumped = aligned + n;
+    return bumped <= limit && bumped > headerBase();
+}
+
+bool
+BumpChunk::canAllocUnaligned(size_t n)
+{
+    char *bumped = bump + n;
+    return bumped <= limit && bumped > headerBase();
+}
+
 void *
 BumpChunk::tryAllocUnaligned(size_t n)
 {
     char *oldBump = bump;
     char *newBump = bump + n;
     if (newBump > limit)
         return NULL;
 
+    JS_ASSERT(canAllocUnaligned(n));
     setBump(newBump);
     return oldBump;
 }
 
 } /* namespace detail */
 } /* namespace js */
 
 void
@@ -131,19 +156,30 @@ LifoAlloc::getOrCreateChunk(size_t n)
             latest = latest->next();
             latest->resetBump(); /* This was an unused BumpChunk on the chain. */
             if (latest->canAlloc(n))
                 return latest;
         }
     }
 
     size_t defaultChunkFreeSpace = defaultChunkSize_ - sizeof(BumpChunk);
-    size_t chunkSize = n > defaultChunkFreeSpace
-                       ? RoundUpPow2(n + sizeof(BumpChunk))
-                       : defaultChunkSize_;
+    size_t chunkSize;
+    if (n > defaultChunkFreeSpace) {
+        size_t allocSizeWithHeader = n + sizeof(BumpChunk);
+
+        /* Guard for overflow. */
+        if (allocSizeWithHeader < n ||
+            (allocSizeWithHeader & (size_t(1) << (tl::BitSize<size_t>::result - 1)))) {
+            return NULL;
+        }
+
+        chunkSize = RoundUpPow2(allocSizeWithHeader);
+    } else {
+        chunkSize = defaultChunkSize_;
+    }
 
     /* If we get here, we couldn't find an existing BumpChunk to fill the request. */
     BumpChunk *newChunk = BumpChunk::new_(chunkSize);
     if (!newChunk)
         return NULL;
     if (!first) {
         latest = first = newChunk;
     } else {
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -44,17 +44,18 @@
 /*
  * This data structure supports stacky LIFO allocation (mark/release and
  * LifoAllocScope). It does not maintain one contiguous segment; instead, it
  * maintains a bunch of linked memory segments. In order to prevent malloc/free
  * thrashing, unused segments are deallocated when garbage collection occurs.
  */
 
 #include "jsutil.h"
-#include "jstl.h"
+
+#include "js/TemplateLib.h"
 
 namespace js {
 
 namespace detail {
 
 static const size_t LIFO_ALLOC_ALIGN = 8;
 
 JS_ALWAYS_INLINE
@@ -73,17 +74,18 @@ AlignPtr(void *orig)
 /* Header for a chunk of memory wrangled by the LifoAlloc. */
 class BumpChunk
 {
     char        *bump;
     char        *limit;
     BumpChunk   *next_;
     size_t      bumpSpaceSize;
 
-    char *base() const { return limit - bumpSpaceSize; }
+    char *headerBase() { return reinterpret_cast<char *>(this); }
+    char *bumpBase() const { return limit - bumpSpaceSize; }
 
     BumpChunk *thisDuringConstruction() { return this; }
 
     explicit BumpChunk(size_t bumpSpaceSize)
       : bump(reinterpret_cast<char *>(thisDuringConstruction()) + sizeof(BumpChunk)),
         limit(bump + bumpSpaceSize),
         next_(NULL), bumpSpaceSize(bumpSpaceSize)
     {
@@ -92,82 +94,77 @@ class BumpChunk
 
     void clobberUnused() {
 #ifdef DEBUG
         memset(bump, 0xcd, limit - bump);
 #endif
     }
 
     void setBump(void *ptr) {
-        JS_ASSERT(base() <= ptr);
+        JS_ASSERT(bumpBase() <= ptr);
         JS_ASSERT(ptr <= limit);
         DebugOnly<char *> prevBump = bump;
         bump = static_cast<char *>(ptr);
         if (prevBump < bump)
             clobberUnused();
     }
 
   public:
     BumpChunk *next() const { return next_; }
     void setNext(BumpChunk *succ) { next_ = succ; }
 
-    size_t used() const { return bump - base(); }
+    size_t used() const { return bump - bumpBase(); }
 
     void resetBump() {
-        setBump(reinterpret_cast<char *>(this) + sizeof(BumpChunk));
+        setBump(headerBase() + sizeof(BumpChunk));
     }
 
     void *mark() const { return bump; }
 
     void release(void *mark) {
         JS_ASSERT(contains(mark));
         JS_ASSERT(mark <= bump);
         setBump(mark);
     }
 
     bool contains(void *mark) const {
-        return base() <= mark && mark <= limit;
+        return bumpBase() <= mark && mark <= limit;
     }
 
-    bool canAlloc(size_t n) {
-        return AlignPtr(bump) + n <= limit;
-    }
-
-    bool canAllocUnaligned(size_t n) {
-        return bump + n <= limit;
-    }
+    bool canAlloc(size_t n);
+    bool canAllocUnaligned(size_t n);
 
     /* Try to perform an allocation of size |n|, return null if not possible. */
     JS_ALWAYS_INLINE
     void *tryAlloc(size_t n) {
         char *aligned = AlignPtr(bump);
         char *newBump = aligned + n;
+
         if (newBump > limit)
             return NULL;
 
+        /* Check for overflow. */
+        if (JS_UNLIKELY(newBump < bump))
+            return NULL;
+
+        JS_ASSERT(canAlloc(n)); /* Ensure consistency between "can" and "try". */
         setBump(newBump);
         return aligned;
     }
 
     void *tryAllocUnaligned(size_t n);
 
     void *allocInfallible(size_t n) {
         void *result = tryAlloc(n);
         JS_ASSERT(result);
         return result;
     }
 
     static BumpChunk *new_(size_t chunkSize);
-
-    static void delete_(BumpChunk *chunk) {
-#ifdef DEBUG
-        memset(chunk, 0xcd, sizeof(*chunk) + chunk->bumpSpaceSize);
-#endif
-        js_free(chunk);
-    }
+    static void delete_(BumpChunk *chunk);
 };
 
 } /* namespace detail */
 
 /*
  * LIFO bump allocator: used for phase-oriented and fast LIFO allocations.
  *
  * Note: |latest| is not necessary "last". We leave BumpChunks latent in the
--- a/js/src/frontend/ParseMaps.h
+++ b/js/src/frontend/ParseMaps.h
@@ -36,19 +36,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 ***** */
 
 #ifndef ParseMaps_h__
 #define ParseMaps_h__
 
-#include "jsvector.h"
-
-#include "mfbt/InlineMap.h"
+#include "ds/InlineMap.h"
+#include "js/HashTable.h"
 
 namespace js {
 
 /*
  * A pool that permits the reuse of the backing storage for the defn, index, or
  * defn-or-header (multi) maps.
  *
  * The pool owns all the maps that are given out, and is responsible for
new file mode 100644
--- /dev/null
+++ b/js/src/gc/Statistics.cpp
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey JavaScript engine.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+
+#include "jscntxt.h"
+#include "jsprobes.h"
+#include "jsutil.h"
+#include "jscrashformat.h"
+#include "jscrashreport.h"
+#include "prmjtime.h"
+
+#include "gc/Statistics.h"
+
+namespace js {
+namespace gcstats {
+
+Statistics::Statistics(JSRuntime *rt)
+  : runtime(rt)
+{
+    char *env = getenv("MOZ_GCTIMER");
+    if (!env || strcmp(env, "none") == 0) {
+        fp = NULL;
+        return;
+    }
+
+    if (strcmp(env, "stdout") == 0) {
+        fullFormat = false;
+        fp = stdout;
+    } else if (strcmp(env, "stderr") == 0) {
+        fullFormat = false;
+        fp = stderr;
+    } else {
+        fullFormat = true;
+
+        fp = fopen(env, "a");
+        JS_ASSERT(fp);
+
+        fprintf(fp, "     AppTime,  Total,   Wait,   Mark,  Sweep, FinObj,"
+                " FinStr, FinScr, FinShp, Destry,    End, +Chu, -Chu, T, Reason\n");
+    }
+
+    PodArrayZero(counts);
+
+    startupTime = PRMJ_Now();
+}
+
+Statistics::~Statistics()
+{
+    if (fp && fp != stdout && fp != stderr)
+        fclose(fp);
+}
+
+struct GCCrashData
+{
+    int isRegen;
+    int isCompartment;
+};
+
+void
+Statistics::beginGC(JSCompartment *comp, Reason reason)
+{
+    compartment = comp;
+
+    PodArrayZero(phaseStarts);
+    PodArrayZero(phaseEnds);
+    PodArrayZero(phaseTimes);
+
+    triggerReason = reason;
+
+    beginPhase(PHASE_GC);
+    Probes::GCStart(compartment);
+
+    GCCrashData crashData;
+    crashData.isRegen = runtime->shapeGen & SHAPE_OVERFLOW_BIT;
+    crashData.isCompartment = !!compartment;
+    crash::SaveCrashData(crash::JS_CRASH_TAG_GC, &crashData, sizeof(crashData));
+}
+
+double
+Statistics::t(Phase phase)
+{
+    return double(phaseTimes[phase]) / PRMJ_USEC_PER_MSEC;
+}
+
+double
+Statistics::beginDelay(Phase phase1, Phase phase2)
+{
+    return double(phaseStarts[phase1] - phaseStarts[phase2]) / PRMJ_USEC_PER_MSEC;
+}
+
+double
+Statistics::endDelay(Phase phase1, Phase phase2)
+{
+    return double(phaseEnds[phase1] - phaseEnds[phase2]) / PRMJ_USEC_PER_MSEC;
+}
+
+void
+Statistics::printStats()
+{
+    if (fullFormat) {
+        /*       App   , Total, Wait , Mark , Sweep, FinOb, FinSt, FinSc, FinSh, Destry, End */
+        fprintf(fp,
+                "%12.0f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, ",
+                double(phaseStarts[PHASE_GC] - startupTime) / PRMJ_USEC_PER_MSEC,
+                t(PHASE_GC),
+                beginDelay(PHASE_MARK, PHASE_GC),
+                t(PHASE_MARK), t(PHASE_SWEEP),
+                t(PHASE_SWEEP_OBJECT), t(PHASE_SWEEP_STRING),
+                t(PHASE_SWEEP_SCRIPT), t(PHASE_SWEEP_SHAPE),
+                t(PHASE_DESTROY),
+                endDelay(PHASE_GC, PHASE_DESTROY));
+
+        fprintf(fp, "%4d, %4d,", counts[STAT_NEW_CHUNK], counts[STAT_DESTROY_CHUNK]);
+        fprintf(fp, " %s, %s\n", compartment ? "C" : "G", ExplainReason(triggerReason));
+    } else {
+        fprintf(fp, "%f %f %f\n",
+                t(PHASE_GC), t(PHASE_MARK), t(PHASE_SWEEP));
+    }
+    fflush(fp);
+}
+
+void
+Statistics::endGC()
+{
+    Probes::GCEnd(compartment);
+    endPhase(PHASE_GC);
+    crash::SnapshotGCStack();
+
+    if (JSAccumulateTelemetryDataCallback cb = runtime->telemetryCallback) {
+        (*cb)(JS_TELEMETRY_GC_REASON, triggerReason);
+        (*cb)(JS_TELEMETRY_GC_IS_COMPARTMENTAL, compartment ? 1 : 0);
+        (*cb)(JS_TELEMETRY_GC_IS_SHAPE_REGEN,
+              runtime->shapeGen & SHAPE_OVERFLOW_BIT ? 1 : 0);
+        (*cb)(JS_TELEMETRY_GC_MS, t(PHASE_GC));
+        (*cb)(JS_TELEMETRY_GC_MARK_MS, t(PHASE_MARK));
+        (*cb)(JS_TELEMETRY_GC_SWEEP_MS, t(PHASE_SWEEP));
+    }
+
+    if (fp)
+        printStats();
+
+    PodArrayZero(counts);
+}
+
+void
+Statistics::beginPhase(Phase phase)
+{
+    phaseStarts[phase] = PRMJ_Now();
+
+    if (phase == gcstats::PHASE_SWEEP) {
+        Probes::GCStartSweepPhase(NULL);
+        if (!compartment) {
+            for (JSCompartment **c = runtime->compartments.begin();
+                 c != runtime->compartments.end(); ++c)
+            {
+                Probes::GCStartSweepPhase(*c);
+            }
+        }
+    }
+}
+
+void
+Statistics::endPhase(Phase phase)
+{
+    phaseEnds[phase] = PRMJ_Now();
+    phaseTimes[phase] += phaseEnds[phase] - phaseStarts[phase];
+
+    if (phase == gcstats::PHASE_SWEEP) {
+        if (!compartment) {
+            for (JSCompartment **c = runtime->compartments.begin();
+                 c != runtime->compartments.end(); ++c)
+            {
+                Probes::GCEndSweepPhase(*c);
+            }
+        }
+        Probes::GCEndSweepPhase(NULL);
+    }
+}
+
+} /* namespace gcstats */
+} /* namespace js */
new file mode 100644
--- /dev/null
+++ b/js/src/gc/Statistics.h
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sw=4 et tw=78:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is SpiderMonkey JavaScript engine.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsgc_statistics_h___
+#define jsgc_statistics_h___
+
+#include <string.h>
+
+#include "jspubtd.h"
+#include "jsutil.h"
+
+struct JSCompartment;
+
+namespace js {
+namespace gcstats {
+
+enum Reason {
+    PUBLIC_API,
+    MAYBEGC,
+    LASTCONTEXT,
+    DESTROYCONTEXT,
+    LASTDITCH,
+    TOOMUCHMALLOC,
+    ALLOCTRIGGER,
+    CHUNK,
+    SHAPE,
+    REFILL
+};
+static const int NUM_REASONS = REFILL + 1;
+
+static inline const char *
+ExplainReason(Reason r)
+{
+    static const char *strs[] = {"  API", "Maybe", "LastC", "DestC", "LastD",
+                                 "Mallc", "Alloc", "Chunk", "Shape", "Refil"};
+
+    JS_ASSERT(strcmp(strs[SHAPE], "Shape") == 0 &&
+              sizeof(strs) / sizeof(strs[0]) == NUM_REASONS);
+
+    return strs[r];
+}
+
+enum Phase {
+    PHASE_GC,
+    PHASE_MARK,
+    PHASE_SWEEP,
+    PHASE_SWEEP_OBJECT,
+    PHASE_SWEEP_STRING,
+    PHASE_SWEEP_SCRIPT,
+    PHASE_SWEEP_SHAPE,
+    PHASE_DESTROY,
+
+    PHASE_LIMIT
+};
+
+enum Stat {
+    STAT_NEW_CHUNK,
+    STAT_DESTROY_CHUNK,
+
+    STAT_LIMIT
+};
+
+struct Statistics {
+    Statistics(JSRuntime *rt);
+    ~Statistics();
+
+    void beginGC(JSCompartment *comp, Reason reason);
+    void endGC();
+
+    void beginPhase(Phase phase);
+    void endPhase(Phase phase);
+
+    void count(Stat s) {
+        JS_ASSERT(s < STAT_LIMIT);
+        counts[s]++;
+    }
+
+  private:
+    JSRuntime *runtime;
+
+    uint64 startupTime;
+
+    FILE *fp;
+    bool fullFormat;
+
+    Reason triggerReason;
+    JSCompartment *compartment;
+
+    uint64 phaseStarts[PHASE_LIMIT];
+    uint64 phaseEnds[PHASE_LIMIT];
+    uint64 phaseTimes[PHASE_LIMIT];
+    unsigned int counts[STAT_LIMIT];
+
+    double t(Phase phase);
+    double beginDelay(Phase phase1, Phase phase2);
+    double endDelay(Phase phase1, Phase phase2);
+    void printStats();
+};
+
+struct AutoGC {
+    AutoGC(Statistics &stats, JSCompartment *comp, Reason reason JS_GUARD_OBJECT_NOTIFIER_PARAM)
+      : stats(stats) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginGC(comp, reason); }
+    ~AutoGC() { stats.endGC(); }
+
+    Statistics &stats;
+    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+struct AutoPhase {
+    AutoPhase(Statistics &stats, Phase phase JS_GUARD_OBJECT_NOTIFIER_PARAM)
+      : stats(stats), phase(phase) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginPhase(phase); }
+    ~AutoPhase() { stats.endPhase(phase); }
+
+    Statistics &stats;
+    Phase phase;
+    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
+} /* namespace gcstats */
+} /* namespace js */
+
+#endif /* jsgc_statistics_h___ */
--- a/js/src/jsanalyze.h
+++ b/js/src/jsanalyze.h
@@ -40,19 +40,19 @@
 
 #ifndef jsanalyze_h___
 #define jsanalyze_h___
 
 #include "jscompartment.h"
 #include "jscntxt.h"
 #include "jsinfer.h"
 #include "jsscript.h"
-#include "jstl.h"
 
 #include "ds/LifoAlloc.h"
+#include "js/TemplateLib.h"
 
 struct JSScript;
 
 /* Forward declaration of downstream register allocations computed for join points. */
 namespace js { namespace mjit { struct RegisterAllocation; } }
 
 namespace js {
 namespace analyze {
--- a/js/src/jsapi-tests/testThreadGC.cpp
+++ b/js/src/jsapi-tests/testThreadGC.cpp
@@ -159,17 +159,17 @@ BEGIN_TEST(testThreadGC_bug590533)
 
         if (setGCIsNeeded) {
             /*
              * Use JS internal API to set the GC trigger flag after we know
              * that the child is in a request and is about to run an infinite
              * loop. Then run the GC with JSRuntime->gcIsNeeded flag set.
              */
             js::AutoLockGC lock(rt);
-            js::TriggerGC(rt);
+            js::TriggerGC(rt, js::gcstats::PUBLIC_API);
         }
 
         JS_GC(cx);
 
         PR_Lock(shared->lock);
         shared->childShouldStop = true;
         while (shared->childState == SharedData::CHILD_RUNNING) {
             JS_TriggerOperationCallback(shared->childContext);
--- a/js/src/jsapi-tests/tests.h
+++ b/js/src/jsapi-tests/tests.h
@@ -35,17 +35,20 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "jsapi.h"
 #include "jsprvtd.h"
-#include "jsvector.h"
+#include "jsalloc.h"
+
+#include "js/Vector.h"
+
 #include <errno.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 class jsvalRoot
 {
   public:
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -78,30 +78,28 @@
 #include "jsprobes.h"
 #include "jsproxy.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
 #include "jstracer.h"
 #include "prmjtime.h"
 #include "jsstaticcheck.h"
-#include "jsvector.h"
 #include "jsweakmap.h"
 #include "jswrapper.h"
 #include "jstypedarray.h"
 
 #include "ds/LifoAlloc.h"
 #include "builtin/RegExp.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
-#include "assembler/wtf/Platform.h"
 
 #include "vm/RegExpObject-inl.h"
 #include "vm/Stack-inl.h"
 #include "vm/String-inl.h"
 
 #if ENABLE_YARR_JIT
 #include "assembler/jit/ExecutableAllocator.h"
 #include "methodjit/Logging.h"
@@ -659,16 +657,17 @@ JSRuntime::JSRuntime()
     gcNumber(0),
     gcMarkingTracer(NULL),
     gcChunkAllocationSinceLastGC(false),
     gcNextFullGCTime(0),
     gcJitReleaseTime(0),
     gcMode(JSGC_MODE_GLOBAL),
     gcIsNeeded(0),
     gcWeakMapList(NULL),
+    gcStats(thisFromCtor()),
     gcTriggerCompartment(NULL),
     gcCurrentCompartment(NULL),
     gcCheckCompartment(NULL),
     gcPoke(false),
     gcMarkAndSweep(false),
     gcRunning(false),
     gcRegenShapes(false),
 #ifdef JS_GC_ZEAL
@@ -691,26 +690,27 @@ JSRuntime::JSRuntime()
     hadOutOfMemory(false),
     data(NULL),
 #ifdef JS_THREADSAFE
     gcLock(NULL),
     gcDone(NULL),
     requestDone(NULL),
     requestCount(0),
     gcThread(NULL),
-    gcHelperThread(this),
+    gcHelperThread(thisFromCtor()),
     rtLock(NULL),
 # ifdef DEBUG
     rtLockOwner(0),
 # endif
     stateChange(NULL),
 #endif
     debuggerMutations(0),
     securityCallbacks(NULL),
     structuredCloneCallbacks(NULL),
+    telemetryCallback(NULL),
     propertyRemovals(0),
     scriptFilenameTable(NULL),
 #ifdef JS_THREADSAFE
     scriptFilenameTableLock(NULL),
 #endif
     thousandsSeparator(0),
     decimalSeparator(0),
     numGrouping(0),
@@ -2701,24 +2701,22 @@ JS_IsGCMarkingTracer(JSTracer *trc)
 JS_PUBLIC_API(void)
 JS_CompartmentGC(JSContext *cx, JSCompartment *comp)
 {
     /* We cannot GC the atoms compartment alone; use a full GC instead. */
     JS_ASSERT(comp != cx->runtime->atomsCompartment);
 
     LeaveTrace(cx);
 
-    GCREASON(PUBLIC_API);
-    js_GC(cx, comp, GC_NORMAL);
+    js_GC(cx, comp, GC_NORMAL, gcstats::PUBLIC_API);
 }
 
 JS_PUBLIC_API(void)
 JS_GC(JSContext *cx)
 {
-    GCREASON(PUBLIC_API);
     JS_CompartmentGC(cx, NULL);
 }
 
 JS_PUBLIC_API(void)
 JS_MaybeGC(JSContext *cx)
 {
     LeaveTrace(cx);
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -42,19 +42,20 @@
 #define jsapi_h___
 /*
  * JavaScript API.
  */
 #include <stddef.h>
 #include <stdio.h>
 #include "js-config.h"
 #include "jspubtd.h"
-#include "jsutil.h"
 #include "jsval.h"
 
+#include "js/Utility.h"
+
 /************************************************************************/
 
 /* JS::Value can store a full int32. */
 #define JSVAL_INT_BITS          32
 #define JSVAL_INT_MIN           ((jsint)0x80000000)
 #define JSVAL_INT_MAX           ((jsint)0x7fffffff)
 
 /************************************************************************/
@@ -1692,16 +1693,27 @@ extern JS_PUBLIC_DATA(jsid) JSID_EMPTY;
  * If you set this flag in a JSFunctionSpec struct's flags initializer, then
  * that struct must live at least as long as the native static method object
  * created due to this flag by JS_DefineFunctions or JS_InitClass.  Typically
  * JSFunctionSpec structs are allocated in static arrays.
  */
 #define JSFUN_GENERIC_NATIVE    JSFUN_LAMBDA
 
 /*
+ * The first call to JS_CallOnce by any thread in a process will call 'func'.
+ * Later calls to JS_CallOnce with the same JSCallOnceType object will be
+ * suppressed.
+ *
+ * Equivalently: each distinct JSCallOnceType object will allow one JS_CallOnce
+ * to invoke its JSInitCallback.
+ */
+extern JS_PUBLIC_API(JSBool)
+JS_CallOnce(JSCallOnceType *once, JSInitCallback func);
+
+/*
  * Microseconds since the epoch, midnight, January 1, 1970 UTC.  See the
  * comment in jstypes.h regarding safe int64 usage.
  */
 extern JS_PUBLIC_API(int64)
 JS_Now(void);
 
 /* Don't want to export data, so provide accessors for non-inline jsvals. */
 extern JS_PUBLIC_API(jsval)
deleted file mode 100644
--- a/js/src/jsarena.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * Lifetime-based fast allocation, inspired by much prior art, including
- * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
- * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
- */
-#include <stdlib.h>
-#include <string.h>
-#include "jsalloc.h"
-#include "jstypes.h"
-#include "jsstdint.h"
-#include "jsbit.h"
-#include "jsarena.h"
-#include "jsprvtd.h"
-
-using namespace js;
-
-/* If JSArena's length is a multiple of 8, that ensures its payload is 8-aligned. */
-JS_STATIC_ASSERT(sizeof(JSArena) % 8 == 0);
-
-JS_PUBLIC_API(void)
-JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, size_t align)
-{
-    /* Restricting ourselves to some simple alignments keeps things simple. */
-    if (align == 1 || align == 2 || align == 4 || align == 8) {
-        pool->mask = align - 1;
-    } else {
-        /* This shouldn't happen, but set pool->mask reasonably if it does. */
-        JS_NOT_REACHED("JS_InitArenaPool: bad align");
-        pool->mask = 7;
-    }
-    pool->first.next = NULL;
-    /* pool->first is a zero-sized dummy arena that's never allocated from. */
-    pool->first.base = pool->first.avail = pool->first.limit =
-        JS_ARENA_ALIGN(pool, &pool->first + 1);
-    pool->current = &pool->first;
-    pool->arenasize = size;
-}
-
-JS_PUBLIC_API(void *)
-JS_ArenaAllocate(JSArenaPool *pool, size_t nb)
-{
-    /*
-     * Search pool from current forward till we find or make enough space.
-     *
-     * NB: subtract nb from a->limit in the loop condition, instead of adding
-     * nb to a->avail, to avoid overflow (possible when running a 32-bit
-     * program on a 64-bit system where the kernel maps the heap up against the
-     * top of the 32-bit address space, see bug 279273).  Note that this
-     * necessitates a comparison between nb and a->limit that looks like a
-     * (conceptual) type error but isn't.
-     */
-    JS_ASSERT((nb & pool->mask) == 0);
-    JSArena *a;
-    /*
-     * Comparing nb to a->limit looks like a (conceptual) type error, but it's
-     * necessary to avoid wrap-around.  Yuk.
-     */
-    for (a = pool->current; nb > a->limit || a->avail > a->limit - nb; pool->current = a) {
-        JSArena **ap = &a->next;
-        if (!*ap) {
-            /* Not enough space in pool, so we must malloc. */
-            size_t gross = sizeof(JSArena) + JS_MAX(nb, pool->arenasize);
-            a = (JSArena *) OffTheBooks::malloc_(gross);
-            if (!a)
-                return NULL;
-
-            a->next = NULL;
-            a->base = a->avail = jsuword(a) + sizeof(JSArena);
-            /*
-             * Because malloc returns 8-aligned pointers and sizeof(JSArena) is
-             * a multiple of 8, a->base will always be 8-aligned, which should
-             * suffice for any valid pool.
-             */
-            JS_ASSERT(a->base == JS_ARENA_ALIGN(pool, a->base));
-            a->limit = (jsuword)a + gross;
-
-            *ap = a;
-            continue;
-        }
-        a = *ap;        /* move to next arena */
-    }
-
-    void* p = (void *)a->avail;
-    a->avail += nb;
-    JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
-    return p;
-}
-
-JS_PUBLIC_API(void *)
-JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr)
-{
-    /* If we've called JS_ArenaRealloc, the new size must be bigger than pool->arenasize. */
-    JS_ASSERT(size + incr > pool->arenasize);
-
-    /* Find the arena containing |p|. */
-    JSArena *a;
-    JSArena **ap = &pool->first.next;
-    while (true) {
-        a = *ap;
-        if (JS_IS_IN_ARENA(a, p))
-            break;
-        JS_ASSERT(a != pool->current);
-        ap = &a->next;
-    }
-    /* If we've called JS_ArenaRealloc, p must be at the start of an arena. */
-    JS_ASSERT(a->base == jsuword(p));
-
-    size_t gross = sizeof(JSArena) + JS_ARENA_ALIGN(pool, size + incr);
-    a = (JSArena *) OffTheBooks::realloc_(a, gross);
-    if (!a)
-        return NULL;
-
-    a->base = jsuword(a) + sizeof(JSArena);
-    a->avail = a->limit = jsuword(a) + gross;
-    /*
-     * Because realloc returns 8-aligned pointers and sizeof(JSArena) is a
-     * multiple of 8, a->base will always be 8-aligned, which should suffice
-     * for any valid pool.
-     */
-    JS_ASSERT(a->base == JS_ARENA_ALIGN(pool, a->base));
-
-    if (a != *ap) {
-        /* realloc moved the allocation: update other pointers to a. */
-        if (pool->current == *ap)
-            pool->current = a;
-        *ap = a;
-    }
-
-    return (void *)a->base;
-}
-
-JS_PUBLIC_API(void *)
-JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr)
-{
-    void *newp;
-
-    /*
-     * If p points to an oversized allocation, it owns an entire arena, so we
-     * can simply realloc the arena.
-     */
-    if (size > pool->arenasize)
-        return JS_ArenaRealloc(pool, p, size, incr);
-
-    JS_ARENA_ALLOCATE(newp, pool, size + incr);
-    if (newp)
-        memcpy(newp, p, size);
-    return newp;
-}
-
-/*
- * Free tail arenas linked after head, which may not be the true list head.
- * Reset pool->current to point to head in case it pointed at a tail arena.
- */
-static void
-FreeArenaList(JSArenaPool *pool, JSArena *head)
-{
-    JSArena **ap, *a;
-
-    ap = &head->next;
-    a = *ap;
-    if (!a)
-        return;
-
-#ifdef DEBUG
-    do {
-        JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
-        a->avail = a->base;
-        JS_CLEAR_UNUSED(a);
-    } while ((a = a->next) != NULL);
-    a = *ap;
-#endif
-
-    do {
-        *ap = a->next;
-        JS_CLEAR_ARENA(a);
-        UnwantedForeground::free_(a);
-    } while ((a = *ap) != NULL);
-
-    pool->current = head;
-}
-
-JS_PUBLIC_API(void)
-JS_ArenaRelease(JSArenaPool *pool, char *mark)
-{
-    JSArena *a;
-
-    for (a = &pool->first; a; a = a->next) {
-        JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
-
-        if (JS_IS_IN_ARENA(a, mark)) {
-            a->avail = JS_ARENA_ALIGN(pool, mark);
-            JS_ASSERT(a->avail <= a->limit);
-            FreeArenaList(pool, a);
-            return;
-        }
-    }
-}
-
-JS_PUBLIC_API(void)
-JS_FreeArenaPool(JSArenaPool *pool)
-{
-    FreeArenaList(pool, &pool->first);
-}
-
-JS_PUBLIC_API(void)
-JS_FinishArenaPool(JSArenaPool *pool)
-{
-    FreeArenaList(pool, &pool->first);
-}
-
-JS_PUBLIC_API(void)
-JS_ArenaFinish()
-{
-}
-
-JS_PUBLIC_API(void)
-JS_ArenaShutDown(void)
-{
-}
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -104,34 +104,32 @@
 
 #include "jstypes.h"
 #include "jsstdint.h"
 #include "jsutil.h"
 
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsatom.h"
-#include "jsbit.h"
 #include "jsbool.h"
 #include "jsbuiltins.h"
 #include "jscntxt.h"
 #include "jsversion.h"
 #include "jsfun.h"
 #include "jsgc.h"
 #include "jsgcmark.h"
 #include "jsinterp.h"
 #include "jsiter.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsscope.h"
 #include "jsstr.h"
 #include "jsstaticcheck.h"
 #include "jstracer.h"
-#include "jsvector.h"
 #include "jswrapper.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/StubCalls.h"
 #include "methodjit/StubCalls-inl.h"
 
 #include "vm/ArgumentsObject.h"
 
 #include "jsarrayinlines.h"
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -47,17 +47,16 @@
 
 #include "jstypes.h"
 #include "jsstdint.h"
 #include "jsutil.h"
 #include "jshash.h"
 #include "jsprf.h"
 #include "jsapi.h"
 #include "jsatom.h"
-#include "jsbit.h"
 #include "jscntxt.h"
 #include "jsgc.h"
 #include "jsgcmark.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsparse.h"
 #include "jsstr.h"
 #include "jsversion.h"
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -37,23 +37,24 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsatom_h___
 #define jsatom_h___
 
 #include <stddef.h>
 #include "jsversion.h"
+#include "jsalloc.h"
 #include "jsapi.h"
 #include "jsprvtd.h"
 #include "jshash.h"
-#include "jshashtable.h"
 #include "jspubtd.h"
 #include "jslock.h"
 
+#include "js/HashTable.h"
 #include "vm/String.h"
 
 /* Engine-internal extensions of jsid */
 
 static JS_ALWAYS_INLINE jsid
 JSID_FROM_BITS(size_t bits)
 {
     jsid id;
deleted file mode 100644
--- a/js/src/jsbit.h
+++ /dev/null
@@ -1,305 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code, released
- * March 31, 1998.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef jsbit_h___
-#define jsbit_h___
-
-#include "jstypes.h"
-#include "jscompat.h"
-#include "jsutil.h"
-
-JS_BEGIN_EXTERN_C
-
-/*
-** A jsbitmap_t is a long integer that can be used for bitmaps
-*/
-typedef jsuword     jsbitmap_t;     /* NSPR name, a la Unix system types */
-typedef jsbitmap_t  jsbitmap;       /* JS-style scalar typedef name */
-
-#define JS_BITMAP_SIZE(bits)    (JS_HOWMANY(bits, JS_BITS_PER_WORD) *         \
-                                 sizeof(jsbitmap))
-
-#define JS_TEST_BIT(_map,_bit)  ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &      \
-                                 ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
-#define JS_SET_BIT(_map,_bit)   ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |=     \
-                                 ((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
-#define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &=     \
-                                 ~((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
-
-/*
-** Compute the log of the least power of 2 greater than or equal to n
-*/
-extern JS_PUBLIC_API(JSIntn) JS_CeilingLog2(JSUint32 i);
-
-/*
-** Compute the log of the greatest power of 2 less than or equal to n
-*/
-extern JS_PUBLIC_API(JSIntn) JS_FloorLog2(JSUint32 i);
-
-/*
- * Replace bit-scanning code sequences with CPU-specific instructions to
- * speedup calculations of ceiling/floor log2.
- *
- * With GCC 3.4 or later we can use __builtin_clz for that, see bug 327129.
- *
- * SWS: Added MSVC intrinsic bitscan support.  See bugs 349364 and 356856.
- */
-#if defined(_WIN32) && (_MSC_VER >= 1300) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
-
-unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask);
-unsigned char _BitScanReverse(unsigned long * Index, unsigned long Mask);
-# pragma intrinsic(_BitScanForward,_BitScanReverse)
-
-__forceinline static int
-__BitScanForward32(unsigned int val)
-{
-    unsigned long idx;
-
-    _BitScanForward(&idx, (unsigned long)val);
-    return (int)idx;
-}
-__forceinline static int
-__BitScanReverse32(unsigned int val)
-{
-    unsigned long idx;
-
-    _BitScanReverse(&idx, (unsigned long)val);
-    return (int)(31-idx);
-}
-# define js_bitscan_ctz32(val)  __BitScanForward32(val)
-# define js_bitscan_clz32(val)  __BitScanReverse32(val)
-# define JS_HAS_BUILTIN_BITSCAN32
-
-#if defined(_M_AMD64) || defined(_M_X64)
-unsigned char _BitScanForward64(unsigned long * Index, unsigned __int64 Mask);
-unsigned char _BitScanReverse64(unsigned long * Index, unsigned __int64 Mask);
-# pragma intrinsic(_BitScanForward64,_BitScanReverse64)
-
-__forceinline static int
-__BitScanForward64(unsigned __int64 val)
-{
-    unsigned long idx;
-
-    _BitScanForward64(&idx, val);
-    return (int)idx;
-}
-__forceinline static int
-__BitScanReverse64(unsigned __int64 val)
-{
-    unsigned long idx;
-
-    _BitScanReverse64(&idx, val);
-    return (int)(63-idx);
-}
-# define js_bitscan_ctz64(val)  __BitScanForward64(val)
-# define js_bitscan_clz64(val)  __BitScanReverse64(val)
-# define JS_HAS_BUILTIN_BITSCAN64
-#endif
-#elif (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-
-# define js_bitscan_ctz32(val)  __builtin_ctz(val)
-# define js_bitscan_clz32(val)  __builtin_clz(val)
-# define JS_HAS_BUILTIN_BITSCAN32
-# if (JS_BYTES_PER_WORD == 8)
-#  define js_bitscan_ctz64(val)  __builtin_ctzll(val)
-#  define js_bitscan_clz64(val)  __builtin_clzll(val)
-#  define JS_HAS_BUILTIN_BITSCAN64
-# endif
-
-#endif
-
-/*
-** Macro version of JS_CeilingLog2: Compute the log of the least power of
-** 2 greater than or equal to _n. The result is returned in _log2.
-*/
-#ifdef JS_HAS_BUILTIN_BITSCAN32
-/*
- * Use intrinsic function or count-leading-zeros to calculate ceil(log2(_n)).
- * The macro checks for "n <= 1" and not "n != 0" as js_bitscan_clz32(0) is
- * undefined.
- */
-# define JS_CEILING_LOG2(_log2,_n)                                            \
-    JS_BEGIN_MACRO                                                            \
-        unsigned int j_ = (unsigned int)(_n);                                 \
-        (_log2) = (j_ <= 1 ? 0 : 32 - js_bitscan_clz32(j_ - 1));              \
-    JS_END_MACRO
-#else
-# define JS_CEILING_LOG2(_log2,_n)                                            \
-    JS_BEGIN_MACRO                                                            \
-        JSUint32 j_ = (JSUint32)(_n);                                         \
-        (_log2) = 0;                                                          \
-        if ((j_) & ((j_)-1))                                                  \
-            (_log2) += 1;                                                     \
-        if ((j_) >> 16)                                                       \
-            (_log2) += 16, (j_) >>= 16;                                       \
-        if ((j_) >> 8)                                                        \
-            (_log2) += 8, (j_) >>= 8;                                         \
-        if ((j_) >> 4)                                                        \
-            (_log2) += 4, (j_) >>= 4;                                         \
-        if ((j_) >> 2)                                                        \
-            (_log2) += 2, (j_) >>= 2;                                         \
-        if ((j_) >> 1)                                                        \
-            (_log2) += 1;                                                     \
-    JS_END_MACRO
-#endif
-
-/*
-** Macro version of JS_FloorLog2: Compute the log of the greatest power of
-** 2 less than or equal to _n. The result is returned in _log2.
-**
-** This is equivalent to finding the highest set bit in the word.
-*/
-#ifdef JS_HAS_BUILTIN_BITSCAN32
-/*
- * Use js_bitscan_clz32 or count-leading-zeros to calculate floor(log2(_n)).
- * Since js_bitscan_clz32(0) is undefined, the macro set the loweset bit to 1
- * to ensure 0 result when _n == 0.
- */
-# define JS_FLOOR_LOG2(_log2,_n)                                              \
-    JS_BEGIN_MACRO                                                            \
-        (_log2) = 31 - js_bitscan_clz32(((unsigned int)(_n)) | 1);            \
-    JS_END_MACRO
-#else
-# define JS_FLOOR_LOG2(_log2,_n)                                              \
-    JS_BEGIN_MACRO                                                            \
-        JSUint32 j_ = (JSUint32)(_n);                                         \
-        (_log2) = 0;                                                          \
-        if ((j_) >> 16)                                                       \
-            (_log2) += 16, (j_) >>= 16;                                       \
-        if ((j_) >> 8)                                                        \
-            (_log2) += 8, (j_) >>= 8;                                         \
-        if ((j_) >> 4)                                                        \
-            (_log2) += 4, (j_) >>= 4;                                         \
-        if ((j_) >> 2)                                                        \
-            (_log2) += 2, (j_) >>= 2;                                         \
-        if ((j_) >> 1)                                                        \
-            (_log2) += 1;                                                     \
-    JS_END_MACRO
-#endif
-
-/*
- * Internal function.
- * Compute the log of the least power of 2 greater than or equal to n. This is
- * a version of JS_CeilingLog2 that operates on unsigned integers with
- * CPU-dependant size.
- */
-#define JS_CEILING_LOG2W(n) ((n) <= 1 ? 0 : 1 + JS_FLOOR_LOG2W((n) - 1))
-
-/*
- * Internal function.
- * Compute the log of the greatest power of 2 less than or equal to n.
- * This is a version of JS_FloorLog2 that operates on unsigned integers with
- * CPU-dependant size and requires that n != 0.
- */
-#define JS_FLOOR_LOG2W(n) (JS_ASSERT((n) != 0), js_FloorLog2wImpl(n))
-
-#if JS_BYTES_PER_WORD == 4
-
-# ifdef JS_HAS_BUILTIN_BITSCAN32
-#  define js_FloorLog2wImpl(n)                                                \
-    ((size_t)(JS_BITS_PER_WORD - 1 - js_bitscan_clz32(n)))
-# else
-#  define js_FloorLog2wImpl(n) ((size_t)JS_FloorLog2(n))
-#endif
-
-#elif JS_BYTES_PER_WORD == 8
-
-# ifdef JS_HAS_BUILTIN_BITSCAN64
-#  define js_FloorLog2wImpl(n)                                                \
-    ((size_t)(JS_BITS_PER_WORD - 1 - js_bitscan_clz64(n)))
-# else
-extern size_t js_FloorLog2wImpl(size_t n);
-# endif
-
-#else
-
-# error "NOT SUPPORTED"
-
-#endif
-
-namespace js {
-
-inline size_t
-CountTrailingZeros(size_t n)
-{
-    JS_ASSERT(n != 0);
-#if JS_BYTES_PER_WORD != 4 && JS_BYTES_PER_WORD != 8
-# error "NOT SUPPORTED"
-#endif
-
-#if JS_BYTES_PER_WORD == 4 && defined JS_HAS_BUILTIN_BITSCAN32
-    return js_bitscan_ctz32(n);
-#elif JS_BYTES_PER_WORD == 8 && defined JS_HAS_BUILTIN_BITSCAN64
-    return js_bitscan_ctz64(n);
-#else
-    size_t count = 0;
-# if JS_BYTES_PER_WORD == 8
-    if (!(n & size_t(0xFFFFFFFFU))) { count += 32; n >>= 32; }
-# endif
-    if (!(n & 0xFFFF)) { count += 16; n >>= 16; }
-    if (!(n & 0xFF))   { count += 8;  n >>= 8; }
-    if (!(n & 0xF))    { count += 4;  n >>= 4; }
-    if (!(n & 0x3))    { count += 2;  n >>= 2; }
-    if (!(n & 0x1))    { count += 1;  n >>= 1; }
-    return count + 1 - (n & 0x1);
-#endif
-}
-
-}
-
-/*
- * Macros for rotate left. There is no rotate operation in the C Language so
- * the construct (a << 4) | (a >> 28) is used instead. Most compilers convert
- * this to a rotate instruction but some versions of MSVC don't without a
- * little help.  To get MSVC to generate a rotate instruction, we have to use
- * the _rotl intrinsic and use a pragma to make _rotl inline.
- *
- * MSVC in VS2005 will do an inline rotate instruction on the above construct.
- */
-
-#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \
-    defined(_M_X64))
-#include <stdlib.h>
-#pragma intrinsic(_rotl)
-#define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits)
-#else
-#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
-#endif
-
-JS_END_EXTERN_C
-#endif /* jsbit_h___ */
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -48,17 +48,16 @@
 #include "jsbool.h"
 #include "jscntxt.h"
 #include "jsinfer.h"
 #include "jsversion.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsstr.h"
-#include "jsvector.h"
 
 #include "vm/GlobalObject.h"
 
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsstrinlines.h"
 
 using namespace js;
--- a/js/src/jsbuiltins.cpp
+++ b/js/src/jsbuiltins.cpp
@@ -53,17 +53,16 @@
 #include "jsmath.h"
 #include "jsnum.h"
 #include "prmjtime.h"
 #include "jsdate.h"
 #include "jsscope.h"
 #include "jsstr.h"
 #include "jsbuiltins.h"
 #include "jstracer.h"
-#include "jsvector.h"
 
 #include "jsatominlines.h"
 #include "jscntxtinlines.h"
 #include "jsnuminlines.h"
 #include "jsobjinlines.h"
 #include "jsscopeinlines.h"
 
 using namespace avmplus;
--- a/js/src/jsclone.h
+++ b/js/src/jsclone.h
@@ -36,19 +36,20 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsclone_h___
 #define jsclone_h___
 
 #include "jsapi.h"
 #include "jscntxt.h"
-#include "jshashtable.h"
 #include "jsstdint.h"
-#include "jsvector.h"
+
+#include "js/HashTable.h"
+#include "js/Vector.h"
 
 JS_FRIEND_API(uint64_t)
 js_GetSCOffset(JSStructuredCloneWriter* writer);
 
 namespace js {
 
 bool
 WriteStructuredClone(JSContext *cx, const Value &v, uint64_t **bufp, size_t *nbytesp,
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -528,31 +528,28 @@ js_DestroyContext(JSContext *cx, JSDestr
          * request to end.  We'll let it run below, just before we do the truly
          * final GC and then free atom state.
          */
         while (cx->outstandingRequests != 0)
             JS_EndRequest(cx);
 #endif
 
         if (last) {
-            GCREASON(LASTCONTEXT);
-            js_GC(cx, NULL, GC_LAST_CONTEXT);
+            js_GC(cx, NULL, GC_LAST_CONTEXT, gcstats::LASTCONTEXT);
 
             /* Take the runtime down, now that it has no contexts or atoms. */
             JS_LOCK_GC(rt);
             rt->state = JSRTS_DOWN;
             JS_NOTIFY_ALL_CONDVAR(rt->stateChange);
         } else {
-            if (mode == JSDCM_FORCE_GC) {
-                GCREASON(DESTROYCONTEXT);
-                js_GC(cx, NULL, GC_NORMAL);
-            } else if (mode == JSDCM_MAYBE_GC) {
-                GCREASON(DESTROYCONTEXT);
+            if (mode == JSDCM_FORCE_GC)
+                js_GC(cx, NULL, GC_NORMAL, gcstats::DESTROYCONTEXT);
+            else if (mode == JSDCM_MAYBE_GC)
                 JS_MaybeGC(cx);
-            }
+
             JS_LOCK_GC(rt);
             js_WaitForGC(rt);
         }
     }
 #ifdef JS_THREADSAFE
 #ifdef DEBUG
     JSThread *t = cx->thread();
 #endif
@@ -1160,17 +1157,17 @@ js_InvokeOperationCallback(JSContext *cx
     JS_LOCK_GC(rt);
     td->interruptFlags = 0;
 #ifdef JS_THREADSAFE
     JS_ATOMIC_DECREMENT(&rt->interruptCounter);
 #endif
     JS_UNLOCK_GC(rt);
 
     if (rt->gcIsNeeded) {
-        js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL);
+        js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, rt->gcTriggerReason);
 
         /*
          * On trace we can exceed the GC quota, see comments in NewGCArena. So
          * we check the quota and report OOM here when we are off trace.
          */
         if (checkOutOfMemory(rt)) {
 #ifdef JS_THREADSAFE
             /*
@@ -1337,16 +1334,17 @@ DSTOffsetCache::DSTOffsetCache()
 }
 
 JSContext::JSContext(JSRuntime *rt)
   : defaultVersion(JSVERSION_DEFAULT),
     hasVersionOverride(false),
     throwing(false),
     exception(UndefinedValue()),
     runOptions(0),
+    reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
     localeCallbacks(NULL),
     resolvingList(NULL),
     generatingError(false),
 #if JS_STACK_GROWTH_DIRECTION > 0
     stackLimit((jsuword)-1),
 #else
     stackLimit(0),
 #endif
@@ -1509,18 +1507,17 @@ JSRuntime::onTooMuchMalloc()
     AutoLockGC lock(this);
 
     /*
      * We can be called outside a request and can race against a GC that
      * mutates the JSThread set during the sweeping phase.
      */
     js_WaitForGC(this);
 #endif
-    GCREASON(TOOMUCHMALLOC);
-    TriggerGC(this);
+    TriggerGC(this, gcstats::TOOMUCHMALLOC);
 }
 
 JS_FRIEND_API(void *)
 JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
 {
     /*
      * Retry when we are done with the background sweeping and have stopped
      * all the allocations and released the empty GC chunks.
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -40,31 +40,33 @@
 
 #ifndef jscntxt_h___
 #define jscntxt_h___
 /*
  * JS execution context.
  */
 #include <string.h>
 
+#include "jsfriendapi.h"
 #include "jsprvtd.h"
 #include "jsatom.h"
 #include "jsclist.h"
 #include "jsdhash.h"
 #include "jsgc.h"
 #include "jsgcchunk.h"
-#include "jshashtable.h"
 #include "jspropertycache.h"
 #include "jspropertytree.h"
 #include "jsstaticcheck.h"
 #include "jsutil.h"
-#include "jsvector.h"
 #include "prmjtime.h"
 
 #include "ds/LifoAlloc.h"
+#include "gc/Statistics.h"
+#include "js/HashTable.h"
+#include "js/Vector.h"
 #include "vm/StackSpace.h"
 
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
 #pragma warning(push)
 #pragma warning(disable:4355) /* Silence warning about "this" used in base member initializer list */
 #endif
@@ -425,16 +427,20 @@ struct JSRuntime {
     uint32              gcNumber;
     js::GCMarker        *gcMarkingTracer;
     bool                gcChunkAllocationSinceLastGC;
     int64               gcNextFullGCTime;
     int64               gcJitReleaseTime;
     JSGCMode            gcMode;
     volatile jsuword    gcIsNeeded;
     js::WeakMapBase     *gcWeakMapList;
+    js::gcstats::Statistics gcStats;
+
+    /* The reason that an interrupt-triggered GC should be called. */
+    js::gcstats::Reason gcTriggerReason;
 
     /* Pre-allocated space for the GC mark stacks. Pointer type ensures alignment. */
     void                *gcMarkStackObjs[js::OBJECT_MARK_STACK_SIZE / sizeof(void *)];
     void                *gcMarkStackRopes[js::ROPES_MARK_STACK_SIZE / sizeof(void *)];
     void                *gcMarkStackTypes[js::TYPE_MARK_STACK_SIZE / sizeof(void *)];
     void                *gcMarkStackXMLs[js::XML_MARK_STACK_SIZE / sizeof(void *)];
     void                *gcMarkStackLarges[js::LARGE_MARK_STACK_SIZE / sizeof(void *)];
 
@@ -594,16 +600,19 @@ struct JSRuntime {
      * Security callbacks set on the runtime are used by each context unless
      * an override is set on the context.
      */
     JSSecurityCallbacks *securityCallbacks;
 
     /* Structured data callbacks are runtime-wide. */
     const JSStructuredCloneCallbacks *structuredCloneCallbacks;
 
+    /* Call this to accumulate telemetry data. */
+    JSAccumulateTelemetryDataCallback telemetryCallback;
+
     /*
      * The propertyRemovals counter is incremented for every JSObject::clear,
      * and for each JSObject::remove method call that frees a slot in the given
      * object. See js_NativeGet and js_NativeSet in jsobj.cpp.
      */
     int32               propertyRemovals;
 
     /* Script filename table. */
@@ -668,69 +677,23 @@ struct JSRuntime {
 
     /*
      * To ensure that cx->malloc does not cause a GC, we set this flag during
      * OOM reporting (in js_ReportOutOfMemory). If a GC is requested while
      * reporting the OOM, we ignore it.
      */
     int32               inOOMReport;
 
-#if defined(MOZ_GCTIMER) || defined(JSGC_TESTPILOT)
-    struct GCData {
-        GCData()
-          : firstEnter(0),
-            firstEnterValid(false)
-#ifdef JSGC_TESTPILOT
-            , infoEnabled(false),
-            start(0),
-            count(0)
-#endif
-        { }
-
-        /*
-         * Timestamp of the first GCTimer -- application runtime is determined
-         * relative to this value.
-         */
-        uint64      firstEnter;
-        bool        firstEnterValid;
-
-        void setFirstEnter(uint64 v) {
-            JS_ASSERT(!firstEnterValid);
-            firstEnter = v;
-            firstEnterValid = true;
-        }
-
-#ifdef JSGC_TESTPILOT
-        bool        infoEnabled;
-
-        bool isTimerEnabled() {
-            return infoEnabled;
-        }
-
-        /*
-         * Circular buffer with GC data.
-         * count may grow >= INFO_LIMIT, which would indicate data loss.
-         */
-        static const size_t INFO_LIMIT = 64;
-        JSGCInfo    info[INFO_LIMIT];
-        size_t      start;
-        size_t      count;
-#else /* defined(MOZ_GCTIMER) */
-        bool isTimerEnabled() {
-            return true;
-        }
-#endif
-    } gcData;
-#endif
-
     JSRuntime();
     ~JSRuntime();
 
     bool init(uint32 maxbytes);
 
+    JSRuntime *thisFromCtor() { return this; }
+
     void setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind);
     void reduceGCTriggerBytes(uint32 amount);
 
     /*
      * Call the system malloc while checking for GC memory pressure and
      * reporting OOM error when cx is not null. We will not GC from here.
      */
     void* malloc_(size_t bytes, JSContext *cx = NULL) {
@@ -965,16 +928,18 @@ struct JSContext
     /* Exception state -- the exception member is a GC root by definition. */
     JSBool              throwing;           /* is there a pending exception? */
     js::Value           exception;          /* most-recently-thrown exception */
 
     /* Per-context run options. */
     uintN               runOptions;            /* see jsapi.h for JSOPTION_* */
 
   public:
+    int32               reportGranularity;  /* see jsprobes.h */
+
     /* Locale specific callbacks for string conversion. */
     JSLocaleCallbacks   *localeCallbacks;
 
     js::AutoResolving   *resolvingList;
 
     /*
      * True if generating an error, to prevent runaway recursion.
      * NB: generatingError packs with throwing below.
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -842,17 +842,22 @@ date_parseISOString(JSLinearString *str,
 
     if (PEEK('Z')) {
         ++i;
     } else if (PEEK('+') || PEEK('-')) {
         if (PEEK('-'))
             tzMul = -1;
         ++i;
         NEED_NDIGITS(2, tzHour);
-        NEED(':');
+        /*
+         * Non-standard extension to the ISO date format (permitted by ES5):
+         * allow "-0700" as a time zone offset, not just "-07:00".
+         */
+        if (PEEK(':'))
+          ++i;
         NEED_NDIGITS(2, tzMin);
     } else {
         isLocalTime = JS_TRUE;
     }
 
  done:
     if (year > 275943 // ceil(1e8/365) + 1970
         || (month == 0 || month > 12)
--- a/js/src/jsdbgapi.cpp
+++ b/js/src/jsdbgapi.cpp
@@ -44,17 +44,16 @@
  */
 #include <string.h>
 #include <stdarg.h>
 #include "jsprvtd.h"
 #include "jstypes.h"
 #include "jsstdint.h"
 #include "jsutil.h"
 #include "jsclist.h"
-#include "jshashtable.h"
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jsversion.h"
 #include "jsdbgapi.h"
 #include "jsemit.h"
 #include "jsfun.h"
 #include "jsgc.h"
 #include "jsgcmark.h"
@@ -64,16 +63,17 @@
 #include "jsopcode.h"
 #include "jsparse.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstaticcheck.h"
 #include "jsstr.h"
 #include "jswatchpoint.h"
 #include "jswrapper.h"
+
 #include "vm/Debugger.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsinterpinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
--- a/js/src/jsdhash.cpp
+++ b/js/src/jsdhash.cpp
@@ -40,17 +40,16 @@
 
 /*
  * Double hashing implementation.
  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsdhash.h"
 #include "jsutil.h"
 
 using namespace js;
 
 #ifdef JS_DHASHMETER
 # if defined MOZILLA_CLIENT && defined DEBUG_XXXbrendan
 #  include "nsTraceMalloc.h"
--- a/js/src/jsdtoa.cpp
+++ b/js/src/jsdtoa.cpp
@@ -42,17 +42,16 @@
  */
 #include "jstypes.h"
 #include "jsstdint.h"
 #include "jsdtoa.h"
 #include "jsprf.h"
 #include "jsapi.h"
 #include "jsprvtd.h"
 #include "jsnum.h"
-#include "jsbit.h"
 #include "jslibmath.h"
 #include "jscntxt.h"
 
 #include "jsobjinlines.h"
 
 using namespace js;
 
 #ifdef IS_LITTLE_ENDIAN
--- a/js/src/jsemit.cpp
+++ b/js/src/jsemit.cpp
@@ -44,17 +44,16 @@
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
 #include <new>
 #include <string.h>
 #include "jstypes.h"
 #include "jsstdint.h"
 #include "jsutil.h"
-#include "jsbit.h"
 #include "jsprf.h"
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jsbool.h"
 #include "jscntxt.h"
 #include "jsversion.h"
 #include "jsemit.h"
 #include "jsfun.h"
@@ -7770,23 +7769,16 @@ js_FinishTakingSrcNotes(JSContext *cx, J
 
     mainCount = cg->main.noteCount;
     totalCount = prologCount + mainCount;
     if (prologCount)
         memcpy(notes, cg->prolog.notes, SRCNOTE_SIZE(prologCount));
     memcpy(notes + prologCount, cg->main.notes, SRCNOTE_SIZE(mainCount));
     SN_MAKE_TERMINATOR(&notes[totalCount]);
 
-#ifdef DEBUG_notme
-  { int bin = JS_CeilingLog2(totalCount);
-    if (bin >= NBINS)
-        bin = NBINS - 1;
-    ++hist[bin];
-  }
-#endif
     return JS_TRUE;
 }
 
 static JSBool
 NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind,
            uintN stackDepth, size_t start, size_t end)
 {
     JS_ASSERT((uintN)(uint16)stackDepth == stackDepth);
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -40,17 +40,16 @@
 
 /*
  * JS standard exception implementation.
  */
 #include <stdlib.h>
 #include <string.h>
 #include "jstypes.h"
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsutil.h"
 #include "jsprf.h"
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jsversion.h"
 #include "jsexn.h"
 #include "jsfun.h"
 #include "jsgc.h"
@@ -613,18 +612,18 @@ StackTraceToString(JSContext *cx, JSExnP
             goto bad;                                                         \
                                                                               \
         if (length_ > stackmax - stacklen) {                                  \
             void *ptr_;                                                       \
             if (stackmax >= STACK_LENGTH_LIMIT ||                             \
                 length_ >= STACK_LENGTH_LIMIT - stacklen) {                   \
                 goto done;                                                    \
             }                                                                 \
-            stackmax = JS_BIT(JS_CeilingLog2(stacklen + length_));            \
-            ptr_ = cx->realloc_(stackbuf, (stackmax+1) * sizeof(jschar));      \
+            stackmax = RoundUpPow2(stacklen + length_);                       \
+            ptr_ = cx->realloc_(stackbuf, (stackmax+1) * sizeof(jschar));     \
             if (!ptr_)                                                        \
                 goto bad;                                                     \
             stackbuf = (jschar *) ptr_;                                       \
         }                                                                     \
         js_strncpy(stackbuf + stacklen, chars_, length_);                     \
         stacklen += length_;                                                  \
     JS_END_MACRO
 
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -217,8 +217,14 @@ JS_SetProtoCalled(JSContext *)
 
 extern size_t sCustomIteratorCount;
 
 JS_FRIEND_API(size_t)
 JS_GetCustomIteratorCount(JSContext *cx)
 {
     return sCustomIteratorCount;
 }
+
+JS_FRIEND_API(void)
+JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback)
+{
+    rt->telemetryCallback = callback;
+}
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -74,16 +74,31 @@ extern JS_FRIEND_API(size_t)
 JS_GetE4XObjectsCreated(JSContext *cx);
 
 extern JS_FRIEND_API(size_t)
 JS_SetProtoCalled(JSContext *cx);
 
 extern JS_FRIEND_API(size_t)
 JS_GetCustomIteratorCount(JSContext *cx);
 
+enum {
+    JS_TELEMETRY_GC_REASON,
+    JS_TELEMETRY_GC_IS_COMPARTMENTAL,
+    JS_TELEMETRY_GC_IS_SHAPE_REGEN,
+    JS_TELEMETRY_GC_MS,
+    JS_TELEMETRY_GC_MARK_MS,
+    JS_TELEMETRY_GC_SWEEP_MS
+};
+
+typedef void
+(* JSAccumulateTelemetryDataCallback)(int id, JSUint32 sample);
+
+extern JS_FRIEND_API(void)
+JS_SetAccumulateTelemetryCallback(JSRuntime *rt, JSAccumulateTelemetryDataCallback callback);
+
 /* Data for tracking analysis/inference memory usage. */
 typedef struct TypeInferenceMemoryStats
 {
     int64 scripts;
     int64 objects;
     int64 tables;
     int64 temporary;
     int64 emptyShapes;
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -39,17 +39,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * JS function support.
  */
 #include <string.h>
 #include "jstypes.h"
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsutil.h"
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsatom.h"
 #include "jsbool.h"
 #include "jsbuiltins.h"
 #include "jscntxt.h"
 #include "jsversion.h"
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -49,33 +49,31 @@
  * XXX swizzle page to freelist for better locality of reference
  */
 #include <math.h>
 #include <string.h>     /* for memset used when DEBUG */
 #include "jstypes.h"
 #include "jsstdint.h"
 #include "jsutil.h"
 #include "jshash.h"
-#include "jsbit.h"
 #include "jsclist.h"
 #include "jsprf.h"
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jscompartment.h"
 #include "jscrashreport.h"
 #include "jscrashformat.h"
 #include "jscntxt.h"
 #include "jsversion.h"
 #include "jsdbgapi.h"
 #include "jsexn.h"
 #include "jsfun.h"
 #include "jsgc.h"
 #include "jsgcchunk.h"
 #include "jsgcmark.h"
-#include "jshashtable.h"
 #include "jsinterp.h"
 #include "jsiter.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsparse.h"
 #include "jsprobes.h"
 #include "jsproxy.h"
@@ -84,23 +82,23 @@
 #include "jsstaticcheck.h"
 #include "jswatchpoint.h"
 #include "jsweakmap.h"
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
 #include "methodjit/MethodJIT.h"
+#include "vm/Debugger.h"
 #include "vm/String.h"
-#include "vm/Debugger.h"
 
 #include "jsobjinlines.h"
 
+#include "vm/CallObject-inl.h"
 #include "vm/String-inl.h"
-#include "vm/CallObject-inl.h"
 
 #ifdef MOZ_VALGRIND
 # define JS_VALGRIND
 #endif
 #ifdef JS_VALGRIND
 # include <valgrind/memcheck.h>
 #endif
 
@@ -437,17 +435,17 @@ ChunkPool::get(JSRuntime *rt)
 
     Chunk *chunk = emptyChunkListHead;
     if (chunk) {
         JS_ASSERT(emptyCount);
         emptyChunkListHead = chunk->info.next;
         --emptyCount;
     } else {
         JS_ASSERT(!emptyCount);
-        chunk = Chunk::allocate();
+        chunk = Chunk::allocate(rt);
         if (!chunk)
             return NULL;
     }
     JS_ASSERT(chunk->unused());
     JS_ASSERT(!rt->gcChunkSet.has(chunk));
 
 #ifdef JS_THREADSAFE
     if (wantBackgroundAllocation(rt))
@@ -470,17 +468,17 @@ ChunkPool::put(JSRuntime *rt, Chunk *chu
      * empty chunks until we are done with all the sweeping and finalization
      * that cannot be done in the background even if shouldShrink() is true.
      * This way we can safely call IsAboutToBeFinalized and Cell::isMarked for
      * finalized GC things in empty chunks. So we only release the chunk if we
      * are called from the background thread.
      */
     if (rt->gcHelperThread.sweeping()) {
         if (rt->gcHelperThread.shouldShrink()) {
-            Chunk::release(chunk);
+            Chunk::release(rt, chunk);
             return;
         }
 
         /*
          * Set the age to one as we expire chunks early during the background
          * sweep so this chunk already survived one GC cycle.
          */
         initialAge = 1;
@@ -509,46 +507,42 @@ ChunkPool::expire(JSRuntime *rt, bool re
         JS_ASSERT(emptyCount);
         Chunk *chunk = *chunkp;
         JS_ASSERT(chunk->unused());
         JS_ASSERT(!rt->gcChunkSet.has(chunk));
         JS_ASSERT(chunk->info.age <= MAX_EMPTY_CHUNK_AGE);
         if (releaseAll || chunk->info.age == MAX_EMPTY_CHUNK_AGE) {
             *chunkp = chunk->info.next;
             --emptyCount;
-            Chunk::release(chunk);
+            Chunk::release(rt, chunk);
         } else {
             /* Keep the chunk but increase its age. */
             ++chunk->info.age;
             chunkp = &chunk->info.next;
         }
     }
     JS_ASSERT_IF(releaseAll, !emptyCount);
 }
 
 /* static */ Chunk *
-Chunk::allocate()
+Chunk::allocate(JSRuntime *rt)
 {
     Chunk *chunk = static_cast<Chunk *>(AllocGCChunk());
     if (!chunk)
         return NULL;
     chunk->init();
-#ifdef MOZ_GCTIMER
-    JS_ATOMIC_INCREMENT(&newChunkCount);
-#endif
+    rt->gcStats.count(gcstats::STAT_NEW_CHUNK);
     return chunk;
 }
 
 /* static */ inline void
-Chunk::release(Chunk *chunk)
+Chunk::release(JSRuntime *rt, Chunk *chunk)
 {
     JS_ASSERT(chunk);
-#ifdef MOZ_GCTIMER
-    JS_ATOMIC_INCREMENT(&destroyChunkCount);
-#endif
+    rt->gcStats.count(gcstats::STAT_DESTROY_CHUNK);
     FreeGCChunk(chunk);
 }
 
 void
 Chunk::init()
 {
     JS_POISON(this, JS_FREE_PATTERN, GC_CHUNK_SIZE);
 
@@ -622,17 +616,17 @@ Chunk::allocateArena(JSCompartment *comp
     if (!hasAvailableArenas())
         removeFromAvailableList();
 
     JSRuntime *rt = comp->rt;
     Probes::resizeHeap(comp, rt->gcBytes, rt->gcBytes + ArenaSize);
     JS_ATOMIC_ADD(&rt->gcBytes, ArenaSize);
     JS_ATOMIC_ADD(&comp->gcBytes, ArenaSize);
     if (comp->gcBytes >= comp->gcTriggerBytes)
-        TriggerCompartmentGC(comp);
+        TriggerCompartmentGC(comp, gcstats::ALLOCTRIGGER);
 
     return aheader;
 }
 
 void
 Chunk::releaseArena(ArenaHeader *aheader)
 {
     JS_ASSERT(aheader->allocated());
@@ -695,17 +689,17 @@ PickChunk(JSCompartment *comp)
 
     /*
      * FIXME bug 583732 - chunk is newly allocated and cannot be present in
      * the table so using ordinary lookupForAdd is suboptimal here.
      */
     GCChunkSet::AddPtr p = rt->gcChunkSet.lookupForAdd(chunk);
     JS_ASSERT(!p);
     if (!rt->gcChunkSet.add(p, chunk)) {
-        Chunk::release(chunk);
+        Chunk::release(rt, chunk);
         return NULL;
     }
 
     chunk->info.prevp = NULL;
     chunk->info.next = NULL;
     chunk->addToAvailableList(comp);
 
     return chunk;
@@ -1054,17 +1048,17 @@ js_FinishGC(JSRuntime *rt)
     for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
         Foreground::delete_(*c);
     rt->compartments.clear();
     rt->atomsCompartment = NULL;
 
     rt->gcSystemAvailableChunkListHead = NULL;
     rt->gcUserAvailableChunkListHead = NULL;
     for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
-        Chunk::release(r.front());
+        Chunk::release(rt, r.front());
     rt->gcChunkSet.clear();
 
 #ifdef JS_THREADSAFE
     rt->gcHelperThread.finish();
 #endif
 
     /*
      * Finish the pool after the background thread stops in case it was doing
@@ -1522,18 +1516,17 @@ RunLastDitchGC(JSContext *cx)
     JSRuntime *rt = cx->runtime;
 #ifdef JS_THREADSAFE
     Maybe<AutoUnlockAtomsCompartment> maybeUnlockAtomsCompartment;
     if (cx->compartment == rt->atomsCompartment && rt->atomsCompartmentIsLocked)
         maybeUnlockAtomsCompartment.construct(cx);
 #endif
     /* The last ditch GC preserves all atoms. */
     AutoKeepAtoms keep(rt);
-    GCREASON(LASTDITCH);
-    js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL);
+    js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, gcstats::LASTDITCH);
 
 #ifdef JS_THREADSAFE
     if (rt->gcBytes >= rt->gcMaxBytes) {
         AutoLockGC lock(rt);
         cx->runtime->gcHelperThread.waitBackgroundSweepEnd();
     }
 #endif
 }
@@ -1576,18 +1569,17 @@ ArenaLists::refillFreeList(JSContext *cx
             return thing;
 
         /*
          * We failed to allocate. Run the GC if we can unless we have done it
          * already. Otherwise report OOM but first schedule a new GC soon.
          */
         if (runGC || !IsGCAllowed(cx)) {
             AutoLockGC lock(rt);
-            GCREASON(REFILL);
-            TriggerGC(rt);
+            TriggerGC(rt, gcstats::REFILL);
             break;
         }
         runGC = true;
     }
 
     js_ReportOutOfMemory(cx);
     return NULL;
 }
@@ -1977,107 +1969,103 @@ MarkRuntime(JSTracer *trc)
     if (!IS_GC_MARKING_TRACER(trc)) {
         /* We don't want to miss these when called from TraceRuntime. */
         if (JSTraceDataOp op = rt->gcGrayRootsTraceOp)
             (*op)(trc, rt->gcGrayRootsData);
     }
 }
 
 void
-TriggerGC(JSRuntime *rt)
+TriggerGC(JSRuntime *rt, gcstats::Reason reason)
 {
     JS_ASSERT(!rt->gcRunning);
     if (rt->gcIsNeeded)
         return;
 
     /*
      * Trigger the GC when it is safe to call an operation callback on any
      * thread.
      */
     rt->gcIsNeeded = true;
     rt->gcTriggerCompartment = NULL;
+    rt->gcTriggerReason = reason;
     TriggerAllOperationCallbacks(rt);
 }
 
 void
-TriggerCompartmentGC(JSCompartment *comp)
+TriggerCompartmentGC(JSCompartment *comp, gcstats::Reason reason)
 {
     JSRuntime *rt = comp->rt;
     JS_ASSERT(!rt->gcRunning);
-    GCREASON(COMPARTMENT);
 
     if (rt->gcZeal()) {
-        TriggerGC(rt);
+        TriggerGC(rt, reason);
         return;
     }
 
     if (rt->gcMode != JSGC_MODE_COMPARTMENT || comp == rt->atomsCompartment) {
         /* We can't do a compartmental GC of the default compartment. */
-        TriggerGC(rt);
+        TriggerGC(rt, reason);
         return;
     }
 
     if (rt->gcIsNeeded) {
         /* If we need to GC more than one compartment, run a full GC. */
         if (rt->gcTriggerCompartment != comp)
             rt->gcTriggerCompartment = NULL;
         return;
     }
 
     if (rt->gcBytes > 8192 && rt->gcBytes >= 3 * (rt->gcTriggerBytes / 2)) {
         /* If we're using significantly more than our quota, do a full GC. */
-        TriggerGC(rt);
+        TriggerGC(rt, reason);
         return;
     }
 
     /*
      * Trigger the GC when it is safe to call an operation callback on any
      * thread.
      */
     rt->gcIsNeeded = true;
     rt->gcTriggerCompartment = comp;
+    rt->gcTriggerReason = reason;
     TriggerAllOperationCallbacks(comp->rt);
 }
 
 void
 MaybeGC(JSContext *cx)
 {
     JSRuntime *rt = cx->runtime;
 
     if (rt->gcZeal()) {
-        GCREASON(MAYBEGC);
-        js_GC(cx, NULL, GC_NORMAL);
+        js_GC(cx, NULL, GC_NORMAL, gcstats::MAYBEGC);
         return;
     }
 
     JSCompartment *comp = cx->compartment;
     if (rt->gcIsNeeded) {
-        GCREASON(MAYBEGC);
-        js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL);
+        js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL, gcstats::MAYBEGC);
         return;
     }
 
     if (comp->gcBytes > 8192 && comp->gcBytes >= 3 * (comp->gcTriggerBytes / 4)) {
-        GCREASON(MAYBEGC);
-        js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL);
+        js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL, gcstats::MAYBEGC);
         return;
     }
 
     /*
      * On 32 bit setting gcNextFullGCTime below is not atomic and a race condition
      * could trigger an GC. We tolerate this.
      */
     int64 now = PRMJ_Now();
     if (rt->gcNextFullGCTime && rt->gcNextFullGCTime <= now) {
-        if (rt->gcChunkAllocationSinceLastGC) {
-            GCREASON(MAYBEGC);
-            js_GC(cx, NULL, GC_SHRINK);
-        } else {
+        if (rt->gcChunkAllocationSinceLastGC)
+            js_GC(cx, NULL, GC_SHRINK, gcstats::MAYBEGC);
+        else
             rt->gcNextFullGCTime = now + GC_IDLE_FULL_SPAN;
-        }
     }
 }
 
 } /* namespace js */
 
 #ifdef JS_THREADSAFE
 
 namespace js {
@@ -2154,17 +2142,17 @@ GCHelperThread::threadLoop()
                 state = IDLE;
             PR_NotifyAllCondVar(done);
             break;
           case ALLOCATING:
             do {
                 Chunk *chunk;
                 {
                     AutoUnlockGC unlock(rt);
-                    chunk = Chunk::allocate();
+                    chunk = Chunk::allocate(rt);
                 }
 
                 /* OOM stops the background allocation. */
                 if (!chunk)
                     break;
                 rt->gcChunkPool.put(rt, chunk);
             } while (state == ALLOCATING && rt->gcChunkPool.wantBackgroundAllocation(rt));
             if (state == ALLOCATING)
@@ -2281,17 +2269,17 @@ GCHelperThread::doSweep()
     }
     for (void ***iter = freeVector.begin(); iter != freeVector.end(); ++iter) {
         void **array = *iter;
         freeElementsAndArray(array, array + FREE_ARRAY_LENGTH);
     }
     freeVector.resize(0);
 }
 
-}
+} /* namespace js */
 
 #endif /* JS_THREADSAFE */
 
 static uint32
 ComputeJitReleaseInterval(JSContext *cx)
 {
     JSRuntime *rt = cx->runtime;
     /*
@@ -2341,17 +2329,17 @@ SweepCompartments(JSContext *cx, JSGCInv
             continue;
         }
         *write++ = compartment;
     }
     rt->compartments.resize(write - rt->compartments.begin());
 }
 
 static void
-BeginMarkPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind GCTIMER_PARAM)
+BeginMarkPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind)
 {
     JSRuntime *rt = cx->runtime;
 
     /*
      * Reset the property cache's type id generator so we can compress ids.
      * Same for the protoHazardShape proxy-shape standing in for all object
      * prototypes having readonly or setter properties.
      */
@@ -2371,32 +2359,32 @@ BeginMarkPhase(JSContext *cx, GCMarker *
         JSContext *iter = NULL;
         while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter))
             acx->purge();
     }
 
     /*
      * Mark phase.
      */
-    GCTIMESTAMP(startMark);
+    rt->gcStats.beginPhase(gcstats::PHASE_MARK);
 
     for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
         r.front()->bitmap.clear();
 
     if (rt->gcCurrentCompartment) {
         for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
             (*c)->markCrossCompartmentWrappers(gcmarker);
         Debugger::markCrossCompartmentDebuggerObjectReferents(gcmarker);
     }
 
     MarkRuntime(gcmarker);
 }
 
 static void
-EndMarkPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind GCTIMER_PARAM)
+EndMarkPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind)
 {
     JSRuntime *rt = cx->runtime;
 
     gcmarker->setMarkColor(GRAY);
     if (JSTraceDataOp op = rt->gcGrayRootsTraceOp)
         (*op)(gcmarker, rt->gcGrayRootsData);
     gcmarker->drainMarkStack();
     gcmarker->setMarkColor(BLACK);
@@ -2408,32 +2396,34 @@ EndMarkPhase(JSContext *cx, GCMarker *gc
            WeakMapBase::markAllIteratively(gcmarker) ||
            Debugger::markAllIteratively(gcmarker))
     {
         gcmarker->drainMarkStack();
     }
 
     rt->gcMarkingTracer = NULL;
 
+    rt->gcStats.endPhase(gcstats::PHASE_MARK);
+
     if (rt->gcCallback)
         (void) rt->gcCallback(cx, JSGC_MARK_END);
 
 #ifdef DEBUG
     /* Make sure that we didn't mark an object in another compartment */
     if (rt->gcCurrentCompartment) {
         for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c) {
             JS_ASSERT_IF(*c != rt->gcCurrentCompartment && *c != rt->atomsCompartment,
                          (*c)->arenas.checkArenaListAllUnmarked());
         }
     }
 #endif
 }
 
 static void
-SweepPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind GCTIMER_PARAM)
+SweepPhase(JSContext *cx, GCMarker *gcmarker, JSGCInvocationKind gckind)
 {
     JSRuntime *rt = cx->runtime;
 
     /*
      * Sweep phase.
      *
      * Finalize as we sweep, outside of rt->gcLock but with rt->gcRunning set
      * so that any attempt to allocate a GC-thing from a finalizer will fail,
@@ -2441,108 +2431,108 @@ SweepPhase(JSContext *cx, GCMarker *gcma
      *
      * We first sweep atom state so we can use IsAboutToBeFinalized on
      * JSString held in a hashtable to check if the hashtable entry can be
      * freed. Note that even after the entry is freed, JSObject finalizers can
      * continue to access the corresponding JSString* assuming that they are
      * unique. This works since the atomization API must not be called during
      * the GC.
      */
-    GCTIMESTAMP(startSweep);
+    gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
 
     /* Finalize unreachable (key,value) pairs in all weak maps. */
     WeakMapBase::sweepAll(gcmarker);
 
     js_SweepAtomState(cx);
 
     /* Collect watch points associated with unreachable objects. */
     WatchpointMap::sweepAll(cx);
 
-    Probes::GCStartSweepPhase(NULL);
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        Probes::GCStartSweepPhase(c);
-
     if (!rt->gcCurrentCompartment)
         Debugger::sweepAll(cx);
 
     uint32 releaseInterval = rt->gcCurrentCompartment ? 0 : ComputeJitReleaseInterval(cx);
     for (GCCompartmentsIter c(rt); !c.done(); c.next())
         c->sweep(cx, releaseInterval);
 
-    /*
-     * We finalize objects before other GC things to ensure that the object's
-     * finalizer can access the other things even if they will be freed.
-     */
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        c->arenas.finalizeObjects(cx);
-
-    GCTIMESTAMP(sweepObjectEnd);
-
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        c->arenas.finalizeStrings(cx);
-
-    GCTIMESTAMP(sweepStringEnd);
-
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        c->arenas.finalizeScripts(cx);
-
-    GCTIMESTAMP(sweepScriptEnd);
-
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        c->arenas.finalizeShapes(cx);
-
-    GCTIMESTAMP(sweepShapeEnd);
-
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        Probes::GCEndSweepPhase(c);
-    Probes::GCEndSweepPhase(NULL);
+    {
+        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_OBJECT);
+
+        /*
+         * We finalize objects before other GC things to ensure that the object's
+         * finalizer can access the other things even if they will be freed.
+         */
+        for (GCCompartmentsIter c(rt); !c.done(); c.next())
+            c->arenas.finalizeObjects(cx);
+    }
+
+    {
+        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_STRING);
+        for (GCCompartmentsIter c(rt); !c.done(); c.next())
+            c->arenas.finalizeStrings(cx);
+    }
+
+    {
+        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_SCRIPT);
+        for (GCCompartmentsIter c(rt); !c.done(); c.next())
+            c->arenas.finalizeScripts(cx);
+    }
+
+    {
+        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_SHAPE);
+        for (GCCompartmentsIter c(rt); !c.done(); c.next())
+            c->arenas.finalizeShapes(cx);
+    }
 
 #ifdef DEBUG
      PropertyTree::dumpShapes(cx);
 #endif
 
-    /*
-     * Sweep script filenames after sweeping functions in the generic loop
-     * above. In this way when a scripted function's finalizer destroys the
-     * script and calls rt->destroyScriptHook, the hook can still access the
-     * script's filename. See bug 323267.
-     */
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        js_SweepScriptFilenames(c);
-
-    /*
-     * This removes compartments from rt->compartment, so we do it last to make
-     * sure we don't miss sweeping any compartments.
-     */
-    if (!rt->gcCurrentCompartment)
-        SweepCompartments(cx, gckind);
+    {
+        gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_DESTROY);
+
+        /*
+         * Sweep script filenames after sweeping functions in the generic loop
+         * above. In this way when a scripted function's finalizer destroys the
+         * script and calls rt->destroyScriptHook, the hook can still access the
+         * script's filename. See bug 323267.
+         */
+        for (GCCompartmentsIter c(rt); !c.done(); c.next())
+            js_SweepScriptFilenames(c);
+
+        /*
+         * This removes compartments from rt->compartment, so we do it last to make
+         * sure we don't miss sweeping any compartments.
+         */
+        if (!rt->gcCurrentCompartment)
+            SweepCompartments(cx, gckind);
 
 #ifndef JS_THREADSAFE
-    /*
-     * Destroy arenas after we finished the sweeping so finalizers can safely
-     * use IsAboutToBeFinalized().
-     * This is done on the GCHelperThread if JS_THREADSAFE is defined.
-     */
-    rt->gcChunkPool.expire(rt, gckind == GC_SHRINK);
+        /*
+         * Destroy arenas after we finished the sweeping so finalizers can safely
+         * use IsAboutToBeFinalized().
+         * This is done on the GCHelperThread if JS_THREADSAFE is defined.
+         */
+        rt->gcChunkPool.expire(rt, gckind == GC_SHRINK);
 #endif
-    GCTIMESTAMP(sweepDestroyEnd);
+    }
 
     if (rt->gcCallback)
         (void) rt->gcCallback(cx, JSGC_FINALIZE_END);
 }
 
 /*
  * Perform mark-and-sweep GC.
  *
  * In a JS_THREADSAFE build, the calling thread must be rt->gcThread and each
  * other thread must be either outside all requests or blocked waiting for GC
  * to finish. The caller must hold rt->gcLock.
  */
 static void
-MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind GCTIMER_PARAM)
+MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind)
 {
     JSRuntime *rt = cx->runtime;
     rt->gcNumber++;
 
     /* Clear gcIsNeeded now, when we are about to start a normal GC cycle. */
     rt->gcIsNeeded = false;
     rt->gcTriggerCompartment = NULL;
 
@@ -2551,20 +2541,20 @@ MarkAndSweep(JSContext *cx, JSGCInvocati
 
     AutoUnlockGC unlock(rt);
 
     GCMarker gcmarker(cx);
     JS_ASSERT(IS_GC_MARKING_TRACER(&gcmarker));
     JS_ASSERT(gcmarker.getMarkColor() == BLACK);
     rt->gcMarkingTracer = &gcmarker;
 
-    BeginMarkPhase(cx, &gcmarker, gckind GCTIMER_ARG);
+    BeginMarkPhase(cx, &gcmarker, gckind);
     gcmarker.drainMarkStack();
-    EndMarkPhase(cx, &gcmarker, gckind GCTIMER_ARG);
-    SweepPhase(cx, &gcmarker, gckind GCTIMER_ARG);
+    EndMarkPhase(cx, &gcmarker, gckind);
+    SweepPhase(cx, &gcmarker, gckind);
 }
 
 #ifdef JS_THREADSAFE
 
 /*
  * If the GC is running and we're called on another thread, wait for this GC
  * activation to finish. We can safely wait here without fear of deadlock (in
  * the case where we are called within a request on another thread's context)
@@ -2736,17 +2726,17 @@ AutoGCSession::~AutoGCSession()
 
 /*
  * GC, repeatedly if necessary, until we think we have not created any new
  * garbage and no other threads are demanding more GC. We disable inlining
  * to ensure that the bottom of the stack with possible GC roots recorded in
  * js_GC excludes any pointers we use during the marking implementation.
  */
 static JS_NEVER_INLINE void
-GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind  GCTIMER_PARAM)
+GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
 {
     JSRuntime *rt = cx->runtime;
 
     JS_ASSERT_IF(comp, gckind != GC_LAST_CONTEXT);
     JS_ASSERT_IF(comp, comp != rt->atomsCompartment);
     JS_ASSERT_IF(comp, rt->gcMode == JSGC_MODE_COMPARTMENT);
 
     /*
@@ -2798,17 +2788,17 @@ GCCycle(JSContext *cx, JSCompartment *co
     JS_ASSERT(!cx->gcBackgroundFree);
     rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
     if (gckind != GC_LAST_CONTEXT && rt->state != JSRTS_LANDING) {
         if (rt->gcHelperThread.prepareForBackgroundSweep(cx))
             cx->gcBackgroundFree = &rt->gcHelperThread;
     }
 #endif
 
-    MarkAndSweep(cx, gckind  GCTIMER_ARG);
+    MarkAndSweep(cx, gckind);
 
 #ifdef JS_THREADSAFE
     if (gckind != GC_LAST_CONTEXT && rt->state != JSRTS_LANDING) {
         JS_ASSERT(cx->gcBackgroundFree == &rt->gcHelperThread);
         cx->gcBackgroundFree = NULL;
         rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK);
     } else {
         JS_ASSERT(!cx->gcBackgroundFree);
@@ -2820,24 +2810,18 @@ GCCycle(JSContext *cx, JSCompartment *co
     rt->setGCLastBytes(rt->gcBytes, gckind);
     rt->gcCurrentCompartment = NULL;
     rt->gcWeakMapList = NULL;
 
     for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
         (*c)->setGCLastBytes((*c)->gcBytes, gckind);
 }
 
-struct GCCrashData
-{
-    int isRegen;
-    int isCompartment;
-};
-
 void
-js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
+js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Reason reason)
 {
     JSRuntime *rt = cx->runtime;
 
     /*
      * Don't collect garbage if the runtime isn't up, and cx is not the last
      * context in the runtime.  The last context must force a GC, and nothing
      * should suppress that final collection or there may be shutdown leaks,
      * or runtime bloat until the next context is created.
@@ -2847,32 +2831,17 @@ js_GC(JSContext *cx, JSCompartment *comp
 
     if (JS_ON_TRACE(cx)) {
         JS_ASSERT(gckind != GC_LAST_CONTEXT);
         return;
     }
 
     RecordNativeStackTopForGC(cx);
 
-    GCCrashData crashData;
-    crashData.isRegen = rt->shapeGen & SHAPE_OVERFLOW_BIT;
-    crashData.isCompartment = !!comp;
-    crash::SaveCrashData(crash::JS_CRASH_TAG_GC, &crashData, sizeof(crashData));
-
-    GCTIMER_BEGIN(rt, comp);
-
-    struct AutoGCProbe {
-        JSCompartment *comp;
-        AutoGCProbe(JSCompartment *comp) : comp(comp) {
-            Probes::GCStart(comp);
-        }
-        ~AutoGCProbe() {
-            Probes::GCEnd(comp); /* background thread may still be sweeping */
-        }
-    } autoGCProbe(comp);
+    gcstats::AutoGC agc(rt->gcStats, comp, reason);
 
     do {
         /*
          * Let the API user decide to defer a GC if it wants to (unless this
          * is the last context).  Invoke the callback regardless. Sample the
          * callback in case we are freely racing with a JS_SetGCCallback{,RT}
          * on another thread.
          */
@@ -2880,35 +2849,32 @@ js_GC(JSContext *cx, JSCompartment *comp
             if (!callback(cx, JSGC_BEGIN) && gckind != GC_LAST_CONTEXT)
                 return;
         }
 
         {
             /* Lock out other GC allocator and collector invocations. */
             AutoLockGC lock(rt);
             rt->gcPoke = false;
-            GCCycle(cx, comp, gckind  GCTIMER_ARG);
+            GCCycle(cx, comp, gckind);
         }
 
         /* We re-sample the callback again as the finalizers can change it. */
         if (JSGCCallback callback = rt->gcCallback)
             (void) callback(cx, JSGC_END);
 
         /*
          * On shutdown, iterate until finalizers or the JSGC_END callback
          * stop creating garbage.
          */
     } while (gckind == GC_LAST_CONTEXT && rt->gcPoke);
 
     rt->gcNextFullGCTime = PRMJ_Now() + GC_IDLE_FULL_SPAN;
 
     rt->gcChunkAllocationSinceLastGC = false;
-    GCTIMER_END(gckind == GC_LAST_CONTEXT);
-
-    crash::SnapshotGCStack();
 }
 
 namespace js {
 
 class AutoCopyFreeListToArenas {
     JSRuntime *rt;
 
   public:
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -40,30 +40,32 @@
 #ifndef jsgc_h___
 #define jsgc_h___
 
 /*
  * JS Garbage Collector.
  */
 #include <setjmp.h>
 
+#include "jsalloc.h"
 #include "jstypes.h"
 #include "jsprvtd.h"
 #include "jspubtd.h"
 #include "jsdhash.h"
-#include "jsbit.h"
 #include "jsgcchunk.h"
-#include "jshashtable.h"
 #include "jslock.h"
 #include "jsutil.h"
-#include "jsvector.h"
 #include "jsversion.h"
 #include "jsgcstats.h"
 #include "jscell.h"
 
+#include "gc/Statistics.h"
+#include "js/HashTable.h"
+#include "js/Vector.h"
+
 struct JSCompartment;
 
 extern "C" void
 js_TraceXML(JSTracer *trc, JSXML* thing);
 
 #if JS_STACK_GROWTH_DIRECTION > 0
 # define JS_CHECK_STACK_SIZE(limit, lval)  ((jsuword)(lval) < limit)
 #else
@@ -651,18 +653,18 @@ struct Chunk {
 
     inline void addToAvailableList(JSCompartment *compartment);
     inline void removeFromAvailableList();
 
     ArenaHeader *allocateArena(JSCompartment *comp, AllocKind kind);
 
     void releaseArena(ArenaHeader *aheader);
 
-    static Chunk *allocate();
-    static inline void release(Chunk *chunk);
+    static Chunk *allocate(JSRuntime *rt);
+    static inline void release(JSRuntime *rt, Chunk *chunk);
 
   private:
     inline void init();
 };
 
 JS_STATIC_ASSERT(sizeof(Chunk) <= GC_CHUNK_SIZE);
 JS_STATIC_ASSERT(sizeof(Chunk) + BytesPerArena > GC_CHUNK_SIZE);
 
@@ -1260,21 +1262,21 @@ MarkRuntime(JSTracer *trc);
 extern void
 TraceRuntime(JSTracer *trc);
 
 extern JS_REQUIRES_STACK JS_FRIEND_API(void)
 MarkContext(JSTracer *trc, JSContext *acx);
 
 /* Must be called with GC lock taken. */
 extern void
-TriggerGC(JSRuntime *rt);
+TriggerGC(JSRuntime *rt, js::gcstats::Reason reason);
 
 /* Must be called with GC lock taken. */
 extern void
-TriggerCompartmentGC(JSCompartment *comp);
+TriggerCompartmentGC(JSCompartment *comp, js::gcstats::Reason reason);
 
 extern void
 MaybeGC(JSContext *cx);
 
 } /* namespace js */
 
 /*
  * Kinds of js_GC invocation.
@@ -1290,17 +1292,17 @@ typedef enum JSGCInvocationKind {
     GC_LAST_CONTEXT     = 1,
 
     /* Minimize GC triggers and release empty GC chunks right away. */
     GC_SHRINK             = 2
 } JSGCInvocationKind;
 
 /* Pass NULL for |comp| to get a full GC. */
 extern void
-js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind);
+js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, js::gcstats::Reason r);
 
 #ifdef JS_THREADSAFE
 /*
  * This is a helper for code at can potentially run outside JS request to
  * ensure that the GC is not running when the function returns.
  *
  * This function must be called with the GC lock held.
  */
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -38,21 +38,21 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsgcinlines_h___
 #define jsgcinlines_h___
 
 #include "jsgc.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
+#include "jslock.h"
 #include "jsscope.h"
 #include "jsxml.h"
 
-#include "jslock.h"
-#include "jstl.h"
+#include "js/TemplateLib.h"
 
 namespace js {
 
 struct Shape;
 
 namespace gc {
 
 inline JSGCTraceKind
--- a/js/src/jsgcmark.h
+++ b/js/src/jsgcmark.h
@@ -38,19 +38,20 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsgcmark_h___
 #define jsgcmark_h___
 
 #include "jsgc.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
+#include "jslock.h"
 
-#include "jslock.h"
-#include "jstl.h"
+
+#include "js/TemplateLib.h"
 
 namespace js {
 namespace gc {
 
 void
 MarkString(JSTracer *trc, JSString *str);
 
 void
--- a/js/src/jsgcstats.cpp
+++ b/js/src/jsgcstats.cpp
@@ -75,64 +75,16 @@ ConservativeGCStats::dump(FILE *fp)
     fprintf(fp, "         excluded, not live: %lu\n", ULSTAT(counter[CGCT_NOTLIVE]));
     fprintf(fp, "            valid GC things: %lu\n", ULSTAT(counter[CGCT_VALID]));
     fprintf(fp, "      valid but not aligned: %lu\n", ULSTAT(unaligned));
 #undef ULSTAT
 }
 #endif
 
 } //gc
-} //js
-
-#ifdef JSGC_TESTPILOT
-typedef JSRuntime::GCData GCData;
-
-JS_PUBLIC_API(bool)
-JS_GetGCInfoEnabled(JSRuntime *rt)
-{
-    return rt->gcData.infoEnabled;
-}
-
-JS_PUBLIC_API(void)
-JS_SetGCInfoEnabled(JSRuntime *rt, bool enabled)
-{
-    rt->gcData.infoEnabled = enabled;
-}
-
-JS_PUBLIC_API(JSGCInfo *)
-JS_GCInfoFront(JSRuntime *rt)
-{
-    GCData &data = rt->gcData;
-    JS_ASSERT(data.infoEnabled);
-    if (!data.count)
-        return NULL;
-
-    return &data.info[data.start];
-}
-
-JS_PUBLIC_API(bool)
-JS_GCInfoPopFront(JSRuntime *rt)
-{
-    GCData &data = rt->gcData;
-    JS_ASSERT(data.infoEnabled);
-    JS_ASSERT(data.count);
-
-    if (data.count >= GCData::INFO_LIMIT) {
-        data.count = data.start = 0;
-        return true;
-    }
-
-    data.start = (data.start + 1) % GCData::INFO_LIMIT;
-    data.count -= 1;
-    return false;
-}
-#endif
-
-
-namespace js {
 
 #ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
 void
 GCMarker::dumpConservativeRoots()
 {
     if (!conservativeDumpFileName)
         return;
 
@@ -148,17 +100,17 @@ GCMarker::dumpConservativeRoots()
         return;
     }
 
     conservativeStats.dump(fp);
 
     for (void **thingp = conservativeRoots.begin(); thingp != conservativeRoots.end(); ++thingp) {
         void *thing = thingp;
         fprintf(fp, "  %p: ", thing);
-        
+
         switch (GetGCThingTraceKind(thing)) {
           case JSTRACE_OBJECT: {
             JSObject *obj = (JSObject *) thing;
             fprintf(fp, "object %s", obj->getClass()->name);
             break;
           }
           case JSTRACE_STRING: {
             JSString *str = (JSString *) thing;
@@ -195,148 +147,9 @@ GCMarker::dumpConservativeRoots()
     }
     fputc('\n', fp);
 
     if (fp != stdout && fp != stderr)
         fclose(fp);
 }
 #endif /* JS_DUMP_CONSERVATIVE_GC_ROOTS */
 
-#if defined(MOZ_GCTIMER) || defined(JSGC_TESTPILOT)
-
-volatile GCTimer::JSGCReason gcReason = GCTimer::NOREASON;
-const char *gcReasons[] = {"  API", "Maybe", "LastC", "DestC", "Compa", "LastD",
-                           "Malloc", "Refill", "Chunk", "Shape", "  None"};
-
-jsrefcount newChunkCount = 0;
-jsrefcount destroyChunkCount = 0;
-
-#ifdef MOZ_GCTIMER
-static const char *gcTimerStatPath = NULL;
-#endif
-
-GCTimer::GCTimer(JSRuntime *rt, JSCompartment *comp)
-  : rt(rt), isCompartmental(comp),
-    enabled(rt->gcData.isTimerEnabled())
-{
-#ifdef MOZ_GCTIMER
-    if (!gcTimerStatPath) {
-        gcTimerStatPath = getenv("MOZ_GCTIMER");
-        if (!gcTimerStatPath || !gcTimerStatPath[0])
-            gcTimerStatPath = "gcTimer.dat";
-    }
-    if (!strcmp(gcTimerStatPath, "none"))
-        enabled = false;
-#endif
-    clearTimestamps();
-    getFirstEnter();
-    enter = PRMJ_Now();
-}
-
-uint64
-GCTimer::getFirstEnter()
-{
-    JSRuntime::GCData &data = rt->gcData;
-    if (enabled && !data.firstEnterValid)
-        data.setFirstEnter(PRMJ_Now());
-
-    return data.firstEnter;
-}
-
-#define TIMEDIFF(start, end) ((double)(end - start) / PRMJ_USEC_PER_MSEC)
-
-void
-GCTimer::finish(bool lastGC)
-{
-#if defined(JSGC_TESTPILOT)
-    if (!enabled) {
-        newChunkCount = 0;
-        destroyChunkCount = 0;
-        return;
-    }
-#endif
-    end = PRMJ_Now();
-
-    if (startMark > 0) {
-        double appTime = TIMEDIFF(getFirstEnter(), enter);
-        double gcTime = TIMEDIFF(enter, end);
-        double waitTime = TIMEDIFF(enter, startMark);
-        double markTime = TIMEDIFF(startMark, startSweep);
-        double sweepTime = TIMEDIFF(startSweep, sweepDestroyEnd);
-        double sweepObjTime = TIMEDIFF(startSweep, sweepObjectEnd);
-        double sweepStringTime = TIMEDIFF(sweepObjectEnd, sweepStringEnd);
-        double sweepScriptTime = TIMEDIFF(sweepStringEnd, sweepScriptEnd);
-        double sweepShapeTime = TIMEDIFF(sweepScriptEnd, sweepShapeEnd);
-        double destroyTime = TIMEDIFF(sweepShapeEnd, sweepDestroyEnd);
-        double endTime = TIMEDIFF(sweepDestroyEnd, end);
-
-#if defined(JSGC_TESTPILOT)
-        GCData &data = rt->gcData;
-        size_t oldLimit = (data.start + data.count) % GCData::INFO_LIMIT;
-        data.count += 1;
-
-        JSGCInfo &info = data.info[oldLimit];
-        info.appTime = appTime;
-        info.gcTime = gcTime;
-        info.waitTime = waitTime;
-        info.markTime = markTime;
-        info.sweepTime = sweepTime;
-        info.sweepObjTime = sweepObjTime;
-        info.sweepStringTime = sweepStringTime;
-        info.sweepScriptTime = sweepScriptTime;
-        info.sweepShapeTime = sweepShapeTime;
-        info.destroyTime = destroyTime;
-        info.endTime = endTime;
-        info.isCompartmental = isCompartmental;
-#endif
-
-#if defined(MOZ_GCTIMER)
-        static FILE *gcFile;
-        static bool fullFormat;
-
-        if (!gcFile) {
-            if (!strcmp(gcTimerStatPath, "stdout")) {
-                gcFile = stdout;
-                fullFormat = false;
-            } else if (!strcmp(gcTimerStatPath, "stderr")) {
-                gcFile = stderr;
-                fullFormat = false;
-            } else {
-                gcFile = fopen(gcTimerStatPath, "a");
-                JS_ASSERT(gcFile);
-                fullFormat = true;
-                fprintf(gcFile, "     AppTime,  Total,   Wait,   Mark,  Sweep, FinObj,"
-                        " FinStr, SwScripts, SwShapes, Destroy,    End, +Chu, -Chu, T, Reason\n");
-            }
-        }
-
-        if (!fullFormat) {
-            fprintf(stderr, "%f %f %f\n",
-                    TIMEDIFF(enter, end),
-                    TIMEDIFF(startMark, startSweep),
-                    TIMEDIFF(startSweep, sweepDestroyEnd));
-        } else {
-            /*               App   , Tot  , Wai  , Mar  , Swe  , FiO  , FiS  , SwScr , SwS  , Des   , End */
-            fprintf(gcFile, "%12.0f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %8.1f,  %6.1f, %6.1f, ",
-                    appTime, gcTime, waitTime, markTime, sweepTime, sweepObjTime, sweepStringTime,
-                    sweepScriptTime, sweepShapeTime, destroyTime, endTime);
-            fprintf(gcFile, "%4d, %4d,", newChunkCount, destroyChunkCount);
-            fprintf(gcFile, " %s, %s\n", isCompartmental ? "C" : "G", gcReasons[gcReason]);
-        }
-        fflush(gcFile);
-        
-        if (lastGC && gcFile != stdout && gcFile != stderr)
-            fclose(gcFile);
-#endif
-    }
-    newChunkCount = 0;
-    destroyChunkCount = 0;
-    gcReason = NOREASON;
-}
-
-#undef TIMEDIFF
-
-#endif
-
-} //js
-
-#undef UL
-#undef PERCENT
+} /* namespace js */
--- a/js/src/jsgcstats.h
+++ b/js/src/jsgcstats.h
@@ -38,59 +38,16 @@
 
 #ifndef jsgcstats_h___
 #define jsgcstats_h___
 
 #if !defined JS_DUMP_CONSERVATIVE_GC_ROOTS && defined DEBUG
 # define JS_DUMP_CONSERVATIVE_GC_ROOTS 1
 #endif
 
-#ifdef JSGC_TESTPILOT
-JS_BEGIN_EXTERN_C
-
-struct JSGCInfo
-{
-    double appTime, gcTime, waitTime, markTime, sweepTime;
-    double sweepObjTime, sweepStringTime, sweepScriptTime, sweepShapeTime;
-    double destroyTime, endTime;
-    bool isCompartmental;
-};
-
-extern JS_PUBLIC_API(void)
-JS_SetGCInfoEnabled(JSRuntime *rt, bool enabled);
-
-extern JS_PUBLIC_API(bool)
-JS_GetGCInfoEnabled(JSRuntime *rt);
-
-/*
- * Data in the circular buffer may end up clobbered before the API client
- * consumes it. Because of this we have a multi-part API. The client uses code
- * like the following:
- *
- * - Call GetInfo, which provides an info pointer.
- * - Read data out of the info pointer to a location the client owns.
- * - Call PopInfo, which provides a "did info get dropped?" value. If that
- *   value is true, the data read out of the info pointer may be tainted, and
- *   must be thrown out. Otherwise, the data was definitely safe to read, and
- *   may be committed to a database or some such.
- *
- * When PopInfo indicates that data has been dropped, all of the information in
- * the circular buffer is reset.
- */
-
-extern JS_PUBLIC_API(JSGCInfo *)
-JS_GCInfoFront(JSRuntime *rt);
-
-/* Return whether info has dropped. See comment above. */
-extern JS_PUBLIC_API(bool)
-JS_GCInfoPopFront(JSRuntime *rt);
-
-JS_END_EXTERN_C
-#endif
-
 namespace js {
 namespace gc {
 /*
  * The conservative GC test for a word shows that it is either a valid GC
  * thing or is not for one of the following reasons.
  */
 enum ConservativeGCTest
 {
@@ -116,84 +73,11 @@ struct ConservativeGCStats
             counter[i] += another.counter[i];
     }
 
     void dump(FILE *fp);
 };
 
 } //gc
 
-#if defined(MOZ_GCTIMER) || defined(JSGC_TESTPILOT)
-
-extern jsrefcount newChunkCount;
-extern jsrefcount destroyChunkCount;
-
-struct GCTimer
-{
-    JSRuntime *rt;
-
-    uint64 enter;
-    uint64 startMark;
-    uint64 startSweep;
-    uint64 sweepObjectEnd;
-    uint64 sweepStringEnd;
-    uint64 sweepScriptEnd;
-    uint64 sweepShapeEnd;
-    uint64 sweepDestroyEnd;
-    uint64 end;
-
-    bool isCompartmental;
-    bool enabled; /* Disabled timers should cause no PRMJ calls. */
-
-    GCTimer(JSRuntime *rt, JSCompartment *comp);
-
-    uint64 getFirstEnter();
-
-    void clearTimestamps() {
-        memset(&enter, 0, &end - &enter + sizeof(end));
-    }
-
-    void finish(bool lastGC);
-
-    enum JSGCReason {
-        PUBLIC_API,
-        MAYBEGC,
-        LASTCONTEXT,
-        DESTROYCONTEXT,
-        COMPARTMENT,
-        LASTDITCH,
-        TOOMUCHMALLOC,
-        ALLOCTRIGGER,
-        REFILL,
-        SHAPE,
-        NOREASON
-    };
-};
-
-/* We accept the possiblility of races for this variable. */
-extern volatile GCTimer::JSGCReason gcReason;
-
-#define GCREASON(x) ((gcReason == GCTimer::NOREASON) ? gcReason = GCTimer::x : gcReason = gcReason)
-
-# define GCTIMER_PARAM              , GCTimer &gcTimer
-# define GCTIMER_ARG                , gcTimer
-# define GCTIMESTAMP(stamp_name_) \
-    JS_BEGIN_MACRO \
-        if (gcTimer.enabled) \
-            gcTimer.stamp_name_ = PRMJ_Now(); \
-    JS_END_MACRO
-# define GCTIMER_BEGIN(rt, comp)    GCTimer gcTimer(rt, comp)
-# define GCTIMER_END(last)          (gcTimer.finish(last))
-#else
-# define GCREASON(x)                ((void) 0)
-# define GCTIMER_PARAM
-# define GCTIMER_ARG
-# define GCTIMESTAMP(x)             ((void) 0)
-# define GCTIMER_BEGIN(rt, comp)    ((void) 0)
-# define GCTIMER_END(last)          ((void) 0)
-#endif
-
 } //js
 
-extern JS_FRIEND_API(void)
-js_DumpGCStats(JSRuntime *rt, FILE *fp);
-
 #endif /* jsgcstats_h__ */
--- a/js/src/jshash.cpp
+++ b/js/src/jshash.cpp
@@ -39,17 +39,16 @@
 
 /*
  * PR hash table package.
  */
 #include <stdlib.h>
 #include <string.h>
 #include "jstypes.h"
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsutil.h"
 #include "jshash.h"
 
 using namespace js;
 
 /* Compute the number of buckets in ht */
 #define NBUCKETS(ht)    JS_BIT(JS_HASH_BITS - (ht)->shift)
 
@@ -102,17 +101,17 @@ JS_NewHashTable(uint32 n, JSHashFunction
                 JSHashAllocOps *allocOps, void *allocPriv)
 {
     JSHashTable *ht;
     size_t nb;
 
     if (n <= MINBUCKETS) {
         n = MINBUCKETSLOG2;
     } else {
-        n = JS_CeilingLog2(n);
+        n = JS_CEILING_LOG2W(n);
         if ((int32)n < 0)
             return NULL;
     }
 
     if (!allocOps) allocOps = &defaultHashAllocOps;
 
     ht = (JSHashTable*) allocOps->allocTable(allocPriv, sizeof *ht);
     if (!ht)
@@ -382,17 +381,17 @@ JS_HashTableEnumerateEntries(JSHashTable
     }
 
 out:
     /* Shrink table if removal of entries made it underloaded */
     if (ht->nentries != nlimit) {
         JS_ASSERT(ht->nentries < nlimit);
         nbuckets = NBUCKETS(ht);
         if (MINBUCKETS < nbuckets && ht->nentries < UNDERLOADED(nbuckets)) {
-            newlog2 = JS_CeilingLog2(ht->nentries);
+            newlog2 = JS_CEILING_LOG2W(ht->nentries);
             if (newlog2 < MINBUCKETSLOG2)
                 newlog2 = MINBUCKETSLOG2;
 
             /*  Check that we really shrink the table. */
             JS_ASSERT(JS_HASH_BITS - ht->shift > newlog2);
             Resize(ht, JS_HASH_BITS - newlog2);
         }
     }
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -34,33 +34,31 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "jsapi.h"
 #include "jsautooplen.h"
-#include "jsbit.h"
 #include "jsbool.h"
 #include "jsdate.h"
 #include "jsexn.h"
 #include "jsfriendapi.h"
 #include "jsgc.h"
 #include "jsgcmark.h"
 #include "jsinfer.h"
 #include "jsmath.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsscript.h"
 #include "jscntxt.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsstr.h"
-#include "jstl.h"
 #include "jsiter.h"
 
 #include "methodjit/MethodJIT.h"
 #include "methodjit/Retcon.h"
 
 #include "jsatominlines.h"
 #include "jsgcinlines.h"
 #include "jsinferinlines.h"
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -40,21 +40,20 @@
 /* Definitions related to javascript type inference. */
 
 #ifndef jsinfer_h___
 #define jsinfer_h___
 
 #include "jsalloc.h"
 #include "jscell.h"
 #include "jsfriendapi.h"
-#include "jstl.h"
 #include "jsprvtd.h"
-#include "jshashtable.h"
 
 #include "ds/LifoAlloc.h"
+#include "js/HashTable.h"
 
 namespace js {
 namespace types {
 
 /* Type set entry for either a JSObject with singleton type or a non-singleton TypeObject. */
 struct TypeObjectKey {
     static intptr_t keyBits(TypeObjectKey *obj) { return (intptr_t) obj; }
     static TypeObjectKey *getKey(TypeObjectKey *obj) { return obj; }
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -68,17 +68,17 @@
 #include "jspropertycache.h"
 #include "jsemit.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
 #include "jsstaticcheck.h"
 #include "jstracer.h"
 #include "jslibmath.h"
-#include "jsvector.h"
+
 #ifdef JS_METHODJIT
 #include "methodjit/MethodJIT.h"
 #include "methodjit/MethodJIT-inl.h"
 #include "methodjit/Logging.h"
 #endif
 #include "vm/Debugger.h"
 
 #include "jsatominlines.h"
@@ -2725,17 +2725,17 @@ BEGIN_CASE(JSOP_BINDNAME)
         if (!obj)
             goto error;
     } while (0);
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_BINDNAME)
 
 BEGIN_CASE(JSOP_IMACOP)
-    JS_ASSERT(JS_UPTRDIFF(regs.fp()->imacropc(), script->code) < script->length);
+    JS_ASSERT(UnsignedPtrDiff(regs.fp()->imacropc(), script->code) < script->length);
     op = JSOp(*regs.fp()->imacropc());
     DO_OP();
 
 #define BITWISE_OP(OP)                                                        \
     JS_BEGIN_MACRO                                                            \
         int32_t i, j;                                                         \
         if (!ValueToECMAInt32(cx, regs.sp[-2], &i))                           \
             goto error;                                                       \
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -51,29 +51,27 @@
 #include "jsbool.h"
 #include "jsbuiltins.h"
 #include "jscntxt.h"
 #include "jsversion.h"
 #include "jsexn.h"
 #include "jsfun.h"
 #include "jsgc.h"
 #include "jsgcmark.h"
-#include "jshashtable.h"
 #include "jsinterp.h"
 #include "jsiter.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsproxy.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstaticcheck.h"
-#include "jsvector.h"
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
 #include "vm/GlobalObject.h"
 
 #include "jsinferinlines.h"
--- a/js/src/jslock.cpp
+++ b/js/src/jslock.cpp
@@ -32,35 +32,36 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "jsapi.h"
+#include "jspubtd.h"
+#include "jstypes.h"
+
 #ifdef JS_THREADSAFE
 
 /*
  * JS locking stubs.
  */
 #include <stdlib.h>
 #include <string.h>
 
 #ifdef XP_WIN
 # include "jswin.h"
 #else
 # include <unistd.h>
 #endif
 
-#include "jspubtd.h"
 #include "jsutil.h"
-#include "jstypes.h"
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jscntxt.h"
 #include "jsgc.h"
 #include "jslock.h"
 #include "jsscope.h"
 #include "jsstr.h"
 
 using namespace js;
 
@@ -499,17 +500,17 @@ js_SetupLocks(int listc, int globc)
     if (global_locks)
         return JS_TRUE;
 #ifdef DEBUG
     if (listc > 10000 || listc < 0) /* listc == fat lock list chunk length */
         printf("Bad number %d in js_SetupLocks()!\n", listc);
     if (globc > 100 || globc < 0)   /* globc == number of global locks */
         printf("Bad number %d in js_SetupLocks()!\n", listc);
 #endif
-    global_locks_log2 = JS_CeilingLog2(globc);
+    global_locks_log2 = JS_CEILING_LOG2W(globc);
     global_locks_mask = JS_BITMASK(global_locks_log2);
     global_lock_count = JS_BIT(global_locks_log2);
     global_locks = (PRLock **) OffTheBooks::malloc_(global_lock_count * sizeof(PRLock*));
     if (!global_locks)
         return JS_FALSE;
     for (i = 0; i < global_lock_count; i++) {
         global_locks[i] = PR_NewLock();
         if (!global_locks[i]) {
@@ -758,9 +759,33 @@ js_UnlockRuntime(JSRuntime *rt)
 
 #ifdef DEBUG
 JSBool
 js_IsRuntimeLocked(JSRuntime *rt)
 {
     return js_CurrentThreadId() == rt->rtLockOwner;
 }
 #endif /* DEBUG */
+
+static PRStatus
+CallOnce(void *func)
+{
+    JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
+    return init() ? PR_FAILURE : PR_SUCCESS;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
+{
+    return PR_CallOnceWithArg(once, CallOnce, JS_FUNC_TO_DATA_PTR(void *, func)) == PR_SUCCESS;
+}
+#else /* JS_THREADSAFE */
+JS_PUBLIC_API(JSBool)
+JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
+{
+    if (!*once) {
+        *once = true;
+        return func();
+    } else {
+        return JS_TRUE;
+    }
+}
 #endif /* JS_THREADSAFE */
--- a/js/src/jslock.h
+++ b/js/src/jslock.h
@@ -43,16 +43,17 @@
 #include "jsapi.h"
 #include "jsprvtd.h"
 
 #ifdef JS_THREADSAFE
 # include "pratom.h"
 # include "prlock.h"
 # include "prcvar.h"
 # include "prthread.h"
+# include "prinit.h"
 #endif
 
 #ifdef JS_THREADSAFE
 
 #if (defined(_WIN32) && defined(_M_IX86)) ||                                  \
     (defined(_WIN64) && (defined(_M_AMD64) || defined(_M_X64))) ||            \
     (defined(__i386) && (defined(__GNUC__) || defined(__SUNPRO_CC))) ||       \
     (defined(__x86_64) && (defined(__GNUC__) || defined(__SUNPRO_CC))) ||     \
--- a/js/src/jslog2.cpp
+++ b/js/src/jslog2.cpp
@@ -32,17 +32,16 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsutil.h"
 
 /*
  * Check that we can use js_bitscan_clz32 to implement JS_FLOOR_LOG2 and
  * JS_FLOOR_LOG2W and js_bitscan_clz64 to implement JS_FLOOR_LOG2W on 64-bit
  * systems.
  */
 #ifdef JS_HAS_BUILTIN_BITSCAN32
@@ -51,41 +50,16 @@ JS_STATIC_ASSERT_IF(JS_BYTES_PER_WORD ==
                     sizeof(unsigned int) == sizeof(JSUword));
 #endif
 #ifdef JS_HAS_BUILTIN_BITSCAN64
 JS_STATIC_ASSERT_IF(JS_BYTES_PER_WORD == 8,
                     sizeof(unsigned long long) == sizeof(JSUword));
 #endif
 
 /*
- * Compute the log of the least power of 2 greater than or equal to n
- */
-JS_PUBLIC_API(JSIntn)
-JS_CeilingLog2(JSUint32 n)
-{
-    JSIntn log2;
-
-    JS_CEILING_LOG2(log2, n);
-    return log2;
-}
-
-/*
- * Compute the log of the greatest power of 2 less than or equal to n.
- * This really just finds the highest set bit in the word.
- */
-JS_PUBLIC_API(JSIntn)
-JS_FloorLog2(JSUint32 n)
-{
-    JSIntn log2;
-
-    JS_FLOOR_LOG2(log2, n);
-    return log2;
-}
-
-/*
  * js_FloorLog2wImpl has to be defined only for 64-bit non-GCC case.
  */
 #if !defined(JS_HAS_BUILTIN_BITSCAN64) && JS_BYTES_PER_WORD == 8
 
 size_t
 js_FloorLog2wImpl(size_t n)
 {
     size_t log2, m;
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -67,17 +67,16 @@
 #include "jsinterp.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsprf.h"
 #include "jsscope.h"
 #include "jsstr.h"
 #include "jstracer.h"
-#include "jsvector.h"
 #include "jslibmath.h"
 
 #include "vm/GlobalObject.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsnuminlines.h"
 #include "jsobjinlines.h"
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -40,17 +40,16 @@
 
 /*
  * JS object implementation.
  */
 #include <stdlib.h>
 #include <string.h>
 #include "jstypes.h"
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsutil.h"
 #include "jshash.h"
 #include "jsdhash.h"
 #include "jsprf.h"
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsatom.h"
 #include "jsbool.h"
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -52,17 +52,16 @@
 #include "jsapi.h"
 #include "jsclass.h"
 #include "jsfriendapi.h"
 #include "jsinfer.h"
 #include "jshash.h"
 #include "jspubtd.h"
 #include "jsprvtd.h"
 #include "jslock.h"
-#include "jsvector.h"
 #include "jscell.h"
 
 #include "vm/String.h"
 
 namespace nanojit { class ValidateWriter; }
 
 namespace js {
 
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -66,17 +66,16 @@
 #include "jsscriptinlines.h"
 #include "jsstr.h"
 
 #include "vm/GlobalObject.h"
 
 #include "jsatominlines.h"
 #include "jsfuninlines.h"
 #include "jsgcinlines.h"
-#include "jsprobes.h"
 #include "jsscopeinlines.h"
 
 inline bool
 JSObject::preventExtensions(JSContext *cx, js::AutoIdVector *props)
 {
     JS_ASSERT(isExtensible());
 
     if (js::FixOp fix = getOps()->fix) {
--- a/js/src/json.cpp
+++ b/js/src/json.cpp
@@ -45,27 +45,25 @@
 #include "jsatom.h"
 #include "jsbool.h"
 #include "jscntxt.h"
 #include "jsfun.h"
 #include "jsinterp.h"
 #include "jsiter.h"
 #include "jsnum.h"
 #include "jsobj.h"
+#include "json.h"
 #include "jsonparser.h"
 #include "jsprf.h"
 #include "jsscan.h"
 #include "jsstr.h"
 #include "jstypes.h"
 #include "jsstdint.h"
 #include "jsutil.h"
 #include "jsxml.h"
-#include "jsvector.h"
-
-#include "json.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsstrinlines.h"
 
 #include "vm/Stack-inl.h"
 
--- a/js/src/json.h
+++ b/js/src/json.h
@@ -35,17 +35,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef json_h___
 #define json_h___
 
 #include "jsprvtd.h"
 #include "jspubtd.h"
-#include "jsvector.h"
+
+#include "js/Vector.h"
 
 #define JSON_MAX_DEPTH  2048
 #define JSON_PARSER_BUFSIZE 1024
 
 extern JSObject *
 js_InitJSONClass(JSContext *cx, JSObject *obj);
 
 extern JSBool
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -63,17 +63,16 @@
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
 #include "jsstaticcheck.h"
-#include "jsvector.h"
 
 #include "vm/Debugger.h"
 
 #include "jscntxtinlines.h"
 #include "jsobjinlines.h"
 #include "jsopcodeinlines.h"
 #include "jsscriptinlines.h"
 
@@ -4095,17 +4094,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                      * un-parenthesized generator expression. The ss->inGenExp
                      * special case of JSOP_YIELD shares array comprehension
                      * decompilation code that leaves the result as the single
                      * string pushed on ss2.
                      */
                     outer = jp->script;
                     outerfun = jp->fun;
                     outerLocalNames = jp->localNames;
-                    LOCAL_ASSERT(JS_UPTRDIFF(pc, outer->code) <= outer->length);
+                    LOCAL_ASSERT(UnsignedPtrDiff(pc, outer->code) <= outer->length);
                     jp->script = inner;
                     jp->fun = fun;
                     jp->localNames = innerLocalNames;
 
                     /*
                      * Decompile only the main bytecode, to avoid tripping over
                      * new prolog ops that have stack effects.
                      */
--- a/js/src/jsotypes.h
+++ b/js/src/jsotypes.h
@@ -90,14 +90,9 @@ typedef JSInt64 int64;
 /* /usr/include/model.h on HP-UX defines int8, int16, and int32 */
 typedef JSInt32 int32;
 typedef JSInt16 int16;
 typedef JSInt8 int8;
 #endif /* AIX && HAVE_SYS_INTTYPES_H */
 
 typedef JSFloat64 float64;
 
-/* Re: jsbit.h */
-#define TEST_BIT        JS_TEST_BIT
-#define SET_BIT         JS_SET_BIT
-#define CLEAR_BIT       JS_CLEAR_BIT
-
 #endif /* !defined(PROTYPES_H) */
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -75,17 +75,16 @@
 #include "jsparse.h"
 #include "jsprobes.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
 #include "jsstaticcheck.h"
 #include "jslibmath.h"
-#include "jsvector.h"
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
 
 #if JS_HAS_DESTRUCTURING
 #include "jsdhash.h"
 #endif
--- a/js/src/jsparse.h
+++ b/js/src/jsparse.h
@@ -1072,17 +1072,17 @@ struct JSFunctionBoxQueue {
 
     size_t count()  { return head - tail; }
     size_t length() { return lengthMask + 1; }
 
     JSFunctionBoxQueue()
       : vector(NULL), head(0), tail(0), lengthMask(0) { }
 
     bool init(uint32 count) {
-        lengthMask = JS_BITMASK(JS_CeilingLog2(count));
+        lengthMask = JS_BITMASK(JS_CEILING_LOG2W(count));
         vector = (JSFunctionBox **) js::OffTheBooks::malloc_(sizeof(JSFunctionBox) * length());
         return !!vector;
     }
 
     ~JSFunctionBoxQueue() { js::UnwantedForeground::free_(vector); }
 
     void push(JSFunctionBox *funbox) {
         if (!funbox->queued) {
--- a/js/src/jsprobes.cpp
+++ b/js/src/jsprobes.cpp
@@ -60,16 +60,158 @@
 
 using namespace js;
 
 const char Probes::nullName[] = "(null)";
 const char Probes::anonymousName[] = "(anonymous)";
 
 bool Probes::ProfilingActive = true;
 
+static Vector<Probes::JITWatcher*, 4, SystemAllocPolicy> jitWatchers;
+
+bool
+Probes::addJITWatcher(JITWatcher *watcher)
+{
+    return jitWatchers.append(watcher);
+}
+
+bool
+Probes::removeJITWatcher(JSRuntime *rt, JITWatcher *watcher)
+{
+    JITWatcher **place = Find(jitWatchers, watcher);
+    if (!place)
+        return false;
+    if (rt)
+        rt->delete_(*place);
+    else
+        Foreground::delete_(*place);
+    jitWatchers.erase(place);
+    return true;
+}
+
+void
+Probes::removeAllJITWatchers(JSRuntime *rt)
+{
+    if (rt) {
+        for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+            rt->delete_(*p);
+    } else {
+        for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+            Foreground::delete_(*p);
+    }
+    jitWatchers.clear();
+}
+
+Probes::JITReportGranularity
+Probes::JITGranularityRequested()
+{
+    JITReportGranularity want = JITREPORT_GRANULARITY_NONE;
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p) {
+        JITReportGranularity request = (*p)->granularityRequested();
+        if (request > want)
+            want = request;
+    }
+
+    return want;
+}
+
+#ifdef JS_METHODJIT
+void
+Probes::registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
+                         JSScript *script, JSFunction *fun,
+                         js::mjit::Compiler_ActiveFrame **inlineFrames,
+                         void *mainCodeAddress, size_t mainCodeSize,
+                         void *stubCodeAddress, size_t stubCodeSize)
+{
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+        (*p)->registerMJITCode(cx, jscr, script, fun,
+                               inlineFrames,
+                               mainCodeAddress, mainCodeSize,
+                               stubCodeAddress, stubCodeSize);
+}
+
+void
+Probes::discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script, void* address)
+{
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+        (*p)->discardMJITCode(cx, jscr, script, address);
+}
+
+void
+Probes::registerICCode(JSContext *cx,
+                       mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
+                       void *start, size_t size)
+{
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+        (*p)->registerICCode(cx, jscr, script, pc, start, size);
+}
+#endif
+
+/* ICs are unregistered in a batch */
+void
+Probes::discardExecutableRegion(void *start, size_t size)
+{
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+        (*p)->discardExecutableRegion(start, size);
+}
+
+static JSRuntime *initRuntime;
+
+JSBool
+Probes::startEngine()
+{
+    bool ok = true;
+
+    return ok;
+}
+
+bool
+Probes::createRuntime(JSRuntime *rt)
+{
+    bool ok = true;
+
+    static JSCallOnceType once = { 0 };
+    initRuntime = rt;
+    if (!JS_CallOnce(&once, Probes::startEngine))
+        ok = false;
+
+#ifdef MOZ_ETW
+    if (!ETWCreateRuntime(rt))
+        ok = false;
+#endif
+
+    return ok;
+}
+
+bool
+Probes::destroyRuntime(JSRuntime *rt)
+{
+    bool ok = true;
+#ifdef MOZ_ETW
+    if (!ETWDestroyRuntime(rt))
+        ok = false;
+#endif
+
+    return ok;
+}
+
+bool
+Probes::shutdown()
+{
+    bool ok = true;
+#ifdef MOZ_ETW
+    if (!ETWShutdown())
+        ok = false;
+#endif
+
+    Probes::removeAllJITWatchers(NULL);
+
+    return ok;
+}
+
 #ifdef INCLUDE_MOZILLA_DTRACE
 static const char *
 ScriptFilename(const JSScript *script)
 {
     if (!script)
         return Probes::nullName;
     if (!script->filename)
         return Probes::anonymousName;
--- a/js/src/jsprobes.h
+++ b/js/src/jsprobes.h
@@ -40,19 +40,26 @@
 #ifndef _JSPROBES_H
 #define _JSPROBES_H
 
 #ifdef INCLUDE_MOZILLA_DTRACE
 #include "javascript-trace.h"
 #endif
 #include "jspubtd.h"
 #include "jsprvtd.h"
+#include "jsscript.h"
+#include "jsobj.h"
 
 namespace js {
 
+namespace mjit {
+struct NativeAddressInfo;
+struct Compiler_ActiveFrame;
+}
+
 namespace Probes {
 
 /*
  * Static probes
  *
  * The probe points defined in this file are scattered around the SpiderMonkey
  * source tree. The presence of Probes::someEvent() means that someEvent is
  * about to happen or has happened. To the extent possible, probes should be
@@ -80,32 +87,41 @@ namespace Probes {
  * Internal use only: remember whether "profiling", whatever that means, is
  * currently active. Used for state management.
  */
 extern bool ProfilingActive;
 
 extern const char nullName[];
 extern const char anonymousName[];
 
+/* Called when first runtime is created for this process */
+JSBool startEngine();
+
 /* JSRuntime created, with currently valid fields */
 bool createRuntime(JSRuntime *rt);
 
 /* JSRuntime about to be destroyed */
 bool destroyRuntime(JSRuntime *rt);
 
 /* Total JS engine shutdown */
 bool shutdown();
 
 /*
  * Test whether we are tracking JS function call enter/exit. The JITs use this
  * to decide whether they can optimize in a way that would prevent probes from
  * firing.
  */
 bool callTrackingActive(JSContext *);
 
+/*
+ * Test whether anything is looking for JIT native code registration events.
+ * This information will not be collected otherwise.
+ */
+bool wantNativeAddressInfo(JSContext *);
+
 /* Entering a JS function */
 bool enterJSFun(JSContext *, JSFunction *, JSScript *, int counter = 1);
 
 /* About to leave a JS function */
 bool exitJSFun(JSContext *, JSFunction *, JSScript *, int counter = 0);
 
 /* Executing a script */
 bool startExecution(JSContext *cx, JSScript *script);
@@ -190,16 +206,111 @@ bool GCEndSweepPhase(JSCompartment *comp
  * application-meaningful events and phases of execution.
  *
  * Not all backends support these.
  */
 bool CustomMark(JSString *string);
 bool CustomMark(const char *string);
 bool CustomMark(int marker);
 
+/* JIT code observation */
+
+enum JITReportGranularity {
+    JITREPORT_GRANULARITY_NONE = 0,
+    JITREPORT_GRANULARITY_FUNCTION = 1,
+    JITREPORT_GRANULARITY_LINE = 2,
+    JITREPORT_GRANULARITY_OP = 3
+};
+
+/*
+ * Observer class for JIT code allocation/deallocation. Currently, this only
+ * handles the method JIT, and does not get notifications when JIT code is
+ * changed (patched) with no new allocation.
+ */
+class JITWatcher {
+public:
+    virtual JITReportGranularity granularityRequested() = 0;
+
+#ifdef JS_METHODJIT
+    virtual void registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
+                                  JSScript *script, JSFunction *fun,
+                                  mjit::Compiler_ActiveFrame** inlineFrames,
+                                  void *mainCodeAddress, size_t mainCodeSize,
+                                  void *stubCodeAddress, size_t stubCodeSize) = 0;
+
+    virtual void discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script,
+                                 void* address) = 0;
+
+    virtual void registerICCode(JSContext *cx,
+                                js::mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
+                                void *start, size_t size) = 0;
+#endif
+
+    virtual void discardExecutableRegion(void *start, size_t size) = 0;
+};
+
+/*
+ * Register a JITWatcher subclass to be informed of JIT code
+ * allocation/deallocation.
+ */
+bool
+addJITWatcher(JITWatcher *watcher);
+
+/*
+ * Remove (and destroy) a registered JITWatcher. rt may be NULL. Returns false
+ * if the watcher is not found.
+ */
+bool
+removeJITWatcher(JSRuntime *rt, JITWatcher *watcher);
+
+/*
+ * Remove (and destroy) all registered JITWatchers. rt may be NULL.
+ */
+void
+removeAllJITWatchers(JSRuntime *rt);
+
+/*
+ * Finest granularity of JIT information desired by all watchers.
+ */
+JITReportGranularity
+JITGranularityRequested();
+
+#ifdef JS_METHODJIT
+/*
+ * New method JIT code has been created
+ */
+void
+registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
+                 JSScript *script, JSFunction *fun,
+                 mjit::Compiler_ActiveFrame** inlineFrames,
+                 void *mainCodeAddress, size_t mainCodeSize,
+                 void *stubCodeAddress, size_t stubCodeSize);
+
+/*
+ * Method JIT code is about to be discarded
+ */
+void
+discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script, void* address);
+
+/*
+ * IC code has been allocated within the given JITScript
+ */
+void
+registerICCode(JSContext *cx,
+               mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
+               void *start, size_t size);
+#endif /* JS_METHODJIT */
+
+/*
+ * A whole region of code has been deallocated, containing any number of ICs.
+ * (ICs are unregistered in a batch, so individual ICs are not registered.)
+ */
+void
+discardExecutableRegion(void *start, size_t size);
+
 /*
  * Internal: DTrace-specific functions to be called during Probes::enterJSFun
  * and Probes::exitJSFun. These will not be inlined, but the argument
  * marshalling required for these probe points is expensive enough that it
  * shouldn't really matter.
  */
 void DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
 void DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
@@ -238,54 +349,21 @@ bool ETWCustomMark(int marker);
 bool ETWStartExecution(JSContext *cx, JSScript *script);
 bool ETWStopExecution(JSContext *cx, JSScript *script);
 bool ETWResizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize);
 #endif
 
 } /* namespace Probes */
 
 /*
- * Probe handlers are implemented inline for minimal performance impact,
+ * Many probe handlers are implemented inline for minimal performance impact,
  * especially important when no backends are enabled.
  */
 
 inline bool
-Probes::createRuntime(JSRuntime *rt)
-{
-    bool ok = true;
-#ifdef MOZ_ETW
-    if (!ETWCreateRuntime(rt))
-        ok = false;
-#endif
-    return ok;
-}
-
-inline bool
-Probes::destroyRuntime(JSRuntime *rt)
-{
-    bool ok = true;
-#ifdef MOZ_ETW
-    if (!ETWDestroyRuntime(rt))
-        ok = false;
-#endif
-    return ok;
-}
-
-inline bool
-Probes::shutdown()
-{
-    bool ok = true;
-#ifdef MOZ_ETW
-    if (!ETWShutdown())
-        ok = false;
-#endif
-    return ok;
-}
-
-inline bool
 Probes::callTrackingActive(JSContext *cx)
 {
 #ifdef INCLUDE_MOZILLA_DTRACE
     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED() || JAVASCRIPT_FUNCTION_RETURN_ENABLED())
         return true;
 #endif
 #ifdef MOZ_TRACE_JSCALLS
     if (cx->functionCallback)
@@ -294,16 +372,23 @@ Probes::callTrackingActive(JSContext *cx
 #ifdef MOZ_ETW
     if (ProfilingActive && ETWCallTrackingActive(cx))
         return true;
 #endif
     return false;
 }
 
 inline bool
+Probes::wantNativeAddressInfo(JSContext *cx)
+{
+    return (cx->reportGranularity >= JITREPORT_GRANULARITY_FUNCTION &&
+            JITGranularityRequested() >= JITREPORT_GRANULARITY_FUNCTION);
+}
+
+inline bool
 Probes::enterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
 {
     bool ok = true;
 #ifdef INCLUDE_MOZILLA_DTRACE
     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
         DTraceEnterJSFun(cx, fun, script);
 #endif
 #ifdef MOZ_TRACE_JSCALLS
--- a/js/src/jspropertycache.cpp
+++ b/js/src/jspropertycache.cpp
@@ -493,17 +493,17 @@ PropertyCache::purge(JSContext *cx)
 }
 
 void
 PropertyCache::purgeForScript(JSContext *cx, JSScript *script)
 {
     JS_ASSERT(!cx->runtime->gcRunning);
 
     for (PropertyCacheEntry *entry = table; entry < table + SIZE; entry++) {
-        if (JS_UPTRDIFF(entry->kpc, script->code) < script->length) {
+        if (UnsignedPtrDiff(entry->kpc, script->code) < script->length) {
             entry->kpc = NULL;
 #ifdef DEBUG
             entry->kshape = entry->vcap = 0;
             entry->vword.setNull();
 #endif
         }
     }
 }
--- a/js/src/jspropertytree.h
+++ b/js/src/jspropertytree.h
@@ -35,19 +35,20 @@
  * 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 jspropertytree_h___
 #define jspropertytree_h___
 
-#include "jshashtable.h"
 #include "jsprvtd.h"
 
+#include "js/HashTable.h"
+
 namespace js {
 
 struct ShapeHasher {
     typedef js::Shape *Key;
     typedef const js::Shape *Lookup;
 
     static inline HashNumber hash(const Lookup l);
     static inline bool match(Key k, Lookup l);
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -872,17 +872,16 @@ Proxy::typeOf(JSContext *cx, JSObject *p
     JS_CHECK_RECURSION(cx, return JSTYPE_OBJECT);
     AutoPendingProxyOperation pending(cx, proxy);
     return GetProxyHandler(proxy)->typeOf(cx, proxy);
 }
 
 bool
 Proxy::objectClassIs(JSObject *proxy, ESClassValue classValue, JSContext *cx)
 {
-    JS_CHECK_RECURSION(cx, JS_NOT_REACHED("cannot reenter"));
     AutoPendingProxyOperation pending(cx, proxy);
     return GetProxyHandler(proxy)->objectClassIs(proxy, classValue, cx);
 }
 
 JSString *
 Proxy::obj_toString(JSContext *cx, JSObject *proxy)
 {
     JS_CHECK_RECURSION(cx, return NULL);
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -236,11 +236,18 @@ typedef struct JSXDRState               
 #ifdef __cplusplus
 class                                       JSFlatString;
 class                                       JSString;
 #else
 typedef struct JSFlatString                 JSFlatString;
 typedef struct JSString                     JSString;
 #endif
 
+#ifdef JS_THREADSAFE
+typedef struct PRCallOnceType    JSCallOnceType;
+#else
+typedef JSBool                   JSCallOnceType;
+#endif
+typedef JSBool                 (*JSInitCallback)(void);
+
 JS_END_EXTERN_C
 
 #endif /* jspubtd_h___ */
--- a/js/src/jsreflect.cpp
+++ b/js/src/jsreflect.cpp
@@ -42,21 +42,19 @@
  */
 #include <stdlib.h>
 #include <string.h>     /* for jsparse.h */
 #include "jspubtd.h"
 #include "jsatom.h"
 #include "jsobj.h"
 #include "jsreflect.h"
 #include "jscntxt.h"    /* for jsparse.h */
-#include "jsbit.h"      /* for jsparse.h */
 #include "jsscript.h"   /* for jsparse.h */
 #include "jsinterp.h"   /* for jsparse.h */
 #include "jsparse.h"
-#include "jsvector.h"
 #include "jsemit.h"
 #include "jsscan.h"
 #include "jsprf.h"
 #include "jsiter.h"
 #include "jsbool.h"
 #include "jsval.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
--- a/js/src/jsscan.cpp
+++ b/js/src/jsscan.cpp
@@ -49,32 +49,30 @@
 #ifdef HAVE_MEMORY_H
 #include <memory.h>
 #endif
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
 #include "jstypes.h"
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsutil.h"
 #include "jsprf.h"
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jscntxt.h"
 #include "jsversion.h"
 #include "jsemit.h"
 #include "jsexn.h"
 #include "jsnum.h"
 #include "jsopcode.h"
 #include "jsparse.h"
 #include "jsscan.h"
 #include "jsscript.h"
 #include "jsstaticcheck.h"
-#include "jsvector.h"
 
 #include "vm/RegExpObject.h"
 
 #include "jsscriptinlines.h"
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
 #endif
--- a/js/src/jsscan.h
+++ b/js/src/jsscan.h
@@ -46,17 +46,18 @@
 #include <stddef.h>
 #include <stdio.h>
 #include <stdarg.h>
 #include "jscntxt.h"
 #include "jsversion.h"
 #include "jsopcode.h"
 #include "jsprvtd.h"
 #include "jspubtd.h"
-#include "jsvector.h"
+
+#include "js/Vector.h"
 
 #define JS_KEYWORD(keyword, type, op, version) \
     extern const char js_##keyword##_str[];
 #include "jskeyword.tbl"
 #undef JS_KEYWORD
 
 namespace js {
 
--- a/js/src/jsscope.cpp
+++ b/js/src/jsscope.cpp
@@ -41,17 +41,16 @@
 /*
  * JS symbol tables.
  */
 #include <new>
 #include <stdlib.h>
 #include <string.h>
 #include "jstypes.h"
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsclist.h"
 #include "jsdhash.h"
 #include "jsutil.h"
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jscntxt.h"
 #include "jsdbgapi.h"
 #include "jslock.h"
@@ -83,18 +82,17 @@ js_GenerateShape(JSRuntime *rt)
          * have a chance to wrap around shapeGen to zero.
          */
         rt->shapeGen = SHAPE_OVERFLOW_BIT;
         shape = SHAPE_OVERFLOW_BIT;
 
 #ifdef JS_THREADSAFE
         AutoLockGC lockIf(rt);
 #endif
-        GCREASON(SHAPE);
-        TriggerGC(rt);
+        TriggerGC(rt, gcstats::SHAPE);
     }
     return shape;
 }
 
 uint32
 js_GenerateShape(JSContext *cx)
 {
     return js_GenerateShape(cx->runtime);
@@ -136,17 +134,17 @@ PropertyTable::init(JSRuntime *rt, Shape
 {
     /*
      * Either we're creating a table for a large scope that was populated
      * via property cache hit logic under JSOP_INITPROP, JSOP_SETNAME, or
      * JSOP_SETPROP; or else calloc failed at least once already. In any
      * event, let's try to grow, overallocating to hold at least twice the
      * current population.
      */
-    uint32 sizeLog2 = JS_CeilingLog2(2 * entryCount);
+    uint32 sizeLog2 = JS_CEILING_LOG2W(2 * entryCount);
     if (sizeLog2 < MIN_SIZE_LOG2)
         sizeLog2 = MIN_SIZE_LOG2;
 
     /*
      * Use rt->calloc_ for memory accounting and overpressure handling
      * without OOM reporting. See PropertyTable::change.
      */
     entries = (Shape **) rt->calloc_(sizeOfEntries(JS_BIT(sizeLog2)));
--- a/js/src/jsscope.h
+++ b/js/src/jsscope.h
@@ -47,22 +47,23 @@
 #ifdef DEBUG
 #include <stdio.h>
 #endif
 
 #include "jstypes.h"
 
 #include "jscntxt.h"
 #include "jscompartment.h"
-#include "jshashtable.h"
 #include "jsobj.h"
 #include "jsprvtd.h"
 #include "jspubtd.h"
 #include "jspropertytree.h"
 
+#include "js/HashTable.h"
+
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4800)
 #pragma warning(push)
 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
 #endif
 
 /*
--- a/js/src/jsstaticcheck.h
+++ b/js/src/jsstaticcheck.h
@@ -35,91 +35,9 @@
  * 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 jsstaticcheck_h___
 #define jsstaticcheck_h___
 
-#ifdef NS_STATIC_CHECKING
-/*
- * Trigger a control flow check to make sure that code flows through label
- */
-inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {
-}
-
-/* avoid unused goto-label warnings */
-#define MUST_FLOW_LABEL(label) goto label; label:
-
-inline JS_FORCES_STACK void VOUCH_DOES_NOT_REQUIRE_STACK() {}
-
-inline JS_FORCES_STACK void
-JS_ASSERT_NOT_ON_TRACE(JSContext *cx)
-{
-    JS_ASSERT(!JS_ON_TRACE(cx));
-}
-
-#else
-#define MUST_FLOW_THROUGH(label)            ((void) 0)
-#define MUST_FLOW_LABEL(label)
-#define VOUCH_DOES_NOT_REQUIRE_STACK()      ((void) 0)
-#define JS_ASSERT_NOT_ON_TRACE(cx)          JS_ASSERT(!JS_ON_TRACE(cx))
-#endif
-#define VOUCH_HAVE_STACK                    VOUCH_DOES_NOT_REQUIRE_STACK
-
-/* sixgill annotation defines */
-
-/* Avoid name collision if included with other headers defining annotations. */
-#ifndef HAVE_STATIC_ANNOTATIONS
-#define HAVE_STATIC_ANNOTATIONS
-
-#ifdef XGILL_PLUGIN
-
-#define STATIC_PRECONDITION(COND)         __attribute__((precondition(#COND)))
-#define STATIC_PRECONDITION_ASSUME(COND)  __attribute__((precondition_assume(#COND)))
-#define STATIC_POSTCONDITION(COND)        __attribute__((postcondition(#COND)))
-#define STATIC_POSTCONDITION_ASSUME(COND) __attribute__((postcondition_assume(#COND)))
-#define STATIC_INVARIANT(COND)            __attribute__((invariant(#COND)))
-#define STATIC_INVARIANT_ASSUME(COND)     __attribute__((invariant_assume(#COND)))
-
-/* Used to make identifiers for assert/assume annotations in a function. */
-#define STATIC_PASTE2(X,Y) X ## Y
-#define STATIC_PASTE1(X,Y) STATIC_PASTE2(X,Y)
-
-#define STATIC_ASSERT(COND)                          \
-  JS_BEGIN_MACRO                                     \
-    __attribute__((assert_static(#COND), unused))    \
-    int STATIC_PASTE1(assert_static_, __COUNTER__);  \
-  JS_END_MACRO
-
-#define STATIC_ASSUME(COND)                          \
-  JS_BEGIN_MACRO                                     \
-    __attribute__((assume_static(#COND), unused))    \
-    int STATIC_PASTE1(assume_static_, __COUNTER__);  \
-  JS_END_MACRO
-
-#define STATIC_ASSERT_RUNTIME(COND)                         \
-  JS_BEGIN_MACRO                                            \
-    __attribute__((assert_static_runtime(#COND), unused))   \
-    int STATIC_PASTE1(assert_static_runtime_, __COUNTER__); \
-  JS_END_MACRO
-
-#else /* XGILL_PLUGIN */
-
-#define STATIC_PRECONDITION(COND)          /* nothing */
-#define STATIC_PRECONDITION_ASSUME(COND)   /* nothing */
-#define STATIC_POSTCONDITION(COND)         /* nothing */
-#define STATIC_POSTCONDITION_ASSUME(COND)  /* nothing */
-#define STATIC_INVARIANT(COND)             /* nothing */
-#define STATIC_INVARIANT_ASSUME(COND)      /* nothing */
-
-#define STATIC_ASSERT(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
-#define STATIC_ASSUME(COND)          JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
-#define STATIC_ASSERT_RUNTIME(COND)  JS_BEGIN_MACRO /* nothing */ JS_END_MACRO
-
-#endif /* XGILL_PLUGIN */
-
-#define STATIC_SKIP_INFERENCE STATIC_INVARIANT(skip_inference())
-
-#endif /* HAVE_STATIC_ANNOTATIONS */
-
 #endif /* jsstaticcheck_h___ */
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -66,18 +66,16 @@
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsprobes.h"
 #include "jsscope.h"
 #include "jsstaticcheck.h"
 #include "jsstr.h"
-#include "jsbit.h"
-#include "jsvector.h"
 #include "jsversion.h"
 
 #include "vm/GlobalObject.h"
 #include "vm/RegExpObject.h"
 
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsautooplen.h"        // generated headers last
--- a/js/src/jsstr.h
+++ b/js/src/jsstr.h
@@ -39,20 +39,20 @@
 
 #ifndef jsstr_h___
 #define jsstr_h___
 
 #include <ctype.h>
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jsprvtd.h"
-#include "jshashtable.h"
 #include "jslock.h"
 #include "jscell.h"
 
+#include "js/HashTable.h"
 #include "vm/Unicode.h"
 
 namespace js {
 
 /* Implemented in jsstrinlines.h */
 class StringBuffer;
 
 /*
deleted file mode 100644
--- a/js/src/jstl.h
+++ /dev/null
@@ -1,447 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sw=4 et tw=99 ft=cpp:
- *
- * ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
- * July 16, 2009.
- *
- * The Initial Developer of the Original Code is
- *   the Mozilla Corporation.
- *
- * Contributor(s):
- *   Luke Wagner <lw@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef jstl_h_
-#define jstl_h_
-
-#include "jsprvtd.h"
-#include "jsbit.h"
-#include "jsstaticcheck.h"
-#include "jsstdint.h"
-
-#include <new>
-#include <string.h>
-
-namespace js {
-
-/* JavaScript Template Library. */
-namespace tl {
-
-/* Compute min/max/clamp. */
-template <size_t i, size_t j> struct Min {
-    static const size_t result = i < j ? i : j;
-};
-template <size_t i, size_t j> struct Max {
-    static const size_t result = i > j ? i : j;
-};
-template <size_t i, size_t min, size_t max> struct Clamp {
-    static const size_t result = i < min ? min : (i > max ? max : i);
-};
-
-/* Compute x^y. */
-template <size_t x, size_t y> struct Pow {
-    static const size_t result = x * Pow<x, y - 1>::result;
-};
-template <size_t x> struct Pow<x,0> {
-    static const size_t result = 1;
-};
-
-/* Compute floor(log2(i)). */
-template <size_t i> struct FloorLog2 {
-    static const size_t result = 1 + FloorLog2<i / 2>::result;
-};
-template <> struct FloorLog2<0> { /* Error */ };
-template <> struct FloorLog2<1> { static const size_t result = 0; };
-
-/* Compute ceiling(log2(i)). */
-template <size_t i> struct CeilingLog2 {
-    static const size_t result = FloorLog2<2 * i - 1>::result;
-};
-
-/* Round up to the nearest power of 2. */
-template <size_t i> struct RoundUpPow2 {
-    static const size_t result = 1u << CeilingLog2<i>::result;
-};
-template <> struct RoundUpPow2<0> {
-    static const size_t result = 1;
-};
-
-/* Compute the number of bits in the given unsigned type. */
-template <class T> struct BitSize {
-    static const size_t result = sizeof(T) * JS_BITS_PER_BYTE;
-};
-
-/* Allow Assertions by only including the 'result' typedef if 'true'. */
-template <bool> struct StaticAssert {};
-template <> struct StaticAssert<true> { typedef int result; };
-
-/* Boolean test for whether two types are the same. */
-template <class T, class U> struct IsSameType {
-    static const bool result = false;
-};
-template <class T> struct IsSameType<T,T> {
-    static const bool result = true;
-};
-
-/*
- * Produce an N-bit mask, where N <= BitSize<size_t>::result.  Handle the
- * language-undefined edge case when N = BitSize<size_t>::result.
- */
-template <size_t N> struct NBitMask {
-    typedef typename StaticAssert<N < BitSize<size_t>::result>::result _;
-    static const size_t result = (size_t(1) << N) - 1;
-};
-template <> struct NBitMask<BitSize<size_t>::result> {
-    static const size_t result = size_t(-1);
-};
-
-/*
- * For the unsigned integral type size_t, compute a mask M for N such that
- * for all X, !(X & M) implies X * N will not overflow (w.r.t size_t)
- */
-template <size_t N> struct MulOverflowMask {
-    static const size_t result =
-        ~NBitMask<BitSize<size_t>::result - CeilingLog2<N>::result>::result;
-};
-template <> struct MulOverflowMask<0> { /* Error */ };
-template <> struct MulOverflowMask<1> { static const size_t result = 0; };
-
-/*
- * Generate a mask for T such that if (X & sUnsafeRangeSizeMask), an X-sized
- * array of T's is big enough to cause a ptrdiff_t overflow when subtracting
- * a pointer to the end of the array from the beginning.
- */
-template <class T> struct UnsafeRangeSizeMask {
-    /*
-     * The '2' factor means the top bit is clear, sizeof(T) converts from
-     * units of elements to bytes.
-     */
-    static const size_t result = MulOverflowMask<2 * sizeof(T)>::result;
-};
-
-/* Return T stripped of any const-ness. */
-template <class T> struct StripConst          { typedef T result; };
-template <class T> struct StripConst<const T> { typedef T result; };
-
-/*
- * Traits class for identifying POD types. Until C++0x, there is no automatic
- * way to detect PODs, so for the moment it is done manually.
- */
-template <class T> struct IsPodType                 { static const bool result = false; };
-template <> struct IsPodType<char>                  { static const bool result = true; };
-template <> struct IsPodType<signed char>           { static const bool result = true; };
-template <> struct IsPodType<unsigned char>         { static const bool result = true; };
-template <> struct IsPodType<short>                 { static const bool result = true; };
-template <> struct IsPodType<unsigned short>        { static const bool result = true; };
-template <> struct IsPodType<int>                   { static const bool result = true; };
-template <> struct IsPodType<unsigned int>          { static const bool result = true; };
-template <> struct IsPodType<long>                  { static const bool result = true; };
-template <> struct IsPodType<unsigned long>         { static const bool result = true; };
-template <> struct IsPodType<long long>             { static const bool result = true; };
-template <> struct IsPodType<unsigned long long>    { static const bool result = true; };
-template <> struct IsPodType<float>                 { static const bool result = true; };
-template <> struct IsPodType<double>                { static const bool result = true; };
-template <> struct IsPodType<wchar_t>               { static const bool result = true; };
-template <typename T> struct IsPodType<T *>         { static const bool result = true; };
-
-/* Return the size/end of an array without using macros. */
-template <class T, size_t N> inline T *ArraySize(T (&)[N]) { return N; }
-template <class T, size_t N> inline T *ArrayEnd(T (&arr)[N]) { return arr + N; }
-
-template <bool cond, typename T, T v1, T v2> struct If        { static const T result = v1; };
-template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T result = v2; };
-
-} /* namespace tl */
-
-/* Useful for implementing containers that assert non-reentrancy */
-class ReentrancyGuard
-{
-    /* ReentrancyGuard is not copyable. */
-    ReentrancyGuard(const ReentrancyGuard &);
-    void operator=(const ReentrancyGuard &);
-
-#ifdef DEBUG
-    bool &entered;
-#endif
-  public:
-    template <class T>
-#ifdef DEBUG
-    ReentrancyGuard(T &obj)
-      : entered(obj.entered)
-#else
-    ReentrancyGuard(T &/*obj*/)
-#endif
-    {
-#ifdef DEBUG
-        JS_ASSERT(!entered);
-        entered = true;
-#endif
-    }
-    ~ReentrancyGuard()
-    {
-#ifdef DEBUG
-        entered = false;
-#endif
-    }
-};
-
-/*
- * Round x up to the nearest power of 2.  This function assumes that the most
- * significant bit of x is not set, which would lead to overflow.
- */
-STATIC_POSTCONDITION_ASSUME(return >= x)
-JS_ALWAYS_INLINE size_t
-RoundUpPow2(size_t x)
-{
-    size_t log2 = JS_CEILING_LOG2W(x);
-    JS_ASSERT(log2 < tl::BitSize<size_t>::result);
-    size_t result = size_t(1) << log2;
-    return result;
-}
-
-template <class T>
-class AlignedPtrAndFlag
-{
-    uintptr_t bits;
-
-  public:
-    AlignedPtrAndFlag(T *t, bool flag) {
-        JS_ASSERT((uintptr_t(t) & 1) == 0);
-        bits = uintptr_t(t) | uintptr_t(flag);
-    }
-
-    T *ptr() const {
-        return (T *)(bits & ~uintptr_t(1));
-    }
-
-    bool flag() const {
-        return (bits & 1) != 0;
-    }
-
-    void setPtr(T *t) {
-        JS_ASSERT((uintptr_t(t) & 1) == 0);
-        bits = uintptr_t(t) | uintptr_t(flag());
-    }
-
-    void setFlag() {
-        bits |= 1;
-    }
-
-    void unsetFlag() {
-        bits &= ~uintptr_t(1);
-    }
-
-    void set(T *t, bool flag) {
-        JS_ASSERT((uintptr_t(t) & 1) == 0);
-        bits = uintptr_t(t) | flag;
-    }
-};
-
-template <class T>
-static inline void
-Reverse(T *beg, T *end)
-{
-    while (beg != end) {
-        if (--end == beg)
-            return;
-        T tmp = *beg;
-        *beg = *end;
-        *end = tmp;
-        ++beg;
-    }
-}
-
-template <class T>
-static inline T *
-Find(T *beg, T *end, const T &v)
-{
-    for (T *p = beg; p != end; ++p) {
-        if (*p == v)
-            return p;
-    }
-    return end;
-}
-
-template <class Container>
-static inline typename Container::ElementType *
-Find(Container &c, const typename Container::ElementType &v)
-{
-    return Find(c.begin(), c.end(), v);
-}
-
-template <typename InputIterT, typename CallableT>
-void
-ForEach(InputIterT begin, InputIterT end, CallableT f)
-{
-    for (; begin != end; ++begin)
-        f(*begin);
-}
-
-template <class T>
-static inline T
-Min(T t1, T t2)
-{
-    return t1 < t2 ? t1 : t2;
-}
-
-template <class T>
-static inline T
-Max(T t1, T t2)
-{
-    return t1 > t2 ? t1 : t2;
-}
-
-/* Allows a const variable to be initialized after its declaration. */
-template <class T>
-static T&
-InitConst(const T &t)
-{
-    return const_cast<T &>(t);
-}
-
-template <class T, class U>
-JS_ALWAYS_INLINE T &
-ImplicitCast(U &u)
-{
-    T &t = u;
-    return t;
-}
-
-template<typename T>
-class AutoScopedAssign
-{
-  private:
-    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
-    T *addr;
-    T old;
-
-  public:
-    AutoScopedAssign(T *addr, const T &value JS_GUARD_OBJECT_NOTIFIER_PARAM)
-        : addr(addr), old(*addr)
-    {
-        JS_GUARD_OBJECT_NOTIFIER_INIT;
-        *addr = value;
-    }
-
-    ~AutoScopedAssign() { *addr = old; }
-};
-
-template <class RefCountable>
-class AlreadyIncRefed
-{
-    typedef RefCountable *****ConvertibleToBool;
-
-    RefCountable *obj;
-
-  public:
-    explicit AlreadyIncRefed(RefCountable *obj) : obj(obj) {}
-
-    bool null() const { return obj == NULL; }
-    operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
-
-    RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
-    RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
-    RefCountable *get() const { return obj; }
-};
-
-template <class RefCountable>
-class NeedsIncRef
-{
-    typedef RefCountable *****ConvertibleToBool;
-
-    RefCountable *obj;
-
-  public:
-    explicit NeedsIncRef(RefCountable *obj) : obj(obj) {}
-
-    bool null() const { return obj == NULL; }
-    operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
-
-    RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
-    RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
-    RefCountable *get() const { return obj; }
-};
-
-template <class RefCountable>
-class AutoRefCount
-{
-    typedef RefCountable *****ConvertibleToBool;
-
-    JSContext *const cx;
-    RefCountable *obj;
-
-    AutoRefCount(const AutoRefCount &);
-    void operator=(const AutoRefCount &);
-
-  public:
-    explicit AutoRefCount(JSContext *cx)
-      : cx(cx), obj(NULL)
-    {}
-
-    AutoRefCount(JSContext *cx, NeedsIncRef<RefCountable> aobj)
-      : cx(cx), obj(aobj.get())
-    {
-        if (obj)
-            obj->incref(cx);
-    }
-
-    AutoRefCount(JSContext *cx, AlreadyIncRefed<RefCountable> aobj)
-      : cx(cx), obj(aobj.get())
-    {}
-
-    ~AutoRefCount() {
-        if (obj)
-            obj->decref(cx);
-    }
-
-    void reset(NeedsIncRef<RefCountable> aobj) {
-        if (obj)
-            obj->decref(cx);
-        obj = aobj.get();
-        if (obj)
-            obj->incref(cx);
-    }
-
-    void reset(AlreadyIncRefed<RefCountable> aobj) {
-        if (obj)
-            obj->decref(cx);
-        obj = aobj.get();
-    }
-
-    bool null() const { return obj == NULL; }
-    operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
-
-    RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
-    RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
-    RefCountable *get() const { return obj; }
-};
-
-} /* namespace js */
-
-#endif /* jstl_h_ */
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -35,17 +35,16 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "jsstdint.h"
-#include "jsbit.h"              // low-level (NSPR-based) headers next
 #include "jsprf.h"
 #include <math.h>               // standard headers next
 
 #if defined(_MSC_VER) || defined(__MINGW32__)
 #include <malloc.h>
 #ifdef _MSC_VER
 #define alloca _alloca
 #endif
@@ -70,17 +69,16 @@
 #include "jsinterp.h"
 #include "jsiter.h"
 #include "jsmath.h"
 #include "jsobj.h"
 #include "jsopcode.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstaticcheck.h"
-#include "jstl.h"
 #include "jstracer.h"
 #include "jsxml.h"
 #include "jstypedarray.h"
 
 #include "builtin/RegExp.h"
 
 #include "jsatominlines.h"
 #include "jscntxtinlines.h"
@@ -7934,32 +7932,32 @@ FinishJIT()
 JS_REQUIRES_STACK void
 PurgeScriptFragments(TraceMonitor* tm, JSScript* script)
 {
     debug_only_printf(LC_TMTracer,
                       "Purging fragments for JSScript %p.\n", (void*)script);
 
     /* A recorder script is being evaluated and can not be destroyed or GC-ed. */
     JS_ASSERT_IF(tm->recorder,
-                 JS_UPTRDIFF(tm->recorder->getTree()->ip, script->code) >= script->length);
+                 UnsignedPtrDiff(tm->recorder->getTree()->ip, script->code) >= script->length);
 
     for (LoopProfileMap::Enum e(*tm->loopProfiles); !e.empty(); e.popFront()) {
-        if (JS_UPTRDIFF(e.front().key, script->code) < script->length)
+        if (UnsignedPtrDiff(e.front().key, script->code) < script->length)
             e.removeFront();
     }
 
     TracedScriptSet::Ptr found = tm->tracedScripts.lookup(script);
     if (!found)
         return;
     tm->tracedScripts.remove(found);
 
     for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
         TreeFragment** fragp = &tm->vmfragments[i];
         while (TreeFragment* frag = *fragp) {
-            if (JS_UPTRDIFF(frag->ip, script->code) < script->length) {
+            if (UnsignedPtrDiff(frag->ip, script->code) < script->length) {
                 /* This fragment is associated with the script. */
                 debug_only_printf(LC_TMTracer,
                                   "Disconnecting TreeFragment %p "
                                   "with ip %p, in range [%p,%p).\n",
                                   (void*)frag, frag->ip, script->code,
                                   script->code + script->length);
 
                 JS_ASSERT(frag->root == frag);
@@ -7971,17 +7969,17 @@ PurgeScriptFragments(TraceMonitor* tm, J
                 continue;
             }
             fragp = &frag->next;
         }
     }
 
     RecordAttemptMap &table = *tm->recordAttempts;
     for (RecordAttemptMap::Enum e(table); !e.empty(); e.popFront()) {
-        if (JS_UPTRDIFF(e.front().key, script->code) < script->length)
+        if (UnsignedPtrDiff(e.front().key, script->code) < script->length)
             e.removeFront();
     }
 }
 
 bool
 OverfullJITCache(JSContext *cx, TraceMonitor* tm)
 {
     /*
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -46,17 +46,16 @@
 
 #include "jstypes.h"
 #include "jsbuiltins.h"
 #include "jscntxt.h"
 #include "jsdhash.h"
 #include "jsinterp.h"
 #include "jslock.h"
 #include "jsnum.h"
-#include "jsvector.h"
 #include "jscompartment.h"
 #include "Writer.h"
 
 namespace js {
 
 template <typename T>
 class Queue {
     T* _data;
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -53,18 +53,16 @@
 #include "jsversion.h"
 #include "jsgc.h"
 #include "jsgcmark.h"
 #include "jsinterp.h"
 #include "jslock.h"
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsstaticcheck.h"
-#include "jsbit.h"
-#include "jsvector.h"
 #include "jstypedarray.h"
 #include "jsutil.h"
 
 #include "vm/GlobalObject.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -103,17 +103,16 @@ JS_PUBLIC_API(void) JS_Assert(const char
     CrashInJS();
 }
 
 #ifdef JS_BASIC_STATS
 
 #include <math.h>
 #include <string.h>
 #include "jscompat.h"
-#include "jsbit.h"
 
 /*
  * Histogram bins count occurrences of values <= the bin label, as follows:
  *
  *   linear:  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10 or more
  *     2**x:  0,   1,   2,   4,   8,  16,  32,  64, 128, 256, 512 or more
  *    10**x:  0,   1,  10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 or more
  *
@@ -137,17 +136,17 @@ ValToBin(uintN logscale, uint32 val)
 {
     uintN bin;
 
     if (val <= 1)
         return val;
     bin = (logscale == 10)
           ? (uintN) ceil(log10((double) val))
           : (logscale == 2)
-          ? (uintN) JS_CeilingLog2(val)
+          ? (uintN) JS_CEILING_LOG2W(val)
           : val;
     return JS_MIN(bin, 10);
 }
 
 void
 JS_BasicStatsAccum(JSBasicStats *bs, uint32 val)
 {
     uintN oldscale, newscale, bin;
@@ -238,161 +237,17 @@ JS_DumpHistogram(JSBasicStats *bs, FILE 
             fprintf(fp, "[%6u, %6u]", val, end - 1);
         else
             fprintf(fp, "[%6u,   +inf]", val);
         fprintf(fp, ": %8u ", cnt);
         if (cnt != 0) {
             if (max > 1e6 && mean > 1e3)
                 cnt = (uint32) ceil(log10((double) cnt));
             else if (max > 16 && mean > 8)
-                cnt = JS_CeilingLog2(cnt);
+                cnt = JS_CEILING_LOG2W(cnt);
             for (uintN i = 0; i < cnt; i++)
                 putc('*', fp);
         }
         putc('\n', fp);
     }
 }
 
 #endif /* JS_BASIC_STATS */
-
-#if defined(DEBUG_notme) && defined(XP_UNIX)
-
-#define __USE_GNU 1
-#include <dlfcn.h>
-#include <string.h>
-#include "jshash.h"
-#include "jsprf.h"
-
-JSCallsite js_calltree_root = {0, NULL, NULL, 0, NULL, NULL, NULL, NULL};
-
-static JSCallsite *
-CallTree(void **bp)
-{
-    void **bpup, **bpdown, *pc;
-    JSCallsite *parent, *site, **csp;
-    Dl_info info;
-    int ok, offset;
-    const char *symbol;
-    char *method;
-
-    /* Reverse the stack frame list to avoid recursion. */
-    bpup = NULL;
-    for (;;) {
-        bpdown = (void**) bp[0];
-        bp[0] = (void*) bpup;
-        if ((void**) bpdown[0] < bpdown)
-            break;
-        bpup = bp;
-        bp = bpdown;
-    }
-
-    /* Reverse the stack again, finding and building a path in the tree. */
-    parent = &js_calltree_root;
-    do {
-        bpup = (void**) bp[0];
-        bp[0] = (void*) bpdown;
-        pc = bp[1];
-
-        csp = &parent->kids;
-        while ((site = *csp) != NULL) {
-            if (site->pc == (uint32)pc) {
-                /* Put the most recently used site at the front of siblings. */
-                *csp = site->siblings;
-                site->siblings = parent->kids;
-                parent->kids = site;
-
-                /* Site already built -- go up the stack. */
-                goto upward;
-            }
-            csp = &site->siblings;
-        }
-
-        /* Check for recursion: see if pc is on our ancestor line. */
-        for (site = parent; site; site = site->parent) {
-            if (site->pc == (uint32)pc)
-                goto upward;
-        }
-
-        /*
-         * Not in tree at all: let's find our symbolic callsite info.
-         * XXX static syms are masked by nearest lower global
-         */
-        info.dli_fname = info.dli_sname = NULL;
-        ok = dladdr(pc, &info);
-        if (ok < 0) {
-            fprintf(stderr, "dladdr failed!\n");
-            return NULL;
-        }
-
-/* XXXbe sub 0x08040000? or something, see dbaron bug with tenthumbs comment */
-        symbol = info.dli_sname;
-        offset = (char*)pc - (char*)info.dli_fbase;
-        method = symbol
-                 ? strdup(symbol)
-                 : JS_smprintf("%s+%X",
-                               info.dli_fname ? info.dli_fname : "main",
-                               offset);
-        if (!method)
-            return NULL;
-
-        /* Create a new callsite record. */
-        site = (JSCallsite *) OffTheBooks::malloc(sizeof(JSCallsite));
-        if (!site)
-            return NULL;
-
-        /* Insert the new site into the tree. */
-        site->pc = (uint32)pc;
-        site->name = method;
-        site->library = info.dli_fname;
-        site->offset = offset;
-        site->parent = parent;
-        site->siblings = parent->kids;
-        parent->kids = site;
-        site->kids = NULL;
-