Merge mozilla-central to mozilla-inbound
authorMatt Brubeck <mbrubeck@mozilla.com>
Tue, 11 Oct 2011 14:11:09 -0700
changeset 79928 39c5a324b3746f1a6a0006f1824506c672e5f53b
parent 79898 1ca405a46f2125640861a73dd44a3e7139b12d55 (current diff)
parent 79927 2b37cfbb5906f78bb681762c2f2fffc6f8c94fa0 (diff)
child 79929 073b4ef6933f72797df80332490ae2d37b09eb92
push idunknown
push userunknown
push dateunknown
milestone10.0a1
Merge mozilla-central to mozilla-inbound
configure.in
embedding/components/windowwatcher/src/nsWWJSUtils.cpp
embedding/components/windowwatcher/src/nsWWJSUtils.h
js/src/configure.in
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
js/src/xpconnect/src/xpcwrappednative.cpp
--- 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/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/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/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/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/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/ipc/glue/WindowsMessageLoop.cpp
+++ b/ipc/glue/WindowsMessageLoop.cpp
@@ -96,16 +96,18 @@ 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;
+// pulled from accessibility's win utils
+extern const PRUnichar* kPropNameTabContent;
 
 namespace {
 
 const wchar_t kOldWndProcProp[] = L"MozillaIPCOldWndProc";
 
 // This isn't defined before Windows XP.
 enum { WM_XP_THEMECHANGED = 0x031A };
 
@@ -374,16 +376,22 @@ 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;
   }
 
+  // Tab content creates a window that responds to accessible WM_GETOBJECT
+  // calls. This window can safely be ignored.
+  if (::GetPropW(hWnd, kPropNameTabContent)) {
+    return false;
+  }
+
   // 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
             /*
@@ -1368,16 +1365,17 @@ JSContext::JSContext(JSRuntime *rt)
     outstandingRequests(0),
 #endif
     autoGCRooters(NULL),
     debugHooks(&rt->globalDebugHooks),
     securityCallbacks(NULL),
     resolveFlags(0),
     rngSeed(0),
     iterValue(MagicValue(JS_NO_ITER_VALUE)),
+    reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
 #ifdef JS_TRACER
     traceJitEnabled(false),
 #endif
 #ifdef JS_METHODJIT
     methodJitEnabled(false),
     profilingEnabled(false),
 #endif
     inferenceEnabled(false),
@@ -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/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,35 @@
  * 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 "jstypes.h"
+#include "jspubtd.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 +499,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 +758,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,156 @@
 
 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;
+}
+
+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);
+}
+
+/* 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,107 @@ 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;
+
+    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;
+
+    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();
+
+/*
+ * 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);
+
+/*
+ * 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 +345,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 +368,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;
-
-      upward:
-        parent = site;
-        bpdown = bp;
-        bp = bpup;
-    } while (bp);
-
-    return site;
-}
-
-JS_FRIEND_API(JSCallsite *)
-JS_Backtrace(int skip)
-{
-    void **bp, **bpdown;
-
-    /* Stack walking code adapted from Kipp's "leaky". */
-#if defined(__i386)
-    __asm__( "movl %%ebp, %0" : "=g"(bp));
-#elif defined(__x86_64__)
-    __asm__( "movq %%rbp, %0" : "=g"(bp));
-#else
-    /*
-     * It would be nice if this worked uniformly, but at least on i386 and
-     * x86_64, it stopped working with gcc 4.1, because it points to the
-     * end of the saved registers instead of the start.
-     */
-    bp = (void**) __builtin_frame_address(0);
-#endif
-    while (--skip >= 0) {
-        bpdown = (void**) *bp++;
-        if (bpdown < bp)
-            break;
-        bp = bpdown;
-    }
-
-    return CallTree(bp);
-}
-
-JS_FRIEND_API(void)
-JS_DumpBacktrace(JSCallsite *trace)
-{
-    while (trace) {
-        fprintf(stdout, "%s [%s +0x%X]\n", trace->name, trace->library,
-                trace->offset);
-        trace = trace->parent;
-    }
-}
-
-#endif /* defined(DEBUG_notme) && defined(XP_UNIX) */
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -39,626 +39,242 @@
 
 /*
  * PR assertion checker.
  */
 
 #ifndef jsutil_h___
 #define jsutil_h___
 
-#include "jstypes.h"
-#include "mozilla/Util.h"
-#include <stdlib.h>
-#include <string.h>
+#include "jsstaticcheck.h"
+
+#include "js/Utility.h"
+
+/* Forward declarations. */
+struct JSContext;
 
 #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  /* defined __cplusplus */
-
-JS_BEGIN_EXTERN_C
-
-#define JS_UPTRDIFF(a_, b_) (uintptr_t(a_) - uintptr_t(b_))
-
-#define JS_CRASH_UNLESS(__cond)                                                 \
-    JS_BEGIN_MACRO                                                              \
-        if (!(__cond)) {                                                        \
-            *(int *)(uintptr_t)0xccadbeef = 0;                                  \
-            ((void(*)())0)(); /* More reliable, but doesn't say CCADBEEF */     \
-        }                                                                       \
-    JS_END_MACRO
-
-#define JS_FREE_PATTERN 0xDA
-
-#ifdef DEBUG
-#define JS_CRASH_DIAGNOSTICS 1
-#endif
-
-#ifdef JS_CRASH_DIAGNOSTICS
-
-#define JS_POISON(p, val, size) memset((p), (val), (size))
-
-#define JS_OPT_ASSERT(expr)                                                   \
-    ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
-
-#define JS_OPT_ASSERT_IF(cond, expr)                                          \
-    ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
-
-#else
-
-#define JS_POISON(p, val, size) ((void) 0)
-#define JS_OPT_ASSERT(expr) ((void) 0)
-#define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
-
-#endif /* JS_CRASH_DIAGNOSTICS */
-
-#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 /* defined(DEBUG) */
-
-/*
- * 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);
-
-#ifdef DEBUG
-# define JS_BASIC_STATS 1
-#endif
-
-#ifdef JS_BASIC_STATS
-
-#include <stdio.h>
-
-typedef struct JSBasicStats {
-    uint32      num;
-    uint32      max;
-    double      sum;
-    double      sqsum;
-    uint32      logscale;           /* logarithmic scale: 0 (linear), 2, 10 */
-    uint32      hist[11];
-} JSBasicStats;
-
-#define JS_INIT_STATIC_BASIC_STATS  {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
-#define JS_BASIC_STATS_INIT(bs)     memset((bs), 0, sizeof(JSBasicStats))
-
-#define JS_BASIC_STATS_ACCUM(bs,val)                                          \
-    JS_BasicStatsAccum(bs, val)
-
-#define JS_MeanAndStdDevBS(bs,sigma)                                          \
-    JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
-
-extern void
-JS_BasicStatsAccum(JSBasicStats *bs, uint32 val);
-
-extern double
-JS_MeanAndStdDev(uint32 num, double sum, double sqsum, double *sigma);
-
-extern void
-JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
-
-extern void
-JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
-
-#else
-
-#define JS_BASIC_STATS_ACCUM(bs,val) /* nothing */
-
-#endif /* JS_BASIC_STATS */
-
-
-#if defined(DEBUG_notme) && defined(XP_UNIX)
-
-typedef struct JSCallsite JSCallsite;
-
-struct JSCallsite {
-    uint32      pc;
-    char        *name;
-    const char  *library;
-    int         offset;
-    JSCallsite  *parent;
-    JSCallsite  *siblings;
-    JSCallsite  *kids;
-    void        *handy;
-};
-
-extern JS_FRIEND_API(JSCallsite *)
-JS_Backtrace(int skip);
-
-extern JS_FRIEND_API(void)
-JS_DumpBacktrace(JSCallsite *trace);
-#endif
-
-#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);
-}
+template <class T>
+class AlignedPtrAndFlag
+{
+    uintptr_t bits;
 
-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 */
-
-/* 
- * 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);
-
-JS_END_EXTERN_C
-
-
-
-#ifdef __cplusplus
-
-/* 
- * 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;
+  public:
+    AlignedPtrAndFlag(T *t, bool flag) {
+        JS_ASSERT((uintptr_t(t) & 1) == 0);
+        bits = uintptr_t(t) | uintptr_t(flag);
+    }
 
-/*
- * 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);\
-        }\
+    T *ptr() const {
+        return (T *)(bits & ~uintptr_t(1));
     }
 
+    bool flag() const {
+        return (bits & 1) != 0;
+    }
 
-/*
- * 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);
+    void setPtr(T *t) {
+        JS_ASSERT((uintptr_t(t) & 1) == 0);
+        bits = uintptr_t(t) | uintptr_t(flag());
     }
 
-    static JS_INLINE void* calloc_(size_t bytes) {
-        return ::js_calloc(bytes);
+    void setFlag() {
+        bits |= 1;
     }
 
-    static JS_INLINE void* realloc_(void* p, size_t bytes) {
-        return ::js_realloc(p, bytes);
+    void unsetFlag() {
+        bits &= ~uintptr_t(1);
+    }
+
+    void set(T *t, bool flag) {
+        JS_ASSERT((uintptr_t(t) & 1) == 0);
+        bits = uintptr_t(t) | flag;
     }
 };
 
-/*
- * 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);
+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;
     }
 
-    JS_DECLARE_DELETE_METHODS(::js_free, JS_ALWAYS_INLINE static)
-};
-
-class UnwantedForeground : public Foreground {
+    ~AutoScopedAssign() { *addr = old; }
 };
 
-} /* namespace js */
+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; }
 
-/*
- * 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
+    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) {}
 
-/**
- * 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)
+    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
 {
-private:
-    bool* mStatementDone;
-public:
-    JSGuardObjectNotifier() : mStatementDone(NULL) {}
+    typedef RefCountable *****ConvertibleToBool;
+
+    JSContext *const cx;
+    RefCountable *obj;
+
+    AutoRefCount(const AutoRefCount &);
+    void operator=(const AutoRefCount &);
 
-    ~JSGuardObjectNotifier() {
-        *mStatementDone = true;
+  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);
     }
 
-    void setStatementDone(bool *aStatementDone) {
-        mStatementDone = aStatementDone;
-    }
-};
+    AutoRefCount(JSContext *cx, AlreadyIncRefed<RefCountable> aobj)
+      : cx(cx), obj(aobj.get())
+    {}
 
-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);
+    ~AutoRefCount() {
+        if (obj)
+            obj->decref(cx);
     }
 
-    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);
+    void reset(NeedsIncRef<RefCountable> aobj) {
+        if (obj)
+            obj->decref(cx);
+        obj = aobj.get();
+        if (obj)
+            obj->incref(cx);
     }
-};
 
-#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
+    void reset(AlreadyIncRefed<RefCountable> aobj) {
+        if (obj)
+            obj->decref(cx);
+        obj = aobj.get();
+    }
 
-#else /* defined(DEBUG) */
+    bool null() const { return obj == NULL; }
+    operator ConvertibleToBool() const { return (ConvertibleToBool)obj; }
 
-#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 {
+    RefCountable *operator->() const { JS_ASSERT(!null()); return obj; }
+    RefCountable &operator*() const { JS_ASSERT(!null()); return *obj; }
+    RefCountable *get() const { return obj; }
+};
 
 template <class T>
 JS_ALWAYS_INLINE static void
 PodZero(T *t)
 {
     memset(t, 0, sizeof(T));
 }
 
@@ -713,154 +329,128 @@ PodEqual(T *one, T *two, size_t len)
                 return false;
         }
         return true;
     }
 
     return !memcmp(one, two, len * sizeof(T));
 }
 
+JS_ALWAYS_INLINE static size_t
+UnsignedPtrDiff(const void *bigger, const void *smaller)
+{
+    return size_t(bigger) - size_t(smaller);
+}
 
 /*
  * Ordinarily, a function taking a JSContext* 'cx' paremter reports errors on
  * the context. In some cases, functions optionally report and indicate this by
  * taking a nullable 'maybecx' parameter. In some cases, though, a function
  * always needs a 'cx', but optionally reports. This option is presented by the
  * MaybeReportError.
  */
 enum MaybeReportError { REPORT_ERROR = true, DONT_REPORT_ERROR = false };
 
+}  /* namespace js */
+#endif  /* __cplusplus */
+
 /*
- * "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
+ * JS_ROTATE_LEFT32
  *
- * 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.
+ * 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.
  *
- * 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.
+ * MSVC in VS2005 will do an inline rotate instruction on the above construct.
  */
-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); }
+#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
+
+/* Static control-flow checks. */
+#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
+
+/* Crash diagnostics */
+#ifdef DEBUG
+# define JS_CRASH_DIAGNOSTICS 1
+#endif
+#ifdef JS_CRASH_DIAGNOSTICS
+# define JS_POISON(p, val, size) memset((p), (val), (size))
+# define JS_OPT_ASSERT(expr)                                                  \
+    ((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
+# define JS_OPT_ASSERT_IF(cond, expr)                                         \
+    ((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
 #else
-    operator T& ()   const { return *pointer; }
+# define JS_POISON(p, val, size) ((void) 0)
+# define JS_OPT_ASSERT(expr) ((void) 0)
+# define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
 #endif
-  private:
-    T *pointer;
-};
 
-template<typename T>
-MoveRef<T> Move(T &t) { return MoveRef<T>(t); }
+/* Basic stats */
+#ifdef DEBUG
+# define JS_BASIC_STATS 1
+#endif
+#ifdef JS_BASIC_STATS
+# include <stdio.h>
+typedef struct JSBasicStats {
+    uint32      num;
+    uint32      max;
+    double      sum;
+    double      sqsum;
+    uint32      logscale;           /* logarithmic scale: 0 (linear), 2, 10 */
+    uint32      hist[11];
+} JSBasicStats;
+# define JS_INIT_STATIC_BASIC_STATS  {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
+# define JS_BASIC_STATS_INIT(bs)     memset((bs), 0, sizeof(JSBasicStats))
+# define JS_BASIC_STATS_ACCUM(bs,val)                                         \
+    JS_BasicStatsAccum(bs, val)
+# define JS_MeanAndStdDevBS(bs,sigma)                                         \
+    JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
+extern void
+JS_BasicStatsAccum(JSBasicStats *bs, uint32 val);
+extern double
+JS_MeanAndStdDev(uint32 num, double sum, double sqsum, double *sigma);
+extern void
+JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
+extern void
+JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
+#else
+# define JS_BASIC_STATS_ACCUM(bs,val)
+#endif
 
-template<typename T>
-MoveRef<T> Move(const T &t) { return MoveRef<T>(const_cast<T &>(t)); }
+/* A jsbitmap_t is a long integer that can be used for bitmaps. */
+typedef size_t 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))))
 
-} /* namespace js */
-
-#endif /* defined(__cplusplus) */
+#define VOUCH_HAVE_STACK                    VOUCH_DOES_NOT_REQUIRE_STACK
 
 #endif /* jsutil_h___ */
--- a/js/src/jsval.h
+++ b/js/src/jsval.h
@@ -37,17 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jsvalimpl_h__
 #define jsvalimpl_h__
 /*
  * Implementation details for js::Value in jsapi.h.
  */
-#include "jsutil.h"
+#include "js/Utility.h"
 
 JS_BEGIN_EXTERN_C
 
 /******************************************************************************/
 
 /* To avoid a circular dependency, pull in the necessary pieces of jsnum.h. */
 
 #define JSDOUBLE_SIGNBIT (((uint64) 1) << 63)
--- a/js/src/jswatchpoint.h
+++ b/js/src/jswatchpoint.h
@@ -35,20 +35,22 @@
  * 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 jswatchpoint_h___
 #define jswatchpoint_h___
 
-#include "jshashtable.h"
+#include "jsalloc.h"
 #include "jsprvtd.h"
 #include "jsapi.h"
 
+#include "js/HashTable.h"
+
 namespace js {
 
 struct WatchKey {
     WatchKey() {}
     WatchKey(JSObject *obj, jsid id) : object(obj), id(id) {}
     JSObject *object;
     jsid id;
 };
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -38,17 +38,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <string.h>
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jsgc.h"
-#include "jshashtable.h"
 #include "jsobj.h"
 #include "jsgc.h"
 #include "jsgcmark.h"
 #include "jsweakmap.h"
 
 #include "vm/GlobalObject.h"
 
 #include "jsgcinlines.h"
--- a/js/src/jsweakmap.h
+++ b/js/src/jsweakmap.h
@@ -42,16 +42,18 @@
 #ifndef jsweakmap_h___
 #define jsweakmap_h___
 
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jsobj.h"
 #include "jsgcmark.h"
 
+#include "js/HashTable.h"
+
 namespace js {
 
 // A subclass template of js::HashMap whose keys and values may be garbage-collected. When
 // a key is collected, the table entry disappears, dropping its reference to the value.
 //
 // More precisely:
 //
 //     A WeakMap entry is collected if and only if either the WeakMap or the entry's key
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -266,16 +266,23 @@ bool
 Wrapper::construct(JSContext *cx, JSObject *wrapper, uintN argc, Value *argv, Value *vp)
 {
     vp->setUndefined(); // default result if we refuse to perform this action
     const jsid id = JSID_VOID;
     GET(ProxyHandler::construct(cx, wrapper, argc, argv, vp));
 }
 
 bool
+Wrapper::nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args)
+{
+    const jsid id = JSID_VOID;
+    CHECKED(CallJSNative(cx, native, args), CALL);
+}
+
+bool
 Wrapper::hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp)
 {
     *bp = false; // default result if we refuse to perform this action
     const jsid id = JSID_VOID;
     JSBool b = JS_FALSE;
     GET(JS_HasInstance(cx, wrappedObject(wrapper), *vp, &b) && Cond(b, bp));
 }
 
@@ -769,23 +776,16 @@ CrossCompartmentWrapper::nativeCall(JSCo
 
     dstArgs.pop();
     call.leave();
     srcArgs.rval() = dstArgs.rval();
     return call.origin->wrap(cx, &srcArgs.rval());
 }
 
 bool
-Wrapper::nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args)
-{
-    const jsid id = JSID_VOID;
-    CHECKED(CallJSNative(cx, native, args), CALL);
-}
-
-bool
 CrossCompartmentWrapper::hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp)
 {
     AutoCompartment call(cx, wrappedObject(wrapper));
     if (!call.enter())
         return false;
 
     Value v = *vp;
     if (!call.destination->wrap(cx, &v))
@@ -843,8 +843,39 @@ CrossCompartmentWrapper::defaultValue(JS
 
 void
 CrossCompartmentWrapper::trace(JSTracer *trc, JSObject *wrapper)
 {
     MarkCrossCompartmentObject(trc, *wrappedObject(wrapper), "wrappedObject");
 }
 
 CrossCompartmentWrapper CrossCompartmentWrapper::singleton(0u);
+
+/* Security wrappers. */
+
+template <class Base>
+SecurityWrapper<Base>::SecurityWrapper(uintN flags)
+  : Base(flags)
+{}
+
+template <class Base>
+bool
+SecurityWrapper<Base>::nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native,
+                                  CallArgs args)
+{
+    /* Let ProxyHandler report the error. */
+    bool ret = ProxyHandler::nativeCall(cx, wrapper, clasp, native, args);
+    JS_ASSERT(!ret && cx->isExceptionPending());
+    return ret;
+}
+
+template <class Base>
+bool
+SecurityWrapper<Base>::objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx)
+{
+    /* Let ProxyHandler say 'no'. */
+    bool ret = ProxyHandler::objectClassIs(obj, classValue, cx);
+    JS_ASSERT(!ret && !cx->isExceptionPending());
+    return ret;
+}
+
+template class SecurityWrapper<Wrapper>;
+template class SecurityWrapper<CrossCompartmentWrapper>;
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -153,16 +153,38 @@ class JS_FRIEND_API(CrossCompartmentWrap
     virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp);
 
     virtual void trace(JSTracer *trc, JSObject *wrapper);
 
     static CrossCompartmentWrapper singleton;
 };
 
 /*
+ * Base class for security wrappers. A security wrapper is potentially hiding
+ * all or part of some wrapped object thus SecurityWrapper defaults to denying
+ * access to the wrappee. This is the opposite of Wrapper which tries to be
+ * completely transparent.
+ *
+ * NB: Currently, only a few ProxyHandler operations are overridden to deny
+ * access, relying on derived SecurityWrapper to block access when necessary.
+ */
+template <class Base>
+class JS_FRIEND_API(SecurityWrapper) : public Base
+{
+  public:
+    SecurityWrapper(uintN flags);
+
+    virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args);
+    virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx);
+};
+
+typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
+typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
+
+/*
  * A hacky class that lets a friend force a fake frame. We must already be
  * in the compartment of |target| when we enter the forced frame.
  */
 class JS_FRIEND_API(ForceFrame)
 {
   public:
     JSContext * const context;
     JSObject * const target;
--- a/js/src/jsxml.cpp
+++ b/js/src/jsxml.cpp
@@ -41,17 +41,16 @@
 
 #if JS_HAS_XML_SUPPORT
 
 #include <math.h>
 #include <stdlib.h>
 #include <string.h>
 #include "jstypes.h"
 #include "jsstdint.h"
-#include "jsbit.h"
 #include "jsprf.h"
 #include "jsutil.h"
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsatom.h"
 #include "jsbool.h"
 #include "jscntxt.h"
 #include "jsfun.h"
@@ -63,17 +62,16 @@
 #include "jsopcode.h"
 #include "jsparse.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstr.h"
 #include "jsxml.h"
 #include "jsstaticcheck.h"
-#include "jsvector.h"
 
 #include "vm/GlobalObject.h"
 
 #include "jsatominlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 #include "jsstrinlines.h"
 
--- a/js/src/methodjit/BaseAssembler.h
+++ b/js/src/methodjit/BaseAssembler.h
@@ -37,17 +37,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #if !defined jsjaeger_baseassembler_h__ && defined JS_METHODJIT
 #define jsjaeger_baseassembler_h__
 
 #include "jscntxt.h"
-#include "jstl.h"
 #include "assembler/assembler/MacroAssemblerCodeRef.h"
 #include "assembler/assembler/MacroAssembler.h"
 #include "assembler/assembler/LinkBuffer.h"
 #include "assembler/moco/MocoStubs.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/MachineRegs.h"
 #include "CodeGenIncludes.h"
 #include "jsobjinlines.h"
--- a/js/src/methodjit/BaseCompiler.h
+++ b/js/src/methodjit/BaseCompiler.h
@@ -36,17 +36,16 @@
  * 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 ***** */
 #if !defined jsjaeger_compilerbase_h__ && defined JS_METHODJIT
 #define jsjaeger_compilerbase_h__
 
 #include "jscntxt.h"
-#include "jstl.h"
 #include "assembler/assembler/MacroAssembler.h"
 #include "assembler/assembler/LinkBuffer.h"
 #include "assembler/assembler/RepatchBuffer.h"
 #include "assembler/jit/ExecutableAllocator.h"
 #include <limits.h>
 
 #if defined JS_CPU_ARM
 # define POST_INST_OFFSET(__expr) ((__expr) - sizeof(ARMWord))
@@ -144,29 +143,33 @@ class LinkerHelper : public JSC::LinkBuf
         return verifyRange(JSC::JITCode(jit->code.m_code.executableAddress(), jit->code.m_size));
     }
 
     JSC::ExecutablePool *init(JSContext *cx) {
         // The pool is incref'd after this call, so it's necessary to release()
         // on any failure.
         JSScript *script = cx->fp()->script();
         JSC::ExecutableAllocator *allocator = script->compartment()->jaegerCompartment()->execAlloc();
+        allocator->setDestroyCallback(Probes::discardExecutableRegion);
         JSC::ExecutablePool *pool;
         m_code = executableAllocAndCopy(masm, allocator, &pool);
         if (!m_code) {
             js_ReportOutOfMemory(cx);
             return NULL;
         }
         m_size = masm.size();   // must come after call to executableAllocAndCopy()!
         return pool;
     }
 
-    JSC::CodeLocationLabel finalize() {
+    JSC::CodeLocationLabel finalize(VMFrame &f) {
         masm.finalize(*this);
-        return finalizeCodeAddendum();
+        JSC::CodeLocationLabel label = finalizeCodeAddendum();
+        Probes::registerICCode(f.cx, f.jit(), f.script(), f.pc(),
+                               label.executableAddress(), masm.size());
+        return label;
     }
 
     void maybeLink(MaybeJump jump, JSC::CodeLocationLabel label) {
         if (!jump.isSet())
             return;
         link(jump.get(), label);
     }
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -415,26 +415,30 @@ mjit::Compiler::pushActiveFrame(JSScript
     ActiveFrame *newa = cx->new_<ActiveFrame>(cx);
     if (!newa)
         return Compile_Error;
 
     newa->parent = a;
     if (a)
         newa->parentPC = PC;
     newa->script = script;
+    newa->mainCodeStart = masm.size();
+    newa->stubCodeStart = stubcc.size();
 
     if (outer) {
         newa->inlineIndex = uint32(inlineFrames.length());
         inlineFrames.append(newa);
     } else {
         newa->inlineIndex = CrossScriptSSA::OUTER_FRAME;
         outer = newa;
     }
     JS_ASSERT(ssa.getFrame(newa->inlineIndex).script == script);
 
+    newa->inlinePCOffset = ssa.frameLength(newa->inlineIndex);
+
     ScriptAnalysis *newAnalysis = script->analysis();
 
 #ifdef JS_METHODJIT_SPEW
     if (cx->typeInferenceEnabled() && IsJaegerSpewChannelActive(JSpew_Regalloc)) {
         unsigned nargs = script->hasFunction ? script->function()->nargs : 0;
         for (unsigned i = 0; i < nargs; i++) {
             uint32 slot = ArgSlot(i);
             if (!newAnalysis->slotEscapes(slot)) {
@@ -855,17 +859,17 @@ mjit::Compiler::generatePrologue()
         INLINE_STUBCALL(stubs::ScriptDebugPrologue, REJOIN_RESUME);
     } else if (Probes::callTrackingActive(cx)) {
         prepareStubCall(Uses(0));
         INLINE_STUBCALL(stubs::ScriptProbeOnlyPrologue, REJOIN_RESUME);
     }
 
     recompileCheckHelper();
 
-    if (outerScript->pcCounters) {
+    if (outerScript->pcCounters || Probes::wantNativeAddressInfo(cx)) {
         size_t length = ssa.frameLength(ssa.numFrames() - 1);
         pcLengths = (PCLengthEntry *) cx->calloc_(sizeof(pcLengths[0]) * length);
         if (!pcLengths)
             return Compile_Error;
     }
 
     return Compile_Okay;
 }
@@ -1421,45 +1425,99 @@ mjit::Compiler::finishThisUp(JITScript *
 
     /* Patch all outgoing calls. */
     masm.finalize(fullCode, inlineDoubles);
     stubcc.masm.finalize(stubCode, oolDoubles);
 
     JSC::ExecutableAllocator::makeExecutable(result, masm.size() + stubcc.size());
     JSC::ExecutableAllocator::cacheFlush(result, masm.size() + stubcc.size());
 
+    Probes::registerMJITCode(cx, jit, script, script->hasFunction ? script->function() : NULL,
+                             (mjit::Compiler_ActiveFrame**) inlineFrames.begin(),
+                             result, masm.size(),
+                             result + masm.size(), stubcc.size());
+
     *jitp = jit;
 
     return Compile_Okay;
 }
 
 class SrcNoteLineScanner {
+    /* offset of the current JSOp in the bytecode */
     ptrdiff_t offset;
+
+    /* next src note to process */
     jssrcnote *sn;
 
+    /* line number of the current JSOp */
+    uint32 lineno;
+
+    /*
+     * Is the current op the first one after a line change directive? Note that
+     * multiple ops may be "first" if a line directive is used to return to a
+     * previous line (eg, with a for loop increment expression.)
+     */
+    bool lineHeader;
+
 public:
-    SrcNoteLineScanner(jssrcnote *sn) : offset(SN_DELTA(sn)), sn(sn) {}
-
-    bool firstOpInLine(ptrdiff_t relpc) {
-        while ((offset < relpc) && !SN_IS_TERMINATOR(sn)) {
-            sn = SN_NEXT(sn);
-            offset += SN_DELTA(sn);
-        }
-
-        while ((offset == relpc) && !SN_IS_TERMINATOR(sn)) {
+    SrcNoteLineScanner(jssrcnote *sn, uint32 lineno)
+        : offset(0), sn(sn), lineno(lineno)
+    {
+    }
+
+    /*
+     * This is called repeatedly with always-advancing relpc values. The src
+     * notes are tuples of <PC offset from prev src note, type, args>. Scan
+     * through, updating the lineno, until the next src note is for a later
+     * bytecode.
+     *
+     * When looking at the desired PC offset ('relpc'), the op is first in that
+     * line iff there is a SRC_SETLINE or SRC_NEWLINE src note for that exact
+     * bytecode.
+     *
+     * Note that a single bytecode may have multiple line-modifying notes (even
+     * though only one should ever be needed.)
+     */
+    void advanceTo(ptrdiff_t relpc) {
+        // Must always advance! If the same or an earlier PC is erroneously
+        // passed in, we will already be past the relevant src notes
+        JS_ASSERT_IF(offset > 0, relpc > offset);
+
+        // Next src note should be for after the current offset
+        JS_ASSERT_IF(offset > 0, SN_IS_TERMINATOR(sn) || SN_DELTA(sn) > 0);
+
+        // The first PC requested is always considered to be a line header
+        lineHeader = (offset == 0);
+
+        if (SN_IS_TERMINATOR(sn))
+            return;
+
+        ptrdiff_t nextOffset;
+        while ((nextOffset = offset + SN_DELTA(sn)) <= relpc && !SN_IS_TERMINATOR(sn)) {
+            offset = nextOffset;
             JSSrcNoteType type = (JSSrcNoteType) SN_TYPE(sn);
-            if (type == SRC_SETLINE || type == SRC_NEWLINE)
-                return true;
+            if (type == SRC_SETLINE || type == SRC_NEWLINE) {
+                if (type == SRC_SETLINE)
+                    lineno = js_GetSrcNoteOffset(sn, 0);
+                else
+                    lineno++;
+
+                if (offset == relpc)
+                    lineHeader = true;
+            }
 
             sn = SN_NEXT(sn);
-            offset += SN_DELTA(sn);
         }
-
-        return false;
-    }
+    }
+
+    bool isLineHeader() const {
+        return lineHeader;
+    }
+
+    uint32 getLine() const { return lineno; }
 };
 
 #ifdef DEBUG
 #define SPEW_OPCODE()                                                         \
     JS_BEGIN_MACRO                                                            \
         if (IsJaegerSpewChannelActive(JSpew_JSOps)) {                         \
             JaegerSpew(JSpew_JSOps, "    %2d ", frame.stackDepth());          \
             LifoAllocScope las(&cx->tempLifoAlloc());                         \
@@ -1487,48 +1545,53 @@ FixDouble(Value &val)
     if (val.isInt32())
         val.setDouble((double)val.toInt32());
 }
 
 CompileStatus
 mjit::Compiler::generateMethod()
 {
     mjit::AutoScriptRetrapper trapper(cx, script);
-    SrcNoteLineScanner scanner(script->notes());
+    SrcNoteLineScanner scanner(script->notes(), script->lineno);
 
     /* For join points, whether there was fallthrough from the previous opcode. */
     bool fallthrough = true;
 
     /* Last bytecode processed. */
     jsbytecode *lastPC = NULL;
 
     for (;;) {
         JSOp op = JSOp(*PC);
         int trap = stubs::JSTRAP_NONE;
         if (op == JSOP_TRAP) {
             if (!trapper.untrap(PC))
                 return Compile_Error;
             op = JSOp(*PC);
             trap |= stubs::JSTRAP_TRAP;
         }
-        if (script->stepModeEnabled() && scanner.firstOpInLine(PC - script->code))
-            trap |= stubs::JSTRAP_SINGLESTEP;
 
         Bytecode *opinfo = analysis->maybeCode(PC);
 
         if (!opinfo) {
             if (op == JSOP_STOP)
                 break;
             if (js_CodeSpec[op].length != -1)
                 PC += js_CodeSpec[op].length;
             else
                 PC += js_GetVariableBytecodeLength(PC);
             continue;
         }
 
+        scanner.advanceTo(PC - script->code);
+        if (script->stepModeEnabled() &&
+            (scanner.isLineHeader() || opinfo->jumpTarget))
+        {
+            trap |= stubs::JSTRAP_SINGLESTEP;
+        }
+
         frame.setPC(PC);
         frame.setInTryBlock(opinfo->inTryBlock);
 
         if (fallthrough) {
             /*
              * If there is fallthrough from the previous opcode and we changed
              * any entries into doubles for a branch at that previous op,
              * revert those entries into integers. Similarly, if we forgot that
@@ -1563,17 +1626,17 @@ mjit::Compiler::generateMethod()
                     frame.syncAndForgetEverything();
                     Jump j = masm.jump();
                     if (!startLoop(PC, j, PC))
                         return Compile_Error;
                 } else {
                     Label start = masm.label();
                     if (!frame.syncForBranch(PC, Uses(0)))
                         return Compile_Error;
-                    if (script->pcCounters) {
+                    if (pcLengths) {
                         /* Track this sync code for the previous op. */
                         size_t length = masm.size() - masm.distanceOf(start);
                         uint32 offset = ssa.frameLength(a->inlineIndex) + lastPC - script->code;
                         pcLengths[offset].codeLength += length;
                     }
                     JS_ASSERT(frame.consistentRegisters(PC));
                 }
             }
@@ -2795,25 +2858,27 @@ mjit::Compiler::generateMethod()
                 FrameEntry *fe = frame.getStack(opinfo->stackDepth - nuses + i);
                 if (fe) {
                     /* fe may be NULL for conditionally pushed entries, e.g. JSOP_AND */
                     frame.extra(fe).types = analysis->pushedTypes(lastPC - script->code, i);
                 }
             }
         }
 
-        if (script->pcCounters) {
+        if (script->pcCounters || pcLengths) {
             size_t length = masm.size() - masm.distanceOf(codeStart);
             if (countersUpdated || length != 0) {
-                if (!countersUpdated)
+                if (!countersUpdated && script->pcCounters)
                     updatePCCounters(lastPC, &codeStart, &countersUpdated);
 
-                /* Fill in the amount of inline code generated for the op. */
-                uint32 offset = ssa.frameLength(a->inlineIndex) + lastPC - script->code;
-                pcLengths[offset].codeLength += length;
+                if (pcLengths) {
+                    /* Fill in the amount of inline code generated for the op. */
+                    uint32 offset = ssa.frameLength(a->inlineIndex) + lastPC - script->code;
+                    pcLengths[offset].codeLength += length;
+                }
             }
         }
 
         frame.assertValidRegisterState();
     }
 
   done:
     return Compile_Okay;
@@ -6716,17 +6781,17 @@ mjit::Compiler::jumpAndTrace(Jump j, jsb
                  */
                 Label start = stubcc.masm.label();
                 stubcc.linkExitDirect(j, start);
                 frame.prepareForJump(target, stubcc.masm, false);
                 if (!stubcc.jumpInScript(stubcc.masm.jump(), target))
                     return false;
                 if (trampoline)
                     *trampoline = true;
-                if (script->pcCounters) {
+                if (pcLengths) {
                     /*
                      * This is OOL code but will usually be executed, so track
                      * it in the CODE_LENGTH for the opcode.
                      */
                     uint32 offset = ssa.frameLength(a->inlineIndex) + PC - script->code;
                     size_t length = stubcc.masm.size() - stubcc.masm.distanceOf(start);
                     pcLengths[offset].codeLength += length;
                 }
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -37,17 +37,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #if !defined jsjaeger_compiler_h__ && defined JS_METHODJIT
 #define jsjaeger_compiler_h__
 
 #include "jsanalyze.h"
 #include "jscntxt.h"
-#include "jstl.h"
 #include "MethodJIT.h"
 #include "CodeGenIncludes.h"
 #include "BaseCompiler.h"
 #include "StubCompiler.h"
 #include "MonoIC.h"
 #include "PolyIC.h"
 
 namespace js {
@@ -386,31 +385,37 @@ class Compiler : public BaseCompiler
     Assembler masm;
     FrameState frame;
 
     /*
      * State for the current stack frame, and links to its parents going up to
      * the outermost script.
      */
 
+public:
     struct ActiveFrame {
         ActiveFrame *parent;
         jsbytecode *parentPC;
         JSScript *script;
         Label *jumpMap;
 
         /*
          * Index into inlineFrames or OUTER_FRAME, matches this frame's index
          * in the cross script SSA.
          */
         uint32 inlineIndex;
 
         /* Current types for non-escaping vars in the script. */
         VarType *varTypes;
 
+        /* JIT code generation tracking state */
+        size_t mainCodeStart;
+        size_t stubCodeStart;
+        size_t inlinePCOffset;
+
         /* State for managing return from inlined frames. */
         bool needReturnValue;          /* Return value will be used. */
         bool syncReturnValue;          /* Return value should be fully synced. */
         bool returnValueDouble;        /* Return value should be a double. */
         bool returnSet;                /* Whether returnRegister is valid. */
         AnyRegisterID returnRegister;  /* Register holding return value. */
         const FrameEntry *returnEntry; /* Entry copied by return value. */
         Vector<Jump, 4, CompilerAllocPolicy> *returnJumps;
@@ -419,16 +424,18 @@ class Compiler : public BaseCompiler
          * Snapshot of the heap state to use after the call, in case
          * there are multiple return paths the inlined frame could take.
          */
         RegisterAllocation *exitState;
 
         ActiveFrame(JSContext *cx);
         ~ActiveFrame();
     };
+
+private:
     ActiveFrame *a;
     ActiveFrame *outer;
 
     JSScript *script;
     analyze::ScriptAnalysis *analysis;
     jsbytecode *PC;
 
     LoopState *loop;
--- a/js/src/methodjit/MachineRegs.h
+++ b/js/src/methodjit/MachineRegs.h
@@ -35,17 +35,16 @@
  * 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 ***** */
 
 #if !defined jsjaeger_regstate_h__ && defined JS_METHODJIT
 #define jsjaeger_regstate_h__
 
-#include "jsbit.h"
 #include "assembler/assembler/MacroAssembler.h"
 
 namespace js {
 
 namespace mjit {
 
 /* Common handling for both general purpose and floating point registers. */
 
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -53,16 +53,27 @@
 #include "jsgcmark.h"
 
 #include "jsgcinlines.h"
 #include "jsinterpinlines.h"
 
 using namespace js;
 using namespace js::mjit;
 
+#ifdef __GCC_HAVE_DWARF2_CFI_ASM
+# define CFI(str) str
+#else
+# define CFI(str)
+#endif
+
+// Put manually-inserted call frame unwinding information into .debug_frame
+// rather than .eh_frame, because we compile with -fno-exceptions which might
+// discard the .eh_frame section. (See
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43232).
+CFI(asm(".cfi_sections .debug_frame");)
 
 js::mjit::CompilerAllocPolicy::CompilerAllocPolicy(JSContext *cx, Compiler &compiler)
 : TempAllocPolicy(cx),
   oomFlag(&compiler.oomInVector)
 {
 }
 void
 StackFrame::methodjitStaticAsserts()
@@ -203,24 +214,34 @@ JS_STATIC_ASSERT(VMFrame::offsetOfFp == 
 JS_STATIC_ASSERT(JSVAL_TAG_MASK == 0xFFFF800000000000LL);
 JS_STATIC_ASSERT(JSVAL_PAYLOAD_MASK == 0x00007FFFFFFFFFFFLL);
 
 asm (
 ".text\n"
 ".globl " SYMBOL_STRING(JaegerTrampoline) "\n"
 SYMBOL_STRING(JaegerTrampoline) ":"       "\n"
     /* Prologue. */
+    CFI(".cfi_startproc"                 "\n")
+    CFI(".cfi_def_cfa rsp, 8"            "\n")
     "pushq %rbp"                         "\n"
+    CFI(".cfi_def_cfa_offset 16"         "\n")
+    CFI(".cfi_offset rbp, -16"           "\n")
     "movq %rsp, %rbp"                    "\n"
+    CFI(".cfi_def_cfa_register rbp"      "\n")
     /* Save non-volatile registers. */
     "pushq %r12"                         "\n"
+    CFI(".cfi_offset r12, -24"           "\n")
     "pushq %r13"                         "\n"
+    CFI(".cfi_offset r13, -32"           "\n")
     "pushq %r14"                         "\n"
+    CFI(".cfi_offset r14, -40"           "\n")
     "pushq %r15"                         "\n"
+    CFI(".cfi_offset r15, -48"           "\n")
     "pushq %rbx"                         "\n"
+    CFI(".cfi_offset rbx, -56"           "\n")
 
     /* Load mask registers. */
     "movq $0xFFFF800000000000, %r13"     "\n"
     "movq $0x00007FFFFFFFFFFF, %r14"     "\n"
 
     /* Build the JIT frame.
      * rdi = cx
      * rsi = fp
@@ -245,59 +266,80 @@ SYMBOL_STRING(JaegerTrampoline) ":"     
     "pushq %rdx"                         "\n"
     "movq  %rsp, %rdi"                   "\n"
     "call " SYMBOL_STRING_VMFRAME(SetVMFrameRegs) "\n"
     "movq  %rsp, %rdi"                   "\n"
     "call " SYMBOL_STRING_VMFRAME(PushActiveVMFrame) "\n"
 
     /* Jump into the JIT'd code. */
     "jmp *0(%rsp)"                      "\n"
+    CFI(".cfi_endproc"                  "\n")
 );
 
 asm (
 ".text\n"
 ".globl " SYMBOL_STRING(JaegerTrampolineReturn) "\n"
 SYMBOL_STRING(JaegerTrampolineReturn) ":"       "\n"
+    CFI(".cfi_startproc"                 "\n")
+    CFI(".cfi_def_cfa rbp, 16"           "\n")
+    CFI(".cfi_offset rbp, -16"           "\n")
+    CFI(".cfi_offset r12, -24"           "\n")
+    CFI(".cfi_offset r13, -32"           "\n")
+    CFI(".cfi_offset r14, -40"           "\n")
+    CFI(".cfi_offset r15, -48"           "\n")
+    CFI(".cfi_offset rbx, -56"           "\n")
     "or   %rdi, %rsi"                    "\n"
     "movq %rsi, 0x30(%rbx)"              "\n"
     "movq %rsp, %rdi"                    "\n"
     "call " SYMBOL_STRING_VMFRAME(PopActiveVMFrame) "\n"
 
     "addq $0x68, %rsp"                   "\n"
     "popq %rbx"                          "\n"
     "popq %r15"                          "\n"
     "popq %r14"                          "\n"
     "popq %r13"                          "\n"
     "popq %r12"                          "\n"
     "popq %rbp"                          "\n"
+    CFI(".cfi_def_cfa rsp, 8"            "\n")
     "movq $1, %rax"                      "\n"
     "ret"                                "\n"
+    CFI(".cfi_endproc"                   "\n")
 );
 
 asm (
 ".text\n"
 ".globl " SYMBOL_STRING(JaegerThrowpoline)  "\n"
 SYMBOL_STRING(JaegerThrowpoline) ":"        "\n"
+    CFI(".cfi_startproc"                    "\n")
+    CFI(".cfi_def_cfa rbp, 16"              "\n")
+    CFI(".cfi_offset rbp, -16"              "\n")
+    CFI(".cfi_offset r12, -24"              "\n")
+    CFI(".cfi_offset r13, -32"              "\n")
+    CFI(".cfi_offset r14, -40"              "\n")
+    CFI(".cfi_offset r15, -48"              "\n")
+    CFI(".cfi_offset rbx, -56"              "\n")
     "movq %rsp, %rdi"                       "\n"
     "call " SYMBOL_STRING_RELOC(js_InternalThrow) "\n"
     "testq %rax, %rax"                      "\n"
     "je   throwpoline_exit"                 "\n"
     "jmp  *%rax"                            "\n"
   "throwpoline_exit:"                       "\n"
     "movq %rsp, %rdi"                       "\n"
     "call " SYMBOL_STRING_VMFRAME(PopActiveVMFrame) "\n"
     "addq $0x68, %rsp"                      "\n"
     "popq %rbx"                             "\n"
     "popq %r15"                             "\n"
     "popq %r14"                             "\n"
     "popq %r13"                             "\n"
     "popq %r12"                             "\n"
     "popq %rbp"                             "\n"
+    CFI(".cfi_def_cfa rsp, 8"               "\n")
     "xorq %rax,%rax"                        "\n"
     "ret"                                   "\n"
+    CFI(".cfi_endproc"                      "\n")
 );
 
 asm (
 ".text\n"
 ".globl " SYMBOL_STRING(JaegerInterpoline)  "\n"
 SYMBOL_STRING(JaegerInterpoline) ":"        "\n"
     "movq %rsp, %rcx"                       "\n"
     "movq %rax, %rdx"                       "\n"
@@ -347,22 +389,30 @@ JS_STATIC_ASSERT(offsetof(VMFrame, saved
 JS_STATIC_ASSERT(offsetof(VMFrame, scratch) == 0xC);
 JS_STATIC_ASSERT(VMFrame::offsetOfFp == 0x1C);
 
 asm (
 ".text\n"
 ".globl " SYMBOL_STRING(JaegerTrampoline) "\n"
 SYMBOL_STRING(JaegerTrampoline) ":"       "\n"
     /* Prologue. */
+    CFI(".cfi_startproc"                 "\n")
+    CFI(".cfi_def_cfa esp, 4"            "\n")
     "pushl %ebp"                         "\n"
+    CFI(".cfi_def_cfa_offset 8"          "\n")
+    CFI(".cfi_offset ebp, -8"            "\n")
     "movl %esp, %ebp"                    "\n"
+    CFI(".cfi_def_cfa_register ebp"      "\n")
     /* Save non-volatile registers. */
     "pushl %esi"                         "\n"
+    CFI(".cfi_offset esi, -12"           "\n")
     "pushl %edi"                         "\n"
+    CFI(".cfi_offset edi, -16"           "\n")
     "pushl %ebx"                         "\n"
+    CFI(".cfi_offset ebx, -20"           "\n")
 
     /* Build the JIT frame. Push fields in order, 
      * then align the stack to form esp == VMFrame. */
     "movl  12(%ebp), %ebx"               "\n"   /* load fp */
     "pushl %ebx"                         "\n"   /* unused1 */
     "pushl %ebx"                         "\n"   /* unused0 */
     "pushl $0x0"                         "\n"   /* stubRejoin */
     "pushl %ebx"                         "\n"   /* entryncode */
@@ -375,43 +425,58 @@ SYMBOL_STRING(JaegerTrampoline) ":"     
     /* Jump into the JIT'd code. */
     "movl  %esp, %ecx"                   "\n"
     "call " SYMBOL_STRING_VMFRAME(SetVMFrameRegs) "\n"
     "movl  %esp, %ecx"                   "\n"
     "call " SYMBOL_STRING_VMFRAME(PushActiveVMFrame) "\n"
 
     "movl 28(%esp), %ebp"                "\n"   /* load fp for JIT code */
     "jmp *88(%esp)"                      "\n"
+    CFI(".cfi_endproc"                   "\n")
 );
 
 asm (
 ".text\n"
 ".globl " SYMBOL_STRING(JaegerTrampolineReturn) "\n"
 SYMBOL_STRING(JaegerTrampolineReturn) ":" "\n"
+    CFI(".cfi_startproc"                 "\n")
+    CFI(".cfi_def_cfa ebp, 8"            "\n")
+    CFI(".cfi_offset ebp, -8"            "\n")
+    CFI(".cfi_offset esi, -12"           "\n")
+    CFI(".cfi_offset edi, -16"           "\n")
+    CFI(".cfi_offset ebx, -20"           "\n")
     "movl  %esi, 0x18(%ebp)"             "\n"
     "movl  %edi, 0x1C(%ebp)"             "\n"
     "movl  %esp, %ebp"                   "\n"
     "addl  $0x48, %ebp"                  "\n" /* Restore stack at STACK_BASE_DIFFERENCE */
     "movl  %esp, %ecx"                   "\n"
     "call " SYMBOL_STRING_VMFRAME(PopActiveVMFrame) "\n"
 
     "addl $0x3C, %esp"                   "\n"
     "popl %ebx"                          "\n"
     "popl %edi"                          "\n"
     "popl %esi"                          "\n"
     "popl %ebp"                          "\n"
+    CFI(".cfi_def_cfa esp, 4"            "\n")
     "movl $1, %eax"                      "\n"
     "ret"                                "\n"
+    CFI(".cfi_endproc"                   "\n")
 );
 
 asm (
 ".text\n"
 ".globl " SYMBOL_STRING(JaegerThrowpoline)  "\n"
 SYMBOL_STRING(JaegerThrowpoline) ":"        "\n"
     /* Align the stack to 16 bytes. */
+    CFI(".cfi_startproc"                 "\n")
+    CFI(".cfi_def_cfa ebp, 8"            "\n")
+    CFI(".cfi_offset ebp, -8"            "\n")
+    CFI(".cfi_offset esi, -12"           "\n")
+    CFI(".cfi_offset edi, -16"           "\n")
+    CFI(".cfi_offset ebx, -20"           "\n")
     "pushl %esp"                         "\n"
     "pushl (%esp)"                       "\n"
     "pushl (%esp)"                       "\n"
     "pushl (%esp)"                       "\n"
     "call " SYMBOL_STRING_RELOC(js_InternalThrow) "\n"
     /* Bump the stack by 0x2c, as in the basic trampoline, but
      * also one more word to clean up the stack for js_InternalThrow,
      * and another to balance the alignment above. */
@@ -422,18 +487,20 @@ SYMBOL_STRING(JaegerThrowpoline) ":"    
   "throwpoline_exit:"                    "\n"
     "movl %esp, %ecx"                    "\n"
     "call " SYMBOL_STRING_VMFRAME(PopActiveVMFrame) "\n"
     "addl $0x3c, %esp"                   "\n"
     "popl %ebx"                          "\n"
     "popl %edi"                          "\n"
     "popl %esi"                          "\n"
     "popl %ebp"                          "\n"
+    CFI(".cfi_def_cfa esp, 4"            "\n")
     "xorl %eax, %eax"                    "\n"
     "ret"                                "\n"
+    CFI(".cfi_endproc"                   "\n")
 );
 
 asm (
 ".text\n"
 ".globl " SYMBOL_STRING(JaegerInterpoline)  "\n"
 SYMBOL_STRING(JaegerInterpoline) ":"        "\n"
     /* Align the stack to 16 bytes. */
     "pushl %esp"                         "\n"
@@ -1193,16 +1260,17 @@ mjit::ReleaseScriptCode(JSContext *cx, J
     // NB: The recompiler may call ReleaseScriptCode, in which case it
     // will get called again when the script is destroyed, so we
     // must protect against calling ReleaseScriptCode twice.
 
     JITScript **pjit = construct ? &script->jitCtor : &script->jitNormal;
     void **parity = construct ? &script->jitArityCheckCtor : &script->jitArityCheckNormal;
 
     if (*pjit) {
+        Probes::discardMJITCode(cx, *pjit, script, (*pjit)->code.m_code.executableAddress());
         (*pjit)->~JITScript();
         cx->free_(*pjit);
         *pjit = NULL;
         *parity = NULL;
     }
 }
 
 #ifdef JS_METHODJIT_PROFILE_STUBS
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -238,17 +238,17 @@ AttachSetGlobalNameStub(VMFrame &f, ic::
 
     if (!linker.verifyRange(jit))
         return Lookup_Uncacheable;
 
     linker.link(done, ic->fastPathStart.labelAtOffset(ic->fastRejoinOffset));
     linker.link(guard, ic->slowPathStart);
     linker.link(isFun, ic->slowPathStart);
 
-    JSC::CodeLocationLabel cs = linker.finalize();
+    JSC::CodeLocationLabel cs = linker.finalize(f);
     JaegerSpew(JSpew_PICs, "generated setgname stub at %p\n", cs.executableAddress());
 
     Repatcher repatcher(f.jit());
     repatcher.relink(ic->fastPathStart.jumpAtOffset(ic->inlineShapeJump), cs);
 
     int offset = linker.locationOf(shapeLabel) - linker.locationOf(start);
     ic->extraShapeGuard = offset;
     JS_ASSERT(ic->extraShapeGuard == offset);
@@ -496,17 +496,17 @@ class EqualityCompiler : public BaseComp
         for (size_t i = 0; i < jumpList.length(); i++)
             buffer.link(jumpList[i], ic.stubEntry);
         jumpList.clear();
 
         /* Set the targets for the the success and failure of the actual equality test. */
         buffer.link(trueJump, ic.target);
         buffer.link(falseJump, ic.fallThrough);
 
-        CodeLocationLabel cs = buffer.finalize();
+        CodeLocationLabel cs = buffer.finalize(f);
 
         /* Jump to the newly generated code instead of to the IC. */
         repatcher.relink(ic.jumpToStub, cs);
 
         return true;
     }
 
     bool update()
@@ -798,17 +798,17 @@ class CallCompiler : public BaseCompiler
             return false;
 
         if (!linker.verifyRange(from)) {
             disable(from);
             return true;
         }
 
         linker.link(notCompiled, ic.slowPathStart.labelAtOffset(ic.slowJoinOffset));
-        JSC::CodeLocationLabel cs = linker.finalize();
+        JSC::CodeLocationLabel cs = linker.finalize(f);
 
         JaegerSpew(JSpew_PICs, "generated CALL stub %p (%lu bytes)\n", cs.executableAddress(),
                    (unsigned long) masm.size());
 
         if (f.regs.inlined()) {
             JSC::LinkBuffer code((uint8 *) cs.executableAddress(), masm.size(), JSC::METHOD_CODE);
             code.patch(inlined, f.regs.inlined());
         }
@@ -884,17 +884,17 @@ class CallCompiler : public BaseCompiler
         if (!linker.verifyRange(from)) {
             disable(from);
             return true;
         }
 
         linker.link(claspGuard, ic.slowPathStart);
         linker.link(funGuard, ic.slowPathStart);
         linker.link(done, ic.funGuard.labelAtOffset(ic.hotPathOffset));
-        JSC::CodeLocationLabel cs = linker.finalize();
+        JSC::CodeLocationLabel cs = linker.finalize(f);
 
         JaegerSpew(JSpew_PICs, "generated CALL closure stub %p (%lu bytes)\n",
                    cs.executableAddress(), (unsigned long) masm.size());
 
         Repatcher repatch(from);
         repatch.relink(ic.funJump, cs);
 
         return true;
@@ -1058,17 +1058,17 @@ class CallCompiler : public BaseCompiler
             return true;
         }
 
         linker.patchJump(ic.slowPathStart.labelAtOffset(ic.slowJoinOffset));
 
         ic.fastGuardedNative = obj;
 
         linker.link(funGuard, ic.slowPathStart);
-        JSC::CodeLocationLabel start = linker.finalize();
+        JSC::CodeLocationLabel start = linker.finalize(f);
 
         JaegerSpew(JSpew_PICs, "generated native CALL stub %p (%lu bytes)\n",
                    start.executableAddress(), (unsigned long) masm.size());
 
         Repatcher repatch(jit);
         repatch.relink(ic.funJump, start);
 
         return true;
@@ -1353,17 +1353,17 @@ ic::GenerateArgumentCheckStub(VMFrame &f
         jit->resetArgsCheck();
         return;
     }
 
     for (unsigned i = 0; i < mismatches.length(); i++)
         linker.link(mismatches[i], jit->argsCheckStub);
     linker.link(done, jit->argsCheckFallthrough);
 
-    JSC::CodeLocationLabel cs = linker.finalize();
+    JSC::CodeLocationLabel cs = linker.finalize(f);
 
     JaegerSpew(JSpew_PICs, "generated ARGS CHECK stub %p (%lu bytes)\n",
                cs.executableAddress(), (unsigned long)masm.size());
 
     Repatcher repatch(jit);
     repatch.relink(jit->argsCheckJump, cs);
 }
 
--- a/js/src/methodjit/PolyIC.cpp
+++ b/js/src/methodjit/PolyIC.cpp
@@ -481,17 +481,17 @@ class SetPropCompiler : public PICStubCo
         buffer.link(shapeGuard, pic.slowPathStart);
         if (slowExit.isSet())
             buffer.link(slowExit.get(), pic.slowPathStart);
         for (Jump *pj = slowExits.begin(); pj != slowExits.end(); ++pj)
             buffer.link(*pj, pic.slowPathStart);
         buffer.link(done, pic.fastPathRejoin);
         if (skipOver.isSet())
             buffer.link(skipOver.get(), pic.fastPathRejoin);
-        CodeLocationLabel cs = buffer.finalize();
+        CodeLocationLabel cs = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generate setprop stub %p %d %d at %p\n",
                    (void*)&pic,
                    initialShape,
                    pic.stubsGenerated,
                    cs.executableAddress());
 
         // This function can patch either the inline fast path for a generated
         // stub. The stub omits the prefix of the inline fast path that loads
@@ -907,17 +907,17 @@ class GetPropCompiler : public PICStubCo
             !buffer.verifyRange(f.jit())) {
             return disable("code memory is out of range");
         }
 
         buffer.link(notArgs, pic.slowPathStart);
         buffer.link(overridden, pic.slowPathStart);
         buffer.link(done, pic.fastPathRejoin);
 
-        CodeLocationLabel start = buffer.finalize();
+        CodeLocationLabel start = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generate args length stub at %p\n",
                    start.executableAddress());
 
         patchPreviousToHere(start);
 
         disable("args length done");
 
         return Lookup_Cacheable;
@@ -947,17 +947,17 @@ class GetPropCompiler : public PICStubCo
             !buffer.verifyRange(f.jit())) {
             return disable("code memory is out of range");
         }
 
         buffer.link(notArray, pic.slowPathStart);
         buffer.link(oob, pic.slowPathStart);
         buffer.link(done, pic.fastPathRejoin);
 
-        CodeLocationLabel start = buffer.finalize();
+        CodeLocationLabel start = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generate array length stub at %p\n",
                    start.executableAddress());
 
         patchPreviousToHere(start);
 
         disable("array length done");
 
         return Lookup_Cacheable;
@@ -984,17 +984,17 @@ class GetPropCompiler : public PICStubCo
         if (!buffer.verifyRange(pic.lastCodeBlock(f.jit())) ||
             !buffer.verifyRange(f.jit())) {
             return disable("code memory is out of range");
         }
 
         buffer.link(notStringObj, pic.slowPathStart);
         buffer.link(done, pic.fastPathRejoin);
 
-        CodeLocationLabel start = buffer.finalize();
+        CodeLocationLabel start = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generate string object length stub at %p\n",
                    start.executableAddress());
 
         patchPreviousToHere(start);
 
         disable("string object length done");
 
         return Lookup_Cacheable;
@@ -1061,17 +1061,17 @@ class GetPropCompiler : public PICStubCo
             !buffer.verifyRange(f.jit())) {
             return disable("code memory is out of range");
         }
 
         buffer.link(notString, pic.getSlowTypeCheck());
         buffer.link(shapeMismatch, pic.slowPathStart);
         buffer.link(done, pic.fastPathRejoin);
 
-        CodeLocationLabel cs = buffer.finalize();
+        CodeLocationLabel cs = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generate string call stub at %p\n",
                    cs.executableAddress());
 
         /* Patch the type check to jump here. */
         if (pic.hasTypeCheck()) {
             Repatcher repatcher(f.jit());
             repatcher.relink(pic.getPropLabels().getInlineTypeJump(pic.fastPathStart), cs);
         }
@@ -1104,17 +1104,17 @@ class GetPropCompiler : public PICStubCo
         if (!buffer.verifyRange(pic.lastCodeBlock(f.jit())) ||
             !buffer.verifyRange(f.jit())) {
             return disable("code memory is out of range");
         }
 
         buffer.link(notString, pic.getSlowTypeCheck());
         buffer.link(done, pic.fastPathRejoin);
 
-        CodeLocationLabel start = buffer.finalize();
+        CodeLocationLabel start = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generate string length stub at %p\n",
                    start.executableAddress());
 
         if (pic.hasTypeCheck()) {
             Repatcher repatcher(f.jit());
             repatcher.relink(pic.getPropLabels().getInlineTypeJump(pic.fastPathStart), start);
         }
 
@@ -1330,17 +1330,17 @@ class GetPropCompiler : public PICStubCo
     }
 
     void linkerEpilogue(LinkerHelper &buffer, Label start, const Vector<Jump, 8> &shapeMismatches)
     {
         // The guard exit jumps to the original slow case.
         for (Jump *pj = shapeMismatches.begin(); pj != shapeMismatches.end(); ++pj)
             buffer.link(*pj, pic.slowPathStart);
 
-        CodeLocationLabel cs = buffer.finalize();
+        CodeLocationLabel cs = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generated %s stub at %p\n", type, cs.executableAddress());
 
         patchPreviousToHere(cs);
 
         pic.stubsGenerated++;
         pic.updateLastPath(buffer, start);
 
         if (pic.stubsGenerated == MAX_PIC_STUBS)
@@ -1551,17 +1551,17 @@ class ScopeNameCompiler : public PICStub
 
         if (!buffer.verifyRange(pic.lastCodeBlock(f.jit())) ||
             !buffer.verifyRange(f.jit())) {
             return disable("code memory is out of range");
         }
 
         buffer.link(failJump, pic.slowPathStart);
         buffer.link(done, pic.fastPathRejoin);
-        CodeLocationLabel cs = buffer.finalize();
+        CodeLocationLabel cs = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generated %s global stub at %p\n", type, cs.executableAddress());
         spew("NAME stub", "global");
 
         patchPreviousToHere(cs);
 
         pic.stubsGenerated++;
         pic.updateLastPath(buffer, failLabel);
         labels.setStubJump(masm, failLabel, failJump);
@@ -1674,17 +1674,17 @@ class ScopeNameCompiler : public PICStub
 
         if (!buffer.verifyRange(pic.lastCodeBlock(f.jit())) ||
             !buffer.verifyRange(f.jit())) {
             return disable("code memory is out of range");
         }
 
         buffer.link(failJump, pic.slowPathStart);
         buffer.link(done, pic.fastPathRejoin);
-        CodeLocationLabel cs = buffer.finalize();
+        CodeLocationLabel cs = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generated %s call stub at %p\n", type, cs.executableAddress());
 
         patchPreviousToHere(cs);
 
         pic.stubsGenerated++;
         pic.updateLastPath(buffer, failLabel);
         labels.setStubJump(masm, failLabel, failJump);
 
@@ -1862,17 +1862,17 @@ class BindNameCompiler : public PICStubC
 
         if (!buffer.verifyRange(pic.lastCodeBlock(f.jit())) ||
             !buffer.verifyRange(f.jit())) {
             return disable("code memory is out of range");
         }
 
         buffer.link(failJump, pic.slowPathStart);
         buffer.link(done, pic.fastPathRejoin);
-        CodeLocationLabel cs = buffer.finalize();
+        CodeLocationLabel cs = buffer.finalize(f);
         JaegerSpew(JSpew_PICs, "generated %s stub at %p\n", type, cs.executableAddress());
 
         patchPreviousToHere(cs);
 
         pic.stubsGenerated++;
         pic.updateLastPath(buffer, failLabel);
         labels.setStubJump(masm, failLabel, failJump);
 
@@ -2420,19 +2420,20 @@ GetElementIC::purge(Repatcher &repatcher
                              FunctionPtr(JS_FUNC_TO_DATA_PTR(void *, ic::CallElement)));
         }
     }
 
     reset();
 }
 
 LookupStatus
-GetElementIC::attachGetProp(VMFrame &f, JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp)
+GetElementIC::attachGetProp(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp)
 {
     JS_ASSERT(v.isString());
+    JSContext *cx = f.cx;
 
     GetPropertyHelper<GetElementIC> getprop(cx, obj, JSID_TO_ATOM(id), *this, f);
     LookupStatus status = getprop.lookupAndTest();
     if (status != Lookup_Cacheable)
         return status;
 
     // With TI enabled, string property stubs can only be added to an opcode if
     // the value read will go through a type barrier afterwards. TI only
@@ -2517,17 +2518,17 @@ GetElementIC::attachGetProp(VMFrame &f, 
 
     // Patch all guards.
     buffer.maybeLink(atomIdGuard, slowPathStart);
     buffer.maybeLink(atomTypeGuard, slowPathStart);
     buffer.link(shapeGuard, slowPathStart);
     buffer.maybeLink(protoGuard, slowPathStart);
     buffer.link(done, fastPathRejoin);
 
-    CodeLocationLabel cs = buffer.finalize();
+    CodeLocationLabel cs = buffer.finalize(f);
 #if DEBUG
     char *chars = DeflateString(cx, v.toString()->getChars(cx), v.toString()->length());
     JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom %p (\"%s\") shape 0x%x (%s: %d)\n",
                js_CodeName[op], cs.executableAddress(), (void*)JSID_TO_ATOM(id), chars,
                holder->shape(), cx->fp()->script()->filename, CurrentLine(cx));
     cx->free_(chars);
 #endif
 
@@ -2599,18 +2600,20 @@ GetElementIC::attachGetProp(VMFrame &f, 
         *vp = ObjectValue(shape->methodObject());
     else
         *vp = holder->getSlot(shape->slot);
 
     return Lookup_Cacheable;
 }
 
 LookupStatus
-GetElementIC::attachArguments(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp)
+GetElementIC::attachArguments(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp)
 {
+    JSContext *cx = f.cx;
+
     if (!v.isInt32())
         return disable(cx, "arguments object with non-integer key");
 
     if (op == JSOP_CALLELEM)
         return disable(cx, "arguments object with call");
 
     JS_ASSERT(hasInlineTypeGuard() || idRemat.knownType() == JSVAL_TYPE_INT32);
 
@@ -2750,18 +2753,20 @@ GetElementIC::attachArguments(JSContext 
     if (!obj->getGeneric(cx, id, vp))
         return Lookup_Error;
 
     return Lookup_Cacheable;
 }
 
 #if defined JS_METHODJIT_TYPED_ARRAY
 LookupStatus
-GetElementIC::attachTypedArray(JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp)
+GetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp)
 {
+    JSContext *cx = f.cx;
+
     if (!v.isInt32())
         return disable(cx, "typed array with string key");
 
     if (op == JSOP_CALLELEM)
         return disable(cx, "typed array with call");
 
     // The fast-path guarantees that after the dense clasp guard, the type is
     // known to be int32, either via type inference or the inline type check.
@@ -2833,43 +2838,43 @@ GetElementIC::attachTypedArray(JSContext
     if (!obj->getGeneric(cx, id, vp))
         return Lookup_Error;
 
     return Lookup_Cacheable;
 }
 #endif /* JS_METHODJIT_TYPED_ARRAY */
 
 LookupStatus
-GetElementIC::update(VMFrame &f, JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp)
+GetElementIC::update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp)
 {
     /*
      * Only treat this as a GETPROP for non-numeric string identifiers. The
      * GETPROP IC assumes the id has already gone through filtering for string
      * indexes in the emitter, i.e. js_GetProtoIfDenseArray is only valid to
      * use when looking up non-integer identifiers.
      */
     if (v.isString() && js_CheckForStringIndex(id) == id)
-        return attachGetProp(f, cx, obj, v, id, vp);
+        return attachGetProp(f, obj, v, id, vp);
 
 #if defined JS_METHODJIT_TYPED_ARRAY
     /*
      * Typed array ICs can make stub calls, and need to know which registers
      * are in use and need to be restored after the call. If type inference is
      * enabled then we don't necessarily know the full set of such registers
      * when generating the IC (loop-carried registers may be allocated later),
      * and additionally the push/pop instructions used to save/restore in the
      * IC are not compatible with carrying entries in floating point registers.
      * Since we can use type information to generate inline paths for typed
      * arrays, just don't generate these ICs with inference enabled.
      */
-    if (!cx->typeInferenceEnabled() && js_IsTypedArray(obj))
-        return attachTypedArray(cx, obj, v, id, vp);
+    if (!f.cx->typeInferenceEnabled() && js_IsTypedArray(obj))
+        return attachTypedArray(f, obj, v, id, vp);
 #endif
 
-    return disable(cx, "unhandled object and key type");
+    return disable(f.cx, "unhandled object and key type");
 }
 
 void JS_FASTCALL
 ic::CallElement(VMFrame &f, ic::GetElementIC *ic)
 {
     JSContext *cx = f.cx;
 
     // Right now, we don't optimize for strings.
@@ -2892,17 +2897,17 @@ ic::CallElement(VMFrame &f, ic::GetEleme
         id = INT_TO_JSID(idval.toInt32());
     else if (!js_InternNonIntElementId(cx, thisObj, idval, &id))
         THROW();
 
     if (!monitor.recompiled() && ic->shouldUpdate(cx)) {
 #ifdef DEBUG
         f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC);
 #endif
-        LookupStatus status = ic->update(f, cx, thisObj, idval, id, &f.regs.sp[-2]);
+        LookupStatus status = ic->update(f, thisObj, idval, id, &f.regs.sp[-2]);
         if (status != Lookup_Uncacheable) {
             if (status == Lookup_Error)
                 THROW();
 
             // If the result can be cached, the value was already retrieved.
             JS_ASSERT(!f.regs.sp[-2].isMagic());
             f.regs.sp[-1].setObject(*thisObj);
             return;
@@ -2953,17 +2958,17 @@ ic::GetElement(VMFrame &f, ic::GetElemen
         if (!js_InternNonIntElementId(cx, obj, idval, &id))
             THROW();
     }
 
     if (!monitor.recompiled() && ic->shouldUpdate(cx)) {
 #ifdef DEBUG
         f.regs.sp[-2] = MagicValue(JS_GENERIC_MAGIC);
 #endif
-        LookupStatus status = ic->update(f, cx, obj, idval, id, &f.regs.sp[-2]);
+        LookupStatus status = ic->update(f, obj, idval, id, &f.regs.sp[-2]);
         if (status != Lookup_Uncacheable) {
             if (status == Lookup_Error)
                 THROW();
 
             // If the result can be cached, the value was already retrieved.
             JS_ASSERT(!f.regs.sp[-2].isMagic());
             return;
         }
@@ -3005,18 +3010,20 @@ SetElementIC::purge(Repatcher &repatcher
         void *stub = JS_FUNC_TO_DATA_PTR(void *, APPLY_STRICTNESS(ic::SetElement, strictMode));
         repatcher.relink(slowPathCall, FunctionPtr(stub));
     }
 
     reset();
 }
 
 LookupStatus
-SetElementIC::attachHoleStub(JSContext *cx, JSObject *obj, int32 keyval)
+SetElementIC::attachHoleStub(VMFrame &f, JSObject *obj, int32 keyval)
 {
+    JSContext *cx = f.cx;
+
     if (keyval < 0)
         return disable(cx, "negative key index");
 
     // We may have failed a capacity check instead of a dense array check.
     // However we should still build the IC in this case, since it could
     // be in a loop that is filling in the array. We can assert, however,
     // that either we're in capacity or there's a hole - guaranteed by
     // the fast path.
@@ -3089,36 +3096,37 @@ SetElementIC::attachHoleStub(JSContext *
     if (!buffer.verifyRange(cx->fp()->jit()))
         return disable(cx, "code memory is out of range");
 
     // Patch all guards.
     for (size_t i = 0; i < fails.length(); i++)
         buffer.link(fails[i], slowPathStart);
     buffer.link(done, fastPathRejoin);
 
-    CodeLocationLabel cs = buffer.finalize();
+    CodeLocationLabel cs = buffer.finalize(f);
     JaegerSpew(JSpew_PICs, "generated dense array hole stub at %p\n", cs.executableAddress());
 
     Repatcher repatcher(cx->fp()->jit());
     repatcher.relink(fastPathStart.jumpAtOffset(inlineHoleGuard), cs);
     inlineHoleGuardPatched = true;
 
     disable(cx, "generated dense array hole stub");
 
     return Lookup_Cacheable;
 }
 
 #if defined JS_METHODJIT_TYPED_ARRAY
 LookupStatus
-SetElementIC::attachTypedArray(JSContext *cx, JSObject *obj, int32 key)
+SetElementIC::attachTypedArray(VMFrame &f, JSObject *obj, int32 key)
 {
     // Right now, only one clasp guard extension is supported.
     JS_ASSERT(!inlineClaspGuardPatched);
 
     Assembler masm;
+    JSContext *cx = f.cx;
 
     // Guard on this typed array's clasp.
     Jump claspGuard = masm.testObjClass(Assembler::NotEqual, objReg, obj->getClass());
 
     // Bounds check.
     Jump outOfBounds;
     Address typedArrayLength(objReg, TypedArray::lengthOffset());
     if (hasConstantKey)
@@ -3192,46 +3200,46 @@ SetElementIC::attachTypedArray(JSContext
 
     disable(cx, "generated typed array stub");
 
     return Lookup_Cacheable;
 }
 #endif /* JS_METHODJIT_TYPED_ARRAY */
 
 LookupStatus
-SetElementIC::update(JSContext *cx, const Value &objval, const Value &idval)
+SetElementIC::update(VMFrame &f, const Value &objval, const Value &idval)
 {
     if (!objval.isObject())
-        return disable(cx, "primitive lval");
+        return disable(f.cx, "primitive lva