Merge last green changeset from mozilla-inbound to mozilla-central
authorMarco Bonardo <mbonardo@mozilla.com>
Wed, 12 Oct 2011 12:02:45 +0200
changeset 79947 866b2b1793cdfc66561bddb20d9ad572f28ec6ca
parent 79918 e0ae39a3298ea6aed6b22dece381f8a41404a98b (current diff)
parent 79946 69369e7dad6c645cc4b3f10f317f32bb188207a0 (diff)
child 79948 4da70aca03cd21253591d7130bbfb5988c418310
push id434
push userclegnitto@mozilla.com
push dateWed, 21 Dec 2011 12:10:54 +0000
treeherdermozilla-beta@bddb6ed8dd47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last green changeset from mozilla-inbound to mozilla-central
configure.in
js/src/configure.in
--- a/configure.in
+++ b/configure.in
@@ -7389,16 +7389,33 @@ AC_SUBST(MOZ_DEMANGLE_SYMBOLS)
 dnl ========================================================
 dnl = Support for gcc stack unwinding (from gcc 3.3)
 dnl ========================================================
 if test -z "$SKIP_LIBRARY_CHECKS"; then
     MOZ_CHECK_HEADER(unwind.h, AC_CHECK_FUNCS(_Unwind_Backtrace))
 fi
 
 dnl ========================================================
+dnl JIT observers
+dnl ========================================================
+
+MOZ_ARG_WITH_STRING(jitreport-granularity,
+[  --jitreport-granularity=N
+                           Default granularity at which to report JIT code
+                           to external tools
+                             0 - no info
+                             1 - code ranges for whole functions only
+                             2 - per-line information
+                             3 - per-op information],
+  JITREPORT_GRANULARITY=$withval,
+  JITREPORT_GRANULARITY=3)
+
+AC_DEFINE_UNQUOTED(JS_DEFAULT_JITREPORT_GRANULARITY, $JITREPORT_GRANULARITY)
+
+dnl ========================================================
 dnl =
 dnl = Misc. Options
 dnl =
 dnl ========================================================
 MOZ_ARG_HEADER(Misc. Options)
 
 dnl ========================================================
 dnl update xterm title
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -121,18 +121,18 @@ class Loader;
 
 namespace dom {
 class Link;
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID      \
-{ 0xd76bcf5f, 0xd02f, 0x459a, \
- { 0xb1, 0x23, 0x8e, 0x2c, 0x9a, 0x0d, 0x84, 0x68 } }
+{ 0x448c396a, 0x013c, 0x47b8, \
+ { 0x95, 0xf4, 0x56, 0x68, 0x0f, 0x5f, 0x12, 0xf8 } }
 
 // Flag for AddStyleSheet().
 #define NS_STYLESHEET_FROM_CATALOG                (1 << 0)
 
 // Document states
 
 // RTL locale: specific to the XUL localedir attribute
 #define NS_DOCUMENT_STATE_RTL_LOCALE              NS_DEFINE_EVENT_STATE_MACRO(0)
@@ -1316,27 +1316,27 @@ public:
   virtual void EnumerateExternalResources(nsSubDocEnumFunc aCallback,
                                           void* aData) = 0;
 
   /**
    * Return whether the document is currently showing (in the sense of
    * OnPageShow() having been called already and OnPageHide() not having been
    * called yet.
    */
-  bool IsShowing() { return mIsShowing; }
+  bool IsShowing() const { return mIsShowing; }
   /**
    * Return whether the document is currently visible (in the sense of
    * OnPageHide having been called and OnPageShow not yet having been called)
    */
-  bool IsVisible() { return mVisible; }
+  bool IsVisible() const { return mVisible; }
   /**
    * Return true when this document is active, i.e., the active document
    * in a content viewer.
    */
-  bool IsActive() { return mDocumentContainer && !mRemovedFromDocShell; }
+  bool IsActive() const { return mDocumentContainer && !mRemovedFromDocShell; }
 
   void RegisterFreezableElement(nsIContent* aContent);
   bool UnregisterFreezableElement(nsIContent* aContent);
   typedef void (* FreezableElementEnumerator)(nsIContent*, void*);
   void EnumerateFreezableElements(FreezableElementEnumerator aEnumerator,
                                   void* aData);
 
 #ifdef MOZ_SMIL
@@ -1568,16 +1568,18 @@ public:
 #define DEPRECATED_OPERATION(_op) e##_op,
   enum DeprecatedOperations {
 #include "nsDeprecatedOperationList.h"
     eDeprecatedOperationCount
   };
 #undef DEPRECATED_OPERATION
   void WarnOnceAbout(DeprecatedOperations aOperation);
 
+  virtual void PostVisibilityUpdateEvent() = 0;
+
 private:
   PRUint64 mWarnedAbout;
 
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
     //     releasing it) happens in the nsDocument destructor. We'd prefer to
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1521,16 +1521,17 @@ nsDOMImplementation::CreateHTMLDocument(
 
   // NOTE! nsDocument::operator new() zeroes out all members, so don't
   // bother initializing members to 0.
 
 nsDocument::nsDocument(const char* aContentType)
   : nsIDocument()
   , mAnimatingImages(PR_TRUE)
   , mIsFullScreen(PR_FALSE)
+  , mVisibilityState(eHidden)
 {
   SetContentTypeInternal(nsDependentCString(aContentType));
   
 #ifdef PR_LOGGING
   if (!gDocumentLeakPRLog)
     gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
 
   if (gDocumentLeakPRLog)
@@ -3832,16 +3833,23 @@ nsDocument::SetScriptGlobalObject(nsIScr
 
     MaybeRescheduleAnimationFrameNotifications();
   }
 
   // Remember the pointer to our window (or lack there of), to avoid
   // having to QI every time it's asked for.
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(mScriptGlobalObject);
   mWindow = window;
+
+  // Set our visibility state, but do not fire the event.  This is correct
+  // because either we're coming out of bfcache (in which case IsVisible() will
+  // still test false at this point and no state change will happen) or we're
+  // doing the initial document load and don't want to fire the event for this
+  // change.
+  mVisibilityState = GetVisibilityState();
 }
 
 nsIScriptGlobalObject*
 nsDocument::GetScriptHandlingObjectInternal() const
 {
   NS_ASSERTION(!mScriptGlobalObject,
                "Do not call this when mScriptGlobalObject is set!");
 
@@ -7317,16 +7325,18 @@ nsDocument::OnPageShow(bool aPersisted,
     mAnimationController->OnPageShow();
   }
 #endif
 
   if (aPersisted) {
     SetImagesNeedAnimating(PR_TRUE);
   }
 
+  UpdateVisibilityState();
+
   nsCOMPtr<nsIDOMEventTarget> target = aDispatchStartTarget;
   if (!target) {
     target = do_QueryInterface(GetWindow());
   }
   DispatchPageTransition(target, NS_LITERAL_STRING("pageshow"), aPersisted);
 }
 
 static bool
@@ -7378,16 +7388,19 @@ nsDocument::OnPageHide(bool aPersisted,
   // Now send out a PageHide event.
   nsCOMPtr<nsIDOMEventTarget> target = aDispatchStartTarget;
   if (!target) {
     target = do_QueryInterface(GetWindow());
   }
   DispatchPageTransition(target, NS_LITERAL_STRING("pagehide"), aPersisted);
 
   mVisible = PR_FALSE;
+
+  UpdateVisibilityState();
+  
   EnumerateExternalResources(NotifyPageHide, &aPersisted);
   EnumerateFreezableElements(NotifyActivityChanged, nsnull);
 }
 
 void
 nsDocument::WillDispatchMutationEvent(nsINode* aTarget)
 {
   NS_ASSERTION(mSubtreeModifiedDepth != 0 ||
@@ -8653,8 +8666,66 @@ nsDocument::SizeOf() const
     return nsINode::SetOn##name_(cx, v);                                  \
   }
 #define TOUCH_EVENT EVENT
 #define DOCUMENT_ONLY_EVENT EVENT
 #include "nsEventNameList.h"
 #undef DOCUMENT_ONLY_EVENT
 #undef TOUCH_EVENT
 #undef EVENT
+
+void
+nsDocument::UpdateVisibilityState()
+{
+  VisibilityState oldState = mVisibilityState;
+  mVisibilityState = GetVisibilityState();
+  if (oldState != mVisibilityState) {
+    nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
+                                         NS_LITERAL_STRING("mozvisibilitychange"),
+                                         false, false);
+  }
+}
+
+nsDocument::VisibilityState
+nsDocument::GetVisibilityState() const
+{
+  // We have to check a few pieces of information here:
+  // 1)  Are we in bfcache (!IsVisible())?  If so, nothing else matters.
+  // 2)  Do we have an outer window?  If not, we're hidden.  Note that we don't
+  //     want to use GetWindow here because it does weird groveling for windows
+  //     in some cases.
+  // 3)  Is our outer window background?  If so, we're hidden.
+  // Otherwise, we're visible.
+  if (!IsVisible() || !mWindow || !mWindow->GetOuterWindow() ||
+      mWindow->GetOuterWindow()->IsBackground()) {
+    return eHidden;
+  }
+
+  return eVisible;
+}
+
+/* virtual */ void
+nsDocument::PostVisibilityUpdateEvent()
+{
+  nsCOMPtr<nsIRunnable> event =
+    NS_NewRunnableMethod(this, &nsDocument::UpdateVisibilityState);
+  NS_DispatchToMainThread(event);
+}
+
+NS_IMETHODIMP
+nsDocument::GetMozHidden(bool* aHidden)
+{
+  *aHidden = mVisibilityState != eVisible;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDocument::GetMozVisibilityState(nsAString& aState)
+{
+  // This needs to stay in sync with the VisibilityState enum.
+  static const char states[][8] = {
+    "hidden",
+    "visible"
+  };
+  PR_STATIC_ASSERT(NS_ARRAY_LENGTH(states) == eVisibilityStateCount);
+  aState.AssignASCII(states[mVisibilityState]);
+  return NS_OK;
+}
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -943,16 +943,22 @@ public:
 
   virtual void ResetFullScreenElement();
   virtual Element* GetFullScreenElement();
   virtual void RequestFullScreen(Element* aElement);
   virtual void CancelFullScreen();
   virtual void UpdateFullScreenStatus(bool aIsFullScreen);
   virtual bool IsFullScreenDoc();
 
+  // This method may fire a DOM event; if it does so it will happen
+  // synchronously.
+  void UpdateVisibilityState();
+  // Posts an event to call UpdateVisibilityState
+  virtual void PostVisibilityUpdateEvent();
+
 protected:
   friend class nsNodeUtils;
 
   /**
    * Check that aId is not empty and log a message to the console
    * service if it is.
    * @returns PR_TRUE if aId looks correct, PR_FALSE otherwise.
    */
@@ -1145,16 +1151,24 @@ protected:
   nsCOMPtr<nsIContent> mFirstBaseNodeWithHref;
 
   nsEventStates mDocumentState;
   nsEventStates mGotDocumentState;
 
   nsRefPtr<nsDOMNavigationTiming> mTiming;
 private:
   friend class nsUnblockOnloadEvent;
+  // This needs to stay in sync with the list in GetMozVisibilityState.
+  enum VisibilityState {
+    eHidden = 0,
+    eVisible,
+    eVisibilityStateCount
+  };
+  // Recomputes the visibility state but doesn't set the new value.
+  VisibilityState GetVisibilityState() const;
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
   nsresult CheckFrameOptions();
   nsresult InitCSP();
 
   /**
@@ -1225,16 +1239,18 @@ private:
 
   nsCString mScrollToRef;
   PRUint8 mScrolledToRefAlready : 1;
   PRUint8 mChangeScrollPosWhenScrollingToRef : 1;
 
   // Tracking for images in the document.
   nsDataHashtable< nsPtrHashKey<imgIRequest>, PRUint32> mImageTracker;
 
+  VisibilityState mVisibilityState;
+
 #ifdef DEBUG
 protected:
   bool mWillReparent;
 #endif
 };
 
 #define NS_DOCUMENT_INTERFACE_TABLE_BEGIN(_class)                             \
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                            \
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -511,16 +511,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug675166.html \
 		test_bug682554.html \
 		test_bug682592.html \
 		bug682592-subframe.html \
 		bug682592-subframe-ref.html \
 		test_bug684671.html \
 		test_bug685798.html \
 		test_bug686449.xhtml \
+		test_bug690056.html \
 		test_bug692434.html \
 		file_bug692434.xml \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug690056.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=690056
+-->
+<head>
+  <title>Test for Bug 690056</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=690056">Mozilla Bug 690056</a>
+<p id="display">
+  <iframe id="x"></iframe>
+  <iframe style="display: none" id="y"></iframe>
+</p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 690056 **/
+SimpleTest.waitForExplicitFinish();
+is(document.mozHidden, false, "Document should not be hidden during load");
+is(document.mozVisibilityState, "visible",
+   "Document should be visible during load");
+
+addLoadEvent(function() {
+  var doc = document.implementation.createDocument("", "", null);
+  is(doc.mozHidden, true, "Data documents should be hidden");
+  is(doc.mozVisibilityState, "hidden", "Data documents really should be hidden");
+
+  is(document.mozHidden, false, "Document should not be hidden onload");
+  is(document.mozVisibilityState, "visible",
+     "Document should be visible onload");
+
+  is($("x").contentDocument.mozHidden, false,
+     "Subframe document should not be hidden onload");
+  is($("x").contentDocument.mozVisibilityState, "visible",
+     "Subframe document should be visible onload");
+  is($("y").contentDocument.mozHidden, false,
+     "display:none subframe document should not be hidden onload");
+  is($("y").contentDocument.mozVisibilityState, "visible",
+     "display:none subframe document should be visible onload");
+  
+  SimpleTest.finish();
+});
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/xslt/src/xslt/txStylesheetCompiler.h
+++ b/content/xslt/src/xslt/txStylesheetCompiler.h
@@ -72,18 +72,18 @@ public:
     nsRefPtr<txNamespaceMap> mMappings;
     nsTArray<PRInt32> mInstructionNamespaces;
     PRInt32 mDepth;
 };
 
 class txACompileObserver
 {
 public:
-    virtual void AddRef() = 0;
-    virtual void Release() = 0;
+    NS_IMETHOD_(nsrefcnt) AddRef() = 0;
+    NS_IMETHOD_(nsrefcnt) Release() = 0;
 
     virtual nsresult loadURI(const nsAString& aUri,
                              const nsAString& aReferrerUri,
                              txStylesheetCompiler* aCompiler) = 0;
     virtual void onDoneCompiling(txStylesheetCompiler* aCompiler,
                                  nsresult aResult,
                                  const PRUnichar *aErrorText = nsnull,
                                  const PRUnichar *aParam = nsnull) = 0;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -4877,16 +4877,20 @@ nsDocShell::SetIsActive(bool aIsActive)
   GetPresShell(getter_AddRefs(pshell));
   if (pshell)
     pshell->SetIsActive(aIsActive);
 
   // Tell the window about it
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mScriptGlobal);
   if (win) {
       win->SetIsBackground(!aIsActive);
+      nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
+      if (doc) {
+          doc->PostVisibilityUpdateEvent();
+      }
   }
 
   // Recursively tell all of our children
   PRInt32 n = mChildList.Count();
   for (PRInt32 i = 0; i < n; ++i) {
       nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(ChildAt(i));
       if (docshell)
         docshell->SetIsActive(aIsActive);
--- a/docshell/test/chrome/Makefile.in
+++ b/docshell/test/chrome/Makefile.in
@@ -115,16 +115,18 @@ include $(topsrcdir)/config/rules.mk
 		test_bug454235.xul \
 		bug454235-subframe.xul \
 		test_bug456980.xul \
 		test_bug662200.xul \
 		bug662200_window.xul \
 		662200a.html \
 		662200b.html \
 		662200c.html \
+		test_bug690056.xul \
+		bug690056_window.xul \
 		$(NULL)
 
 _DOCSHELL_SUBHARNESS = \
     docshell_helpers.js \
     generic.html \
     $(NULL)
 
 libs:: $(_HTTP_FILES)
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/bug690056_window.xul
@@ -0,0 +1,176 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window id="690056Test"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        width="600"
+        height="600"
+        onload="setTimeout(nextTest,0);"
+        title="bug 6500056 test">
+
+  <script type="application/javascript" src= "chrome://mochikit/content/chrome-harness.js" />
+  <script type="application/javascript" src="docshell_helpers.js" />
+  <script type="application/javascript"><![CDATA[
+    var tests = testIterator();
+
+    function nextTest() {
+      tests.next();
+    }
+
+    // Makes sure that we fire the visibilitychange events
+    function testIterator() {
+      // Enable bfcache
+      enableBFCache(8);
+
+      // Load something for a start
+      doPageNavigation({
+        uri: 'data:text/html,<title>initial load</title>',
+        onNavComplete: nextTest
+      });
+      yield;
+
+      // Now load a new page
+      doPageNavigation({
+        uri: 'data:text/html,<title>new load</title>',
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "initial load",
+                            persisted: true },
+                          { type: "mozvisibilitychange",
+                            title: "initial load",
+                            visibilityState: "hidden",
+                            hidden: true },
+                          // No visibilitychange events fired for initial pageload
+                          { type: "pageshow",
+                            title: "new load",
+                            persisted: false }, // false on initial load
+                        ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      // Now go back
+      doPageNavigation({
+        back: true,
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "new load",
+                            persisted: true },
+                          { type: "mozvisibilitychange",
+                            title: "new load",
+                            visibilityState: "hidden",
+                            hidden: true },
+                          { type: "mozvisibilitychange",
+                            title: "initial load",
+                            visibilityState: "visible",
+                            hidden: false },
+                          { type: "pageshow",
+                            title: "initial load",
+                            persisted: true },
+                        ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      // And forward
+      doPageNavigation({
+        forward: true,
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "initial load",
+                            persisted: true },
+                          { type: "mozvisibilitychange",
+                            title: "initial load",
+                            visibilityState: "hidden",
+                            hidden: true },
+                          { type: "mozvisibilitychange",
+                            title: "new load",
+                            visibilityState: "visible",
+                            hidden: false },
+                          { type: "pageshow",
+                            title: "new load",
+                            persisted: true },
+                        ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      function generateDetector(state, hidden, title, name) {
+        var detector = function (event) {
+          is(event.target.mozHidden, hidden,
+             name + " hidden value does not match");
+          is(event.target.mozVisibilityState, state,
+             name + " state value does not match");
+          is(event.target.title, title,
+             name + " title value does not match");
+          document.getElementById("content")
+                  .removeEventListener("mozvisibilitychange",
+                                       detector,
+                                       true);
+          nextTest();
+        }
+
+        document.getElementById("content")
+                .addEventListener("mozvisibilitychange", detector, true);
+      }
+      
+      generateDetector("hidden", true, "new load", "Going hidden");
+        
+      // Now flip our docshell to not active
+      document.getElementById("content").docShellIsActive = false;
+      yield;
+
+      // And navigate back; there should be no visibility state transitions
+      doPageNavigation({
+        back: true,
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "new load",
+                            persisted: true },
+                          { type: "pageshow",
+                            title: "initial load",
+                            persisted: true },
+                        ],
+        unexpectedEvents: [ "mozvisibilitychange" ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      generateDetector("visible", false, "initial load", "Going visible");
+
+      // Now set the docshell active again
+      document.getElementById("content").docShellIsActive = true;
+      yield;
+
+      // And forward
+      doPageNavigation({
+        forward: true,
+        eventsToListenFor: [ "pageshow", "pagehide", "mozvisibilitychange" ],
+        expectedEvents: [ { type: "pagehide",
+                            title: "initial load",
+                            persisted: true },
+                          { type: "mozvisibilitychange",
+                            title: "initial load",
+                            visibilityState: "hidden",
+                            hidden: true },
+                          { type: "mozvisibilitychange",
+                            title: "new load",
+                            visibilityState: "visible",
+                            hidden: false },
+                          { type: "pageshow",
+                            title: "new load",
+                            persisted: true },
+                        ],
+        onNavComplete: nextTest
+      });
+      yield;
+
+      // Tell the framework the test is finished.  Include the final 'yield' 
+      // statement to prevent a StopIteration exception from being thrown.
+      finish();
+      yield;      
+    }
+  ]]></script>
+
+  <browser type="content-primary" flex="1" id="content" src="about:blank"/>
+</window>
\ No newline at end of file
--- a/docshell/test/chrome/docshell_helpers.js
+++ b/docshell/test/chrome/docshell_helpers.js
@@ -13,16 +13,18 @@ for each (var name in imports) {
 const NAV_NONE = 0;
 const NAV_BACK = 1;
 const NAV_FORWARD = 2;
 const NAV_URI = 3;
 const NAV_RELOAD = 4;
 
 var gExpectedEvents;          // an array of events which are expected to
                               // be triggered by this navigation
+var gUnexpectedEvents;        // an array of event names which are NOT expected
+                              // to be triggered by this navigation
 var gFinalEvent;              // true if the last expected event has fired
 var gUrisNotInBFCache = [];   // an array of uri's which shouldn't be stored
                               // in the bfcache
 var gNavType = NAV_NONE;      // defines the most recent navigation type
                               // executed by doPageNavigation
 var gOrigMaxTotalViewers =    // original value of max_total_viewers,
   undefined;                  // to be restored at end of test
 
@@ -90,16 +92,18 @@ function doPageNavigation(params) {
   let back = params.back ? params.back : false;
   let forward = params.forward ? params.forward : false;
   let reload = params.reload ? params.reload : false;
   let uri = params.uri ? params.uri : false;
   let eventsToListenFor = typeof(params.eventsToListenFor) != "undefined" ?
     params.eventsToListenFor : ["pageshow"];
   gExpectedEvents = typeof(params.eventsToListenFor) == "undefined" || 
     eventsToListenFor.length == 0 ? undefined : params.expectedEvents; 
+  gUnexpectedEvents = typeof(params.eventsToListenFor) == "undefined" || 
+    eventsToListenFor.length == 0 ? undefined : params.unexpectedEvents; 
   let preventBFCache = (typeof[params.preventBFCache] == "undefined") ? 
     false : params.preventBFCache;
   let waitOnly = (typeof(params.waitForEventsOnly) == "boolean" 
     && params.waitForEventsOnly);
   
   // Do some sanity checking on arguments.  
   if (back && forward)
     throw "Can't specify both back and forward";
@@ -124,16 +128,20 @@ function doPageNavigation(params) {
   for each (let anEventType in eventsToListenFor) {
     let eventFound = false;
     if ( (anEventType == "pageshow") && (!gExpectedEvents) )
       eventFound = true;
     for each (let anExpectedEvent in gExpectedEvents) {
       if (anExpectedEvent.type == anEventType)
         eventFound = true;
     }
+    for each (let anExpectedEventType in gUnexpectedEvents) {
+      if (anExpectedEventType == anEventType)
+        eventFound = true;
+    }
     if (!eventFound)
       throw "Event type " + anEventType + " is specified in " +
         "eventsToListenFor, but not in expectedEvents";
   }
   
   // If the test explicitly sets .eventsToListenFor to [], don't wait for any 
   // events.
   gFinalEvent = eventsToListenFor.length == 0 ? true : false;
@@ -255,17 +263,22 @@ function pageEventListener(event) {
   if ( (event.type == "pageshow") && 
     (gNavType == NAV_BACK || gNavType == NAV_FORWARD) ) {
     let uri = TestWindow.getBrowser().currentURI.spec;
     if (uri in gUrisNotInBFCache) {
       ok(!event.persisted, "pageshow event has .persisted = false, even " +
        "though it was loaded with .preventBFCache previously\n");
     }
   }
-  
+
+  if (typeof(gUnexpectedEvents) != "undefined") {
+    is(gUnexpectedEvents.indexOf(event.type), -1,
+       "Should not get unexpected event " + event.type);
+  }  
+
   // If no expected events were specified, mark the final event as having been 
   // triggered when a pageshow event is fired; this will allow 
   // doPageNavigation() to return.
   if ((typeof(gExpectedEvents) == "undefined") && event.type == "pageshow")
   {
     setTimeout(function() { gFinalEvent = true; }, 0);
     return;
   }
@@ -296,16 +309,28 @@ function pageEventListener(event) {
   }  
   
   if (typeof(expected.persisted) != "undefined") {
     is(event.persisted, expected.persisted, 
       "The persisted property of the " + event.type + " event on page " +
       event.originalTarget.location + " had an unexpected value"); 
   }
 
+  if ("visibilityState" in expected) {
+    is(event.originalTarget.mozVisibilityState, expected.visibilityState,
+       "The visibilityState property of the document on page " +
+       event.originalTarget.location + " had an unexpected value");
+  }
+
+  if ("hidden" in expected) {
+    is(event.originalTarget.mozHidden, expected.hidden,
+       "The hidden property of the document on page " +
+       event.originalTarget.location + " had an unexpected value");
+  }
+
   // If we're out of expected events, let doPageNavigation() return.
   if (gExpectedEvents.length == 0)
     setTimeout(function() { gFinalEvent = true; }, 0);
 }
 
 /**
  * End a test.  
  */
new file mode 100644
--- /dev/null
+++ b/docshell/test/chrome/test_bug690056.xul
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=690056
+-->
+<window title="Mozilla Bug 690056"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=690056"
+     target="_blank">Mozilla Bug 690056</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript">
+  <![CDATA[
+  /** Test for Bug 690056 **/
+SimpleTest.waitForExplicitFinish();
+window.open("bug690056_window.xul", "bug690056",
+            "chrome,width=600,height=600");
+  ]]>
+  </script>
+</window>
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -92,31 +92,39 @@ public:
 
   virtual void ActivateOrDeactivate(bool aActivate) = 0;
 
   // this is called GetTopWindowRoot to avoid conflicts with nsIDOMWindow::GetWindowRoot
   virtual already_AddRefed<nsPIWindowRoot> GetTopWindowRoot() = 0;
 
   virtual void SetActive(bool aActive)
   {
+    NS_PRECONDITION(IsOuterWindow(),
+                    "active state is only maintained on outer windows");
     mIsActive = aActive;
   }
 
   bool IsActive()
   {
+    NS_PRECONDITION(IsOuterWindow(),
+                    "active state is only maintained on outer windows");
     return mIsActive;
   }
 
   virtual void SetIsBackground(bool aIsBackground)
   {
+    NS_PRECONDITION(IsOuterWindow(),
+                    "background state is only maintained on outer windows");
     mIsBackground = aIsBackground;
   }
 
   bool IsBackground()
   {
+    NS_PRECONDITION(IsOuterWindow(),
+                    "background state is only maintained on outer windows");
     return mIsBackground;
   }
 
   nsIDOMEventTarget* GetChromeEventHandler() const
   {
     return mChromeEventHandler;
   }
 
--- a/dom/interfaces/core/nsIDOMDocument.idl
+++ b/dom/interfaces/core/nsIDOMDocument.idl
@@ -61,17 +61,17 @@ interface nsIDOMLocation;
  * cannot exist outside the context of a Document, the nsIDOMDocument 
  * interface also contains the factory methods needed to create these 
  * objects.
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[scriptable, uuid(3f845f32-cb34-459c-8f79-2dfaa3088bbf)]
+[scriptable, uuid(CD4CD7C3-C688-4E50-9A72-4A00EABE66AB)]
 interface nsIDOMDocument : nsIDOMNode
 {
   readonly attribute nsIDOMDocumentType         doctype;
   readonly attribute nsIDOMDOMImplementation    implementation;
   readonly attribute nsIDOMElement              documentElement;
   nsIDOMElement                 createElement(in DOMString tagName)
                                   raises(DOMException);
   nsIDOMDocumentFragment        createDocumentFragment();
@@ -406,9 +406,15 @@ interface nsIDOMDocument : nsIDOMNode
 
   /**
    * Inline event handler for readystatechange events.
    */
   [implicit_jscontext] attribute jsval onreadystatechange;
 
   [implicit_jscontext] attribute jsval onmouseenter;
   [implicit_jscontext] attribute jsval onmouseleave;
+
+  /**
+   * Visibility API implementation.
+   */
+  readonly attribute boolean mozHidden;
+  readonly attribute DOMString mozVisibilityState;
 };
--- a/dom/interfaces/core/nsIDOMXMLDocument.idl
+++ b/dom/interfaces/core/nsIDOMXMLDocument.idl
@@ -33,17 +33,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMDocument.idl"
 
-[scriptable, uuid(9f566fd8-8bd7-49eb-be8b-16fb50d00d32)]
+[scriptable, uuid(BB4D4D76-3802-4191-88E2-933BA609C4E1)]
 interface nsIDOMXMLDocument : nsIDOMDocument
 {
   // DOM Level 3 Load & Save, DocumentLS
   // http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS
   /**
    * Whether to load synchronously or asynchronously.
    * The default is async==true.
    */
--- a/dom/interfaces/html/nsIDOMHTMLDocument.idl
+++ b/dom/interfaces/html/nsIDOMHTMLDocument.idl
@@ -42,17 +42,17 @@
 /**
  * The nsIDOMHTMLDocument interface is the interface to a [X]HTML
  * document object.
  *
  * @see <http://www.whatwg.org/html/>
  */
 interface nsISelection;
 
-[scriptable, uuid(280857b8-c52c-455e-8b47-c56ad96614f7)]
+[scriptable, uuid(C94A5F14-F79F-4054-A93C-E8FF35623460)]
 interface nsIDOMHTMLDocument : nsIDOMDocument
 {
   readonly attribute DOMString            URL;
            attribute DOMString            domain;
            attribute DOMString            cookie;
   // returns "BackCompat" if we're in quirks mode,
   // or "CSS1Compat" if we're in strict mode
   readonly attribute DOMString            compatMode;
--- a/dom/interfaces/svg/nsIDOMSVGDocument.idl
+++ b/dom/interfaces/svg/nsIDOMSVGDocument.idl
@@ -34,15 +34,15 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMDocument.idl"
 
 interface nsIDOMSVGSVGElement;
 
-[scriptable, uuid(78ebe55f-631f-4b3b-9eba-c3689ff5ccbc)]
+[scriptable, uuid(B3806DF6-7ED4-4426-84E6-545EEFE5AA9A)]
 interface nsIDOMSVGDocument : nsIDOMDocument
 {
   readonly attribute DOMString domain;
   readonly attribute DOMString URL;
   readonly attribute nsIDOMSVGSVGElement rootElement;
 };
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -155,19 +155,16 @@ NPObjWrapper_GetProperty(JSContext *cx, 
 static JSBool
 NPObjWrapper_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
                           jsval *statep, jsid *idp);
 
 static JSBool
 NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsid id, uintN flags,
                         JSObject **objp);
 
-static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
-
 static void
 NPObjWrapper_Finalize(JSContext *cx, JSObject *obj);
 
 static JSBool
 NPObjWrapper_Call(JSContext *cx, uintN argc, jsval *vp);
 
 static JSBool
 NPObjWrapper_Construct(JSContext *cx, uintN argc, jsval *vp);
@@ -178,17 +175,17 @@ CreateNPObjectMember(NPP npp, JSContext 
 
 static JSClass sNPObjectJSWrapperClass =
   {
     NPRUNTIME_JSCLASS_NAME,
     JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_NEW_ENUMERATE,
     NPObjWrapper_AddProperty, NPObjWrapper_DelProperty,
     NPObjWrapper_GetProperty, NPObjWrapper_SetProperty,
     (JSEnumerateOp)NPObjWrapper_newEnumerate,
-    (JSResolveOp)NPObjWrapper_NewResolve, NPObjWrapper_Convert,
+    (JSResolveOp)NPObjWrapper_NewResolve, JS_ConvertStub,
     NPObjWrapper_Finalize, nsnull, nsnull, NPObjWrapper_Call,
     NPObjWrapper_Construct, nsnull, nsnull
   };
 
 typedef struct NPObjectMemberPrivate {
     JSObject *npobjWrapper;
     jsval fieldValue;
     NPIdentifier methodName;
@@ -1678,28 +1675,16 @@ NPObjWrapper_NewResolve(JSContext *cx, J
 
     return fnc != nsnull;
   }
 
   // no property or method
   return JS_TRUE;
 }
 
-static JSBool
-NPObjWrapper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp)
-{
-  // The sole reason we implement this hook is to prevent the JS
-  // engine from calling valueOf() on NPObject's. Some NPObject's may
-  // actually implement a method named valueOf, but it's unlikely to
-  // behave as the JS engine expects it to. IOW, this is an empty hook
-  // that overrides what the default hook does.
-
-  return JS_TRUE;
-}
-
 static void
 NPObjWrapper_Finalize(JSContext *cx, JSObject *obj)
 {
   NPObject *npobj = (NPObject *)::JS_GetPrivate(cx, obj);
   if (npobj) {
     if (sNPObjWrappers.ops) {
       PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_REMOVE);
     }
@@ -2190,16 +2175,19 @@ NPObjectMember_Convert(JSContext *cx, JS
 
   switch (type) {
   case JSTYPE_VOID:
   case JSTYPE_STRING:
   case JSTYPE_NUMBER:
   case JSTYPE_BOOLEAN:
   case JSTYPE_OBJECT:
     *vp = memberPrivate->fieldValue;
+    if (!JSVAL_IS_PRIMITIVE(*vp)) {
+      return JS_ConvertStub(cx, JSVAL_TO_OBJECT(*vp), type, vp);
+    }
     return JS_TRUE;
   case JSTYPE_FUNCTION:
     // Leave this to NPObjectMember_Call.
     return JS_TRUE;
   default:
     NS_ERROR("illegal operation on JSObject prototype object");
     return JS_FALSE;
   }
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -41,16 +41,17 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = dom/plugins/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _MOCHITEST_FILES = \
   utils.js \
+  test_defaultValue.html \
   test_getauthenticationinfo.html \
   test_npobject_getters.html \
   test_npruntime_npnevaluate.html \
   test_npruntime_npninvoke.html \
   test_npruntime_npninvokedefault.html \
   test_npruntime_identifiers.html \
   npruntime_identifiers_subpage.html \
   loremipsum.txt \
new file mode 100644
--- /dev/null
+++ b/dom/plugins/test/mochitest/test_defaultValue.html
@@ -0,0 +1,36 @@
+<html>
+  <head>
+    <title>NPObject [[DefaultValue]] implementation</title>
+
+    <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  </head>
+
+  <body onload="run()">
+
+    <embed id="plugin" type="application/x-test" wmode="window"></embed>
+
+    <script class="testbody" type="application/javascript">
+      SimpleTest.waitForExplicitFinish();
+
+      function run() {
+        var plugin = document.getElementById("plugin");
+        var pluginProto = Object.getPrototypeOf(plugin);
+
+        plugin.propertyAndMethod = {};
+        plugin.propertyAndMethod + "baz";
+        ok(true, "|plugin.propertyAndMethod + \"baz\"| shouldn't assert");
+        pluginProto.propertyAndMethod = {};
+        pluginProto.propertyAndMethod + "quux";
+        ok(true, "|pluginProto.propertyAndMethod + \"quux\"| shouldn't assert");
+
+        plugin + "foo";
+        ok(true, "|plugin + \"foo\"| shouldn't assert");
+        pluginProto + "bar";
+        ok(true, "|pluginProto + \"bar\"| shouldn't assert");
+
+        SimpleTest.finish();
+      }
+    </script>
+  </body>
+</html>
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -142,18 +142,16 @@ ThebesLayerBufferOGL::RenderTo(const nsI
   }
 
   PRInt32 passes = mTexImageOnWhite ? 2 : 1;
   for (PRInt32 pass = 1; pass <= passes; ++pass) {
     LayerProgram *program;
 
     if (passes == 2) {
       ComponentAlphaTextureLayerProgram *alphaProgram;
-      NS_ASSERTION(!mTexImage->IsRGB() && !mTexImageOnWhite->IsRGB(),
-                   "Only BGR image surported with component alpha (currently!)");
       if (pass == 1) {
         alphaProgram = aManager->GetComponentAlphaPass1LayerProgram();
         gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_ONE_MINUS_SRC_COLOR,
                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
       } else {
         alphaProgram = aManager->GetComponentAlphaPass2LayerProgram();
         gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE,
                                  LOCAL_GL_ONE, LOCAL_GL_ONE);
--- a/gfx/thebes/GLContext.cpp
+++ b/gfx/thebes/GLContext.cpp
@@ -770,17 +770,16 @@ TiledTextureImage::DirectUpdate(gfxASurf
         if (tileRegion.IsEmpty())
             continue;
         tileRegion.MoveBy(-xPos, -yPos); // translate into tile local space
         result &= mImages[i]->DirectUpdate(aSurf,
                                            tileRegion,
                                            aFrom + nsIntPoint(xPos, yPos));
     }
     mShaderType = mImages[0]->GetShaderProgramType();
-    mIsRGBFormat = mImages[0]->IsRGB();
     mTextureState = Valid;
     return result;
 }
 
 void
 TiledTextureImage::GetUpdateRegion(nsIntRegion& aForRegion)
 {
     if (mTextureState != Valid) {
@@ -883,17 +882,16 @@ void
 TiledTextureImage::EndUpdate()
 {
     NS_ASSERTION(mInUpdate, "EndUpdate not in update");
     if (!mUpdateSurface) { // update was to a single TextureImage
         mImages[mCurrentImage]->EndUpdate();
         mInUpdate = PR_FALSE;
         mTextureState = Valid;
         mShaderType = mImages[mCurrentImage]->GetShaderProgramType();
-        mIsRGBFormat = mImages[mCurrentImage]->IsRGB();
         return;
     }
 
     // upload tiles from temp surface
     for (unsigned i = 0; i < mImages.Length(); i++) {
         int xPos = (i % mColumns) * mTileSize;
         int yPos = (i / mColumns) * mTileSize;
         nsIntRect imageRect = nsIntRect(nsIntPoint(xPos,yPos), mImages[i]->GetSize());
@@ -911,17 +909,16 @@ TiledTextureImage::EndUpdate()
         ctx->SetSource(mUpdateSurface, gfxPoint(-xPos, -yPos));
         ctx->Paint();
         mImages[i]->EndUpdate();
     }
 
     mUpdateSurface = nsnull;
     mInUpdate = PR_FALSE;
     mShaderType = mImages[0]->GetShaderProgramType();
-    mIsRGBFormat = mImages[0]->IsRGB();
     mTextureState = Valid;
 }
 
 void TiledTextureImage::BeginTileIteration()
 {
     mCurrentImage = 0;
 }
 
--- a/gfx/thebes/GLContext.h
+++ b/gfx/thebes/GLContext.h
@@ -316,18 +316,16 @@ public:
     virtual already_AddRefed<gfxASurface> GetBackingSurface()
     { return NULL; }
 
     const nsIntSize& GetSize() const { return mSize; }
     ContentType GetContentType() const { return mContentType; }
     virtual bool InUpdate() const = 0;
     GLenum GetWrapMode() const { return mWrapMode; }
 
-    bool IsRGB() const { return mIsRGBFormat; }
-
     void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
 
 protected:
     friend class GLContext;
 
     /**
      * After the ctor, the TextureImage is invalid.  Implementations
      * must allocate resources successfully before returning the new
@@ -335,29 +333,27 @@ protected:
      * clients must not be given partially-constructed TextureImages.
      */
     TextureImage(const nsIntSize& aSize,
                  GLenum aWrapMode, ContentType aContentType,
                  bool aIsRGB = false)
         : mSize(aSize)
         , mWrapMode(aWrapMode)
         , mContentType(aContentType)
-        , mIsRGBFormat(aIsRGB)
     {}
 
     /**
      * Applies this TextureImage's filter, assuming that its texture is
      * the currently bound texture.
      */
     virtual void ApplyFilter() = 0;
 
     nsIntSize mSize;
     GLenum mWrapMode;
     ContentType mContentType;
-    bool mIsRGBFormat;
     ShaderProgramType mShaderType;
     gfxPattern::GraphicsFilter mFilter;
 };
 
 /**
  * BasicTextureImage is the baseline TextureImage implementation ---
  * it updates its texture by allocating a scratch buffer for the
  * client to draw into, then using glTexSubImage2D() to upload the new
--- a/gfx/thebes/GLContextProviderEGL.cpp
+++ b/gfx/thebes/GLContextProviderEGL.cpp
@@ -1202,17 +1202,17 @@ public:
             }
             Resize(aSize);
         } else {
             // Convert RGB24 to either ARGB32 on mobile.  We can't
             // generate GL_RGB data, so we'll always have an alpha byte
             // for RGB24.  No easy way to upload that to GL.
             // 
             // Note that if we start using RGB565 here, we'll need to
-            // watch for a) setting mIsRGBFormat to TRUE; and b) getting
+            // watch for a) setting the correct format; and b) getting
             // the stride right.
             if (mUpdateFormat == gfxASurface::ImageFormatRGB24) {
                 mUpdateFormat = gfxASurface::ImageFormatARGB32;
             }
             // We currently always use BGRA type textures
             mShaderType = BGRALayerProgramType;
         }
     }
@@ -1270,19 +1270,16 @@ public:
                 mUpdateSurface = GetLockSurface();
             } else {
                 mUpdateSurface = mBackingSurface;
             }
 
             return mUpdateSurface;
         }
 
-        // if we get this far, then we're using Cairo's byte order
-        mIsRGBFormat = PR_FALSE;
-
         //printf_stderr("creating image surface %dx%d format %d\n", mUpdateRect.width, mUpdateRect.height, mUpdateFormat);
 
         mUpdateSurface =
             new gfxImageSurface(gfxIntSize(mUpdateRect.width, mUpdateRect.height),
                                 mUpdateFormat);
 
         mUpdateSurface->SetDeviceOffset(gfxPoint(-mUpdateRect.x, -mUpdateRect.y));
 
@@ -1641,17 +1638,16 @@ public:
 
             if (!BindTexImage()) {
                 printf_stderr("ProviderEGL Failed to bind teximage: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
                 return PR_FALSE;
             }
         }
 
         mBackingSurface = xsurface;
-        mIsRGBFormat = PR_TRUE;
 #endif
 
         return mBackingSurface != nsnull;
     }
 
 protected:
     typedef gfxASurface::gfxImageFormat ImageFormat;
 
--- a/gfx/thebes/gfx3DMatrix.cpp
+++ b/gfx/thebes/gfx3DMatrix.cpp
@@ -796,20 +796,31 @@ gfxRect gfx3DMatrix::ProjectRectBounds(c
     max_y = max(points[i].y, max_y);
   }
 
   return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
 }
 
 gfxPoint3D gfx3DMatrix::GetNormalVector() const
 {
-    // Define a plane in transformed space as the transformations
-    // of 3 points on the z=0 screen plane.
-    gfxPoint3D a = Transform3D(gfxPoint3D(0, 0, 0));
-    gfxPoint3D b = Transform3D(gfxPoint3D(0, 1, 0));
-    gfxPoint3D c = Transform3D(gfxPoint3D(1, 0, 0));
+  // Define a plane in transformed space as the transformations
+  // of 3 points on the z=0 screen plane.
+  gfxPoint3D a = Transform3D(gfxPoint3D(0, 0, 0));
+  gfxPoint3D b = Transform3D(gfxPoint3D(0, 1, 0));
+  gfxPoint3D c = Transform3D(gfxPoint3D(1, 0, 0));
+
+  // Convert to two vectors on the surface of the plane.
+  gfxPoint3D ab = b - a;
+  gfxPoint3D ac = c - a;
 
-    // Convert to two vectors on the surface of the plane.
-    gfxPoint3D ab = b - a;
-    gfxPoint3D ac = c - a;
+  return ac.CrossProduct(ab);
+}
 
-    return ac.CrossProduct(ab);
+bool gfx3DMatrix::IsBackfaceVisible() const
+{
+  // Inverse()._33 < 0;
+  gfxFloat det = Determinant();
+  float _33 = _12*_24*_41 - _14*_22*_41 +
+              _14*_21*_42 - _11*_24*_42 -
+              _12*_21*_44 + _11*_22*_44;
+  return (_33 * det) < 0;
 }
+
--- a/gfx/thebes/gfx3DMatrix.h
+++ b/gfx/thebes/gfx3DMatrix.h
@@ -302,16 +302,22 @@ public:
 
   /**
    * Returns a unit vector that is perpendicular to the plane formed
    * by transform the screen plane (z=0) by this matrix.
    */
   gfxPoint3D GetNormalVector() const;
 
   /**
+   * Returns true if a plane transformed by this matrix will
+   * have it's back face visible.
+   */
+  bool IsBackfaceVisible() const;
+
+  /**
    * Check if matrix is singular (no inverse exists).
    */
   bool IsSingular() const;
 
   /**
    * Create a translation matrix.
    *
    * \param aX Translation on X-axis.
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -204,17 +204,16 @@ 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 \
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -161,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
@@ -217,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/configure.in
+++ b/js/src/configure.in
@@ -4632,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/jsapi.h
+++ b/js/src/jsapi.h
@@ -1693,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)
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -1334,16 +1334,17 @@ DSTOffsetCache::DSTOffsetCache()
 }
 
 JSContext::JSContext(JSRuntime *rt)
   : defaultVersion(JSVERSION_DEFAULT),
     hasVersionOverride(false),
     throwing(false),
     exception(UndefinedValue()),
     runOptions(0),
+    reportGranularity(JS_DEFAULT_JITREPORT_GRANULARITY),
     localeCallbacks(NULL),
     resolvingList(NULL),
     generatingError(false),
 #if JS_STACK_GROWTH_DIRECTION > 0
     stackLimit((jsuword)-1),
 #else
     stackLimit(0),
 #endif
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -928,16 +928,18 @@ struct JSContext
     /* Exception state -- the exception member is a GC root by definition. */
     JSBool              throwing;           /* is there a pending exception? */
     js::Value           exception;          /* most-recently-thrown exception */
 
     /* Per-context run options. */
     uintN               runOptions;            /* see jsapi.h for JSOPTION_* */
 
   public:
+    int32               reportGranularity;  /* see jsprobes.h */
+
     /* Locale specific callbacks for string conversion. */
     JSLocaleCallbacks   *localeCallbacks;
 
     js::AutoResolving   *resolvingList;
 
     /*
      * True if generating an error, to prevent runaway recursion.
      * NB: generatingError packs with throwing below.
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -842,17 +842,22 @@ date_parseISOString(JSLinearString *str,
 
     if (PEEK('Z')) {
         ++i;
     } else if (PEEK('+') || PEEK('-')) {
         if (PEEK('-'))
             tzMul = -1;
         ++i;
         NEED_NDIGITS(2, tzHour);
-        NEED(':');
+        /*
+         * Non-standard extension to the ISO date format (permitted by ES5):
+         * allow "-0700" as a time zone offset, not just "-07:00".
+         */
+        if (PEEK(':'))
+          ++i;
         NEED_NDIGITS(2, tzMin);
     } else {
         isLocalTime = JS_TRUE;
     }
 
  done:
     if (year > 275943 // ceil(1e8/365) + 1970
         || (month == 0 || month > 12)
--- a/js/src/jslock.cpp
+++ b/js/src/jslock.cpp
@@ -32,33 +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 "jsapi.h"
+#include "jspubtd.h"
+#include "jstypes.h"
+
 #ifdef JS_THREADSAFE
 
 /*
  * JS locking stubs.
  */
 #include <stdlib.h>
 #include <string.h>
 
 #ifdef XP_WIN
 # include "jswin.h"
 #else
 # include <unistd.h>
 #endif
 
-#include "jspubtd.h"
 #include "jsutil.h"
-#include "jstypes.h"
 #include "jsstdint.h"
 #include "jscntxt.h"
 #include "jsgc.h"
 #include "jslock.h"
 #include "jsscope.h"
 #include "jsstr.h"
 
 using namespace js;
@@ -757,9 +759,33 @@ js_UnlockRuntime(JSRuntime *rt)
 
 #ifdef DEBUG
 JSBool
 js_IsRuntimeLocked(JSRuntime *rt)
 {
     return js_CurrentThreadId() == rt->rtLockOwner;
 }
 #endif /* DEBUG */
+
+static PRStatus
+CallOnce(void *func)
+{
+    JSInitCallback init = JS_DATA_TO_FUNC_PTR(JSInitCallback, func);
+    return init() ? PR_FAILURE : PR_SUCCESS;
+}
+
+JS_PUBLIC_API(JSBool)
+JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
+{
+    return PR_CallOnceWithArg(once, CallOnce, JS_FUNC_TO_DATA_PTR(void *, func)) == PR_SUCCESS;
+}
+#else /* JS_THREADSAFE */
+JS_PUBLIC_API(JSBool)
+JS_CallOnce(JSCallOnceType *once, JSInitCallback func)
+{
+    if (!*once) {
+        *once = true;
+        return func();
+    } else {
+        return JS_TRUE;
+    }
+}
 #endif /* JS_THREADSAFE */
--- a/js/src/jslock.h
+++ b/js/src/jslock.h
@@ -43,16 +43,17 @@
 #include "jsapi.h"
 #include "jsprvtd.h"
 
 #ifdef JS_THREADSAFE
 # include "pratom.h"
 # include "prlock.h"
 # include "prcvar.h"
 # include "prthread.h"
+# include "prinit.h"
 #endif
 
 #ifdef JS_THREADSAFE
 
 #if (defined(_WIN32) && defined(_M_IX86)) ||                                  \
     (defined(_WIN64) && (defined(_M_AMD64) || defined(_M_X64))) ||            \
     (defined(__i386) && (defined(__GNUC__) || defined(__SUNPRO_CC))) ||       \
     (defined(__x86_64) && (defined(__GNUC__) || defined(__SUNPRO_CC))) ||     \
--- a/js/src/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/jsprobes.cpp
+++ b/js/src/jsprobes.cpp
@@ -60,16 +60,158 @@
 
 using namespace js;
 
 const char Probes::nullName[] = "(null)";
 const char Probes::anonymousName[] = "(anonymous)";
 
 bool Probes::ProfilingActive = true;
 
+static Vector<Probes::JITWatcher*, 4, SystemAllocPolicy> jitWatchers;
+
+bool
+Probes::addJITWatcher(JITWatcher *watcher)
+{
+    return jitWatchers.append(watcher);
+}
+
+bool
+Probes::removeJITWatcher(JSRuntime *rt, JITWatcher *watcher)
+{
+    JITWatcher **place = Find(jitWatchers, watcher);
+    if (!place)
+        return false;
+    if (rt)
+        rt->delete_(*place);
+    else
+        Foreground::delete_(*place);
+    jitWatchers.erase(place);
+    return true;
+}
+
+void
+Probes::removeAllJITWatchers(JSRuntime *rt)
+{
+    if (rt) {
+        for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+            rt->delete_(*p);
+    } else {
+        for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+            Foreground::delete_(*p);
+    }
+    jitWatchers.clear();
+}
+
+Probes::JITReportGranularity
+Probes::JITGranularityRequested()
+{
+    JITReportGranularity want = JITREPORT_GRANULARITY_NONE;
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p) {
+        JITReportGranularity request = (*p)->granularityRequested();
+        if (request > want)
+            want = request;
+    }
+
+    return want;
+}
+
+#ifdef JS_METHODJIT
+void
+Probes::registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
+                         JSScript *script, JSFunction *fun,
+                         js::mjit::Compiler_ActiveFrame **inlineFrames,
+                         void *mainCodeAddress, size_t mainCodeSize,
+                         void *stubCodeAddress, size_t stubCodeSize)
+{
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+        (*p)->registerMJITCode(cx, jscr, script, fun,
+                               inlineFrames,
+                               mainCodeAddress, mainCodeSize,
+                               stubCodeAddress, stubCodeSize);
+}
+
+void
+Probes::discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script, void* address)
+{
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+        (*p)->discardMJITCode(cx, jscr, script, address);
+}
+
+void
+Probes::registerICCode(JSContext *cx,
+                       mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
+                       void *start, size_t size)
+{
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+        (*p)->registerICCode(cx, jscr, script, pc, start, size);
+}
+#endif
+
+/* ICs are unregistered in a batch */
+void
+Probes::discardExecutableRegion(void *start, size_t size)
+{
+    for (JITWatcher **p = jitWatchers.begin(); p != jitWatchers.end(); ++p)
+        (*p)->discardExecutableRegion(start, size);
+}
+
+static JSRuntime *initRuntime;
+
+JSBool
+Probes::startEngine()
+{
+    bool ok = true;
+
+    return ok;
+}
+
+bool
+Probes::createRuntime(JSRuntime *rt)
+{
+    bool ok = true;
+
+    static JSCallOnceType once = { 0 };
+    initRuntime = rt;
+    if (!JS_CallOnce(&once, Probes::startEngine))
+        ok = false;
+
+#ifdef MOZ_ETW
+    if (!ETWCreateRuntime(rt))
+        ok = false;
+#endif
+
+    return ok;
+}
+
+bool
+Probes::destroyRuntime(JSRuntime *rt)
+{
+    bool ok = true;
+#ifdef MOZ_ETW
+    if (!ETWDestroyRuntime(rt))
+        ok = false;
+#endif
+
+    return ok;
+}
+
+bool
+Probes::shutdown()
+{
+    bool ok = true;
+#ifdef MOZ_ETW
+    if (!ETWShutdown())
+        ok = false;
+#endif
+
+    Probes::removeAllJITWatchers(NULL);
+
+    return ok;
+}
+
 #ifdef INCLUDE_MOZILLA_DTRACE
 static const char *
 ScriptFilename(const JSScript *script)
 {
     if (!script)
         return Probes::nullName;
     if (!script->filename)
         return Probes::anonymousName;
--- a/js/src/jsprobes.h
+++ b/js/src/jsprobes.h
@@ -40,19 +40,26 @@
 #ifndef _JSPROBES_H
 #define _JSPROBES_H
 
 #ifdef INCLUDE_MOZILLA_DTRACE
 #include "javascript-trace.h"
 #endif
 #include "jspubtd.h"
 #include "jsprvtd.h"
+#include "jsscript.h"
+#include "jsobj.h"
 
 namespace js {
 
+namespace mjit {
+struct NativeAddressInfo;
+struct Compiler_ActiveFrame;
+}
+
 namespace Probes {
 
 /*
  * Static probes
  *
  * The probe points defined in this file are scattered around the SpiderMonkey
  * source tree. The presence of Probes::someEvent() means that someEvent is
  * about to happen or has happened. To the extent possible, probes should be
@@ -80,32 +87,41 @@ namespace Probes {
  * Internal use only: remember whether "profiling", whatever that means, is
  * currently active. Used for state management.
  */
 extern bool ProfilingActive;
 
 extern const char nullName[];
 extern const char anonymousName[];
 
+/* Called when first runtime is created for this process */
+JSBool startEngine();
+
 /* JSRuntime created, with currently valid fields */
 bool createRuntime(JSRuntime *rt);
 
 /* JSRuntime about to be destroyed */
 bool destroyRuntime(JSRuntime *rt);
 
 /* Total JS engine shutdown */
 bool shutdown();
 
 /*
  * Test whether we are tracking JS function call enter/exit. The JITs use this
  * to decide whether they can optimize in a way that would prevent probes from
  * firing.
  */
 bool callTrackingActive(JSContext *);
 
+/*
+ * Test whether anything is looking for JIT native code registration events.
+ * This information will not be collected otherwise.
+ */
+bool wantNativeAddressInfo(JSContext *);
+
 /* Entering a JS function */
 bool enterJSFun(JSContext *, JSFunction *, JSScript *, int counter = 1);
 
 /* About to leave a JS function */
 bool exitJSFun(JSContext *, JSFunction *, JSScript *, int counter = 0);
 
 /* Executing a script */
 bool startExecution(JSContext *cx, JSScript *script);
@@ -190,16 +206,111 @@ bool GCEndSweepPhase(JSCompartment *comp
  * application-meaningful events and phases of execution.
  *
  * Not all backends support these.
  */
 bool CustomMark(JSString *string);
 bool CustomMark(const char *string);
 bool CustomMark(int marker);
 
+/* JIT code observation */
+
+enum JITReportGranularity {
+    JITREPORT_GRANULARITY_NONE = 0,
+    JITREPORT_GRANULARITY_FUNCTION = 1,
+    JITREPORT_GRANULARITY_LINE = 2,
+    JITREPORT_GRANULARITY_OP = 3
+};
+
+/*
+ * Observer class for JIT code allocation/deallocation. Currently, this only
+ * handles the method JIT, and does not get notifications when JIT code is
+ * changed (patched) with no new allocation.
+ */
+class JITWatcher {
+public:
+    virtual JITReportGranularity granularityRequested() = 0;
+
+#ifdef JS_METHODJIT
+    virtual void registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
+                                  JSScript *script, JSFunction *fun,
+                                  mjit::Compiler_ActiveFrame** inlineFrames,
+                                  void *mainCodeAddress, size_t mainCodeSize,
+                                  void *stubCodeAddress, size_t stubCodeSize) = 0;
+
+    virtual void discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script,
+                                 void* address) = 0;
+
+    virtual void registerICCode(JSContext *cx,
+                                js::mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
+                                void *start, size_t size) = 0;
+#endif
+
+    virtual void discardExecutableRegion(void *start, size_t size) = 0;
+};
+
+/*
+ * Register a JITWatcher subclass to be informed of JIT code
+ * allocation/deallocation.
+ */
+bool
+addJITWatcher(JITWatcher *watcher);
+
+/*
+ * Remove (and destroy) a registered JITWatcher. rt may be NULL. Returns false
+ * if the watcher is not found.
+ */
+bool
+removeJITWatcher(JSRuntime *rt, JITWatcher *watcher);
+
+/*
+ * Remove (and destroy) all registered JITWatchers. rt may be NULL.
+ */
+void
+removeAllJITWatchers(JSRuntime *rt);
+
+/*
+ * Finest granularity of JIT information desired by all watchers.
+ */
+JITReportGranularity
+JITGranularityRequested();
+
+#ifdef JS_METHODJIT
+/*
+ * New method JIT code has been created
+ */
+void
+registerMJITCode(JSContext *cx, js::mjit::JITScript *jscr,
+                 JSScript *script, JSFunction *fun,
+                 mjit::Compiler_ActiveFrame** inlineFrames,
+                 void *mainCodeAddress, size_t mainCodeSize,
+                 void *stubCodeAddress, size_t stubCodeSize);
+
+/*
+ * Method JIT code is about to be discarded
+ */
+void
+discardMJITCode(JSContext *cx, mjit::JITScript *jscr, JSScript *script, void* address);
+
+/*
+ * IC code has been allocated within the given JITScript
+ */
+void
+registerICCode(JSContext *cx,
+               mjit::JITScript *jscr, JSScript *script, jsbytecode* pc,
+               void *start, size_t size);
+#endif /* JS_METHODJIT */
+
+/*
+ * A whole region of code has been deallocated, containing any number of ICs.
+ * (ICs are unregistered in a batch, so individual ICs are not registered.)
+ */
+void
+discardExecutableRegion(void *start, size_t size);
+
 /*
  * Internal: DTrace-specific functions to be called during Probes::enterJSFun
  * and Probes::exitJSFun. These will not be inlined, but the argument
  * marshalling required for these probe points is expensive enough that it
  * shouldn't really matter.
  */
 void DTraceEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
 void DTraceExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script);
@@ -238,54 +349,21 @@ bool ETWCustomMark(int marker);
 bool ETWStartExecution(JSContext *cx, JSScript *script);
 bool ETWStopExecution(JSContext *cx, JSScript *script);
 bool ETWResizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize);
 #endif
 
 } /* namespace Probes */
 
 /*
- * Probe handlers are implemented inline for minimal performance impact,
+ * Many probe handlers are implemented inline for minimal performance impact,
  * especially important when no backends are enabled.
  */
 
 inline bool
-Probes::createRuntime(JSRuntime *rt)
-{
-    bool ok = true;
-#ifdef MOZ_ETW
-    if (!ETWCreateRuntime(rt))
-        ok = false;
-#endif
-    return ok;
-}
-
-inline bool
-Probes::destroyRuntime(JSRuntime *rt)
-{
-    bool ok = true;
-#ifdef MOZ_ETW
-    if (!ETWDestroyRuntime(rt))
-        ok = false;
-#endif
-    return ok;
-}
-
-inline bool
-Probes::shutdown()
-{
-    bool ok = true;
-#ifdef MOZ_ETW
-    if (!ETWShutdown())
-        ok = false;
-#endif
-    return ok;
-}
-
-inline bool
 Probes::callTrackingActive(JSContext *cx)
 {
 #ifdef INCLUDE_MOZILLA_DTRACE
     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED() || JAVASCRIPT_FUNCTION_RETURN_ENABLED())
         return true;
 #endif
 #ifdef MOZ_TRACE_JSCALLS
     if (cx->functionCallback)
@@ -294,16 +372,23 @@ Probes::callTrackingActive(JSContext *cx
 #ifdef MOZ_ETW
     if (ProfilingActive && ETWCallTrackingActive(cx))
         return true;
 #endif
     return false;
 }
 
 inline bool
+Probes::wantNativeAddressInfo(JSContext *cx)
+{
+    return (cx->reportGranularity >= JITREPORT_GRANULARITY_FUNCTION &&
+            JITGranularityRequested() >= JITREPORT_GRANULARITY_FUNCTION);
+}
+
+inline bool
 Probes::enterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
 {
     bool ok = true;
 #ifdef INCLUDE_MOZILLA_DTRACE
     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
         DTraceEnterJSFun(cx, fun, script);
 #endif
 #ifdef MOZ_TRACE_JSCALLS
--- a/js/src/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/methodjit/BaseCompiler.h
+++ b/js/src/methodjit/BaseCompiler.h
@@ -143,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;
@@ -4312,18 +4377,18 @@ mjit::Compiler::jsop_getprop(JSAtom *ato
                 stubcc.linkExit(notObject, Uses(1));
                 stubcc.leave();
                 OOL_STUBCALL(stubs::GetProp, rejoin);
                 if (rejoin == REJOIN_GETTER)
                     testPushedType(rejoin, -1);
             }
             RegisterID reg = frame.copyDataIntoReg(top);
             frame.pop();
-            frame.pushWord(Address(reg, TypedArray::lengthOffset()), JSVAL_TYPE_INT32);
-            frame.freeReg(reg);
+            masm.loadPayload(Address(reg, TypedArray::lengthOffset()), reg);
+            frame.pushTypedPayload(JSVAL_TYPE_INT32, reg);
             if (!isObject)
                 stubcc.rejoin(Changes(1));
             return true;
         }
 
         /*
          * Check if we are accessing the 'length' of the lazy arguments for the
          * current frame. No actual arguments object has ever been constructed
@@ -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
@@ -385,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;
@@ -418,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/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 lval");
     if (!idval.isInt32())
-        return disable(cx, "non-int32 key");
+        return disable(f.cx, "non-int32 key");
 
     JSObject *obj = &objval.toObject();
     int32 key = idval.toInt32();
 
     if (obj->isDenseArray())
-        return attachHoleStub(cx, obj, key);
+        return attachHoleStub(f, obj, key);
 
 #if defined JS_METHODJIT_TYPED_ARRAY
     /* Not attaching typed array stubs with linear scan allocator, see GetElementIC. */
-    if (!cx->typeInferenceEnabled() && js_IsTypedArray(obj))
-        return attachTypedArray(cx, obj, key);
+    if (!f.cx->typeInferenceEnabled() && js_IsTypedArray(obj))
+        return attachTypedArray(f, obj, key);
 #endif
 
-    return disable(cx, "unsupported object type");
+    return disable(f.cx, "unsupported object type");
 }
 
 template<JSBool strict>
 void JS_FASTCALL
 ic::SetElement(VMFrame &f, ic::SetElementIC *ic)
 {
     JSContext *cx = f.cx;
 
     if (ic->shouldUpdate(cx)) {
-        LookupStatus status = ic->update(cx, f.regs.sp[-3], f.regs.sp[-2]);
+        LookupStatus status = ic->update(f, f.regs.sp[-3], f.regs.sp[-2]);
         if (status == Lookup_Error)
             THROW();
     }
 
     stubs::SetElem<strict>(f);
 }
 
 template void JS_FASTCALL ic::SetElement<true>(VMFrame &f, SetElementIC *ic);
--- a/js/src/methodjit/PolyIC.h
+++ b/js/src/methodjit/PolyIC.h
@@ -295,23 +295,20 @@ struct GetElementIC : public BasePolyIC 
     void reset() {
         BasePolyIC::reset();
         inlineTypeGuardPatched = false;
         inlineClaspGuardPatched = false;
         typeRegHasBaseShape = false;
         hasLastStringStub = false;
     }
     void purge(Repatcher &repatcher);
-    LookupStatus update(VMFrame &f, JSContext *cx, JSObject *obj, const Value &v, jsid id, Value *vp);
-    LookupStatus attachGetProp(VMFrame &f, JSContext *cx, JSObject *obj, const Value &v, jsid id,
-                               Value *vp);
-    LookupStatus attachArguments(JSContext *cx, JSObject *obj, const Value &v, jsid id,
-                               Value *vp);
-    LookupStatus attachTypedArray(JSContext *cx, JSObject *obj, const Value &v, jsid id,
-                                  Value *vp);
+    LookupStatus update(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp);
+    LookupStatus attachGetProp(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp);
+    LookupStatus attachArguments(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp);
+    LookupStatus attachTypedArray(VMFrame &f, JSObject *obj, const Value &v, jsid id, Value *vp);
     LookupStatus disable(JSContext *cx, const char *reason);
     LookupStatus error(JSContext *cx);
     bool shouldUpdate(JSContext *cx);
 };
 
 struct SetElementIC : public BaseIC {
     SetElementIC() : execPool(NULL) { reset(); }
     ~SetElementIC() {
@@ -365,19 +362,19 @@ struct SetElementIC : public BaseIC {
         BaseIC::reset();
         if (execPool != NULL)
             execPool->release();
         execPool = NULL;
         inlineClaspGuardPatched = false;
         inlineHoleGuardPatched = false;
     }
     void purge(Repatcher &repatcher);
-    LookupStatus attachTypedArray(JSContext *cx, JSObject *obj, int32 key);
-    LookupStatus attachHoleStub(JSContext *cx, JSObject *obj, int32 key);
-    LookupStatus update(JSContext *cx, const Value &objval, const Value &idval);
+    LookupStatus attachTypedArray(VMFrame &f, JSObject *obj, int32 key);
+    LookupStatus attachHoleStub(VMFrame &f, JSObject *obj, int32 key);
+    LookupStatus update(VMFrame &f, const Value &objval, const Value &idval);
     LookupStatus disable(JSContext *cx, const char *reason);
     LookupStatus error(JSContext *cx);
 };
 
 struct PICInfo : public BasePolyIC {
     PICInfo() { reset(); }
 
     // Operation this is a PIC for.
--- a/js/src/tests/ecma_5/JSON/jstests.list
+++ b/js/src/tests/ecma_5/JSON/jstests.list
@@ -19,16 +19,17 @@ script stringify-call-replacer-once.js
 script stringify-call-toJSON-once.js
 script stringify-dropping-elements.js
 script stringify-gap.js
 script stringify-ignore-noncallable-toJSON.js
 script stringify-missing-arguments.js
 script stringify-nonarray-noncallable-replacer.js
 script stringify-primitives.js
 script stringify-replacer.js
+script stringify-replacer-array-boxed-elements.js
 script stringify-replacer-array-duplicated-element.js
 script stringify-replacer-array-edgecase-jsid-elements.js
 script stringify-replacer-array-hijinks.js
 script stringify-replacer-array-skipped-element.js
 script stringify-replacer-with-array-indexes.js
 script stringify-special-escapes.js
 script stringify-toJSON-arguments.js
 script trailing-comma.js
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/JSON/stringify-replacer-array-boxed-elements.js
@@ -0,0 +1,60 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+var gTestfile = 'stringify-replacer-array-boxed-elements.js';
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 648471;
+var summary = "Boxed-string/number objects in replacer arrays";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var S = new String(3);
+var N = new Number(4);
+
+assertEq(JSON.stringify({ 3: 3, 4: 4 }, [S]),
+         '{"3":3}');
+assertEq(JSON.stringify({ 3: 3, 4: 4 }, [N]),
+         '{"4":4}');
+
+Number.prototype.toString = function() { return 3; };
+assertEq(JSON.stringify({ 3: 3, 4: 4 }, [N]),
+         '{"3":3}');
+
+String.prototype.toString = function() { return 4; };
+assertEq(JSON.stringify({ 3: 3, 4: 4 }, [S]),
+         '{"4":4}');
+
+Number.prototype.toString = function() { return new String(42); };
+assertEq(JSON.stringify({ 3: 3, 4: 4 }, [N]),
+         '{"4":4}');
+
+String.prototype.toString = function() { return new Number(17); };
+assertEq(JSON.stringify({ 3: 3, 4: 4 }, [S]),
+         '{"3":3}');
+
+Number.prototype.toString = null;
+assertEq(JSON.stringify({ 3: 3, 4: 4 }, [N]),
+         '{"4":4}');
+
+String.prototype.toString = null;
+assertEq(JSON.stringify({ 3: 3, 4: 4 }, [S]),
+         '{"3":3}');
+
+Number.prototype.valueOf = function() { return 17; };
+assertEq(JSON.stringify({ 4: 4, 17: 17 }, [N]),
+         '{"17":17}');
+
+String.prototype.valueOf = function() { return 42; };
+assertEq(JSON.stringify({ 3: 3, 42: 42 }, [S]),
+         '{"42":42}');
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("Tests complete");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/extensions/15.9.4.2.js
@@ -0,0 +1,91 @@
+/* -*- 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 JavaScript Engine testing utilities.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): Bruce Hoult
+ *
+ * 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 ***** */
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 682754;
+
+
+//-----------------------------------------------------------------------------
+test();
+//-----------------------------------------------------------------------------
+
+function iso(d)
+{
+  return new Date(d).toISOString();
+}
+
+function check(s, millis){
+  description = "Date.parse('"+s+"') == '"+iso(millis)+"'";
+  expected = millis;
+  actual = Date.parse(s);
+  reportCompare(expected, actual, description);
+}
+
+function checkInvalid(s)
+{
+  description = "Date.parse('"+s+"') produces invalid date";
+  expected = NaN;
+  actual = Date.parse(s);
+  reportCompare(expected, actual, description);
+}
+
+function dd(year, month, day, hour, minute, second, millis){
+  return Date.UTC(year, month-1, day, hour, minute, second, millis);
+}
+
+function TZAtDate(d){
+  return d.getTimezoneOffset() * 60000;
+}
+
+function TZInMonth(month){
+  return TZAtDate(new Date(dd(2009,month,1,0,0,0,0)));
+}
+
+function test()
+{
+  enterFunc ('test');
+  printBugNumber(BUGNUMBER);
+
+  JanTZ = TZInMonth(1);
+  JulTZ = TZInMonth(7);
+  CurrTZ = TZAtDate(new Date());
+
+  // Allow non-standard "-0700" as timezone, not just "-07:00"
+  check("2009-07-23T00:53:21.001-0700", dd(2009,7,23,7,53,21,1));
+
+  exitFunc ('test');
+}
--- a/js/src/tests/ecma_5/extensions/jstests.list
+++ b/js/src/tests/ecma_5/extensions/jstests.list
@@ -1,11 +1,12 @@
 url-prefix ../../jsreftest.html?test=ecma_5/extensions/
 fails-if(Android) script 8.12.5-01.js
 script 15.4.4.11.js
+script 15.9.4.2.js
 script Boolean-toSource.js
 script Number-toSource.js
 script Object-keys-and-object-ids.js
 script String-toSource.js
 script bug352085.js
 script bug472534.js
 script bug496985.js
 script bug566661.js
--- a/js/src/tests/user.js
+++ b/js/src/tests/user.js
@@ -22,17 +22,17 @@ user_pref("security.warn_leaving_secure"
 user_pref("security.warn_submit_insecure", false);
 user_pref("security.warn_viewing_mixed", false);
 user_pref("signed.applets.codebase_principal_support", true);
 user_pref("browser.warnOnQuit", false);
 user_pref("browser.cache.check_doc_frequency", 1);
 user_pref("extensions.checkCompatibility", false);
 user_pref("extensions.checkUpdateSecurity", false);
 user_pref("browser.EULA.override", true);
-user_pref("javascript.options.tracejit.chrome", true);
-user_pref("javascript.options.tracejit.content", true);
+user_pref("javascript.options.tracejit.chrome", false);
+user_pref("javascript.options.tracejit.content", false);
 user_pref("javascript.options.methodjit.chrome", true);
 user_pref("javascript.options.methodjit.content", true);
 user_pref("javascript.options.jitprofiling.chrome", true);
 user_pref("javascript.options.jitprofiling.content", true);
 user_pref("javascript.options.methodjit_always", false);
 user_pref("javascript.options.strict", false);
 user_pref("javascript.options.werror", false);
--- a/js/src/xpconnect/src/dombindingsgen.py
+++ b/js/src/xpconnect/src/dombindingsgen.py
@@ -532,16 +532,18 @@ listTemplateFooter = (
 "${name}Wrapper::Properties ${name}Wrapper::sProtoProperties[] = {\n"
 "${properties}\n"
 "};\n"
 "\n""template<>\n"
 "${name}Wrapper::Methods ${name}Wrapper::sProtoMethods[] = {\n"
 "${methods}\n"
 "};\n"
 "\n"
+"template class ListBase<${name}Class>;\n"
+"\n"
 "JSObject*\n"
 "${name}::create(JSContext *cx, XPCWrappedNativeScope *scope, ${nativeClass} *list, nsWrapperCache *cache, bool *triedToWrap)\n"
 "{\n"
 "    return ${name}Wrapper::create(cx, scope, list, cache, triedToWrap);\n"
 "}\n"
 "\n"
 "bool\n"
 "${name}::objIsWrapper(JSObject *obj)\n"
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -736,24 +736,26 @@ void nsDisplayList::HitTest(nsDisplayLis
       nsAutoTArray<nsIFrame*, 16> outFrames;
       item->HitTest(aBuilder, aRect, aState, &outFrames);
       
       // For 3d transforms with preserve-3d we add hit frames into the temp list 
       // so we can sort them later, otherwise we add them directly to the output list.
       nsTArray<nsIFrame*> *writeFrames = aOutFrames;
       if (item->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
           item->GetUnderlyingFrame()->Preserves3D()) {
-        nsDisplayTransform *transform = static_cast<nsDisplayTransform*>(item);
-        nsPoint point = aRect.TopLeft();
-        // A 1x1 rect means a point, otherwise use the center of the rect
-        if (aRect.width != 1 || aRect.height != 1) {
-          point = aRect.Center();
+        if (outFrames.Length()) {
+          nsDisplayTransform *transform = static_cast<nsDisplayTransform*>(item);
+          nsPoint point = aRect.TopLeft();
+          // A 1x1 rect means a point, otherwise use the center of the rect
+          if (aRect.width != 1 || aRect.height != 1) {
+            point = aRect.Center();
+          }
+          temp.AppendElement(FramesWithDepth(transform->GetHitDepthAtPoint(point)));
+          writeFrames = &temp[temp.Length() - 1].mFrames;
         }
-        temp.AppendElement(FramesWithDepth(transform->GetHitDepthAtPoint(point)));
-        writeFrames = &temp[temp.Length() - 1].mFrames;
       } else {
         // We may have just finished a run of consecutive preserve-3d transforms, 
         // so flush these into the destination array before processing our frame list.
         FlushFramesArray(temp, aOutFrames);
       }
 
       for (PRUint32 j = 0; j < outFrames.Length(); j++) {
         nsIFrame *f = outFrames.ElementAt(j);
@@ -2540,16 +2542,29 @@ nsDisplayTransform::GetResultingTransfor
                                                        aFactor, nsnull, aOutAncestor);
       return nsLayoutUtils::ChangeMatrixBasis(newOrigin + toMozOrigin, result) * parent;
   }
 
   return nsLayoutUtils::ChangeMatrixBasis
     (newOrigin + toMozOrigin, result);
 }
 
+/* If the matrix is singular, or a hidden backface is shown, the frame won't be visible or hit. */
+static bool IsFrameVisible(nsIFrame* aFrame, const gfx3DMatrix& aMatrix) 
+{
+  if (aMatrix.IsSingular()) {
+    return false;
+  }
+  if (aFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN &&
+      aMatrix.IsBackfaceVisible()) {
+    return false;
+  }
+  return true;
+}
+
 const gfx3DMatrix&
 nsDisplayTransform::GetTransform(float aFactor)
 {
   if (mTransform.IsIdentity() || mCachedFactor != aFactor) {
     mTransform =
       GetResultingTransformMatrix(mFrame, ToReferenceFrame(),
                                   aFactor,
                                   nsnull);
@@ -2560,19 +2575,17 @@ nsDisplayTransform::GetTransform(float a
 
 already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBuilder,
                                                        LayerManager *aManager,
                                                        const ContainerParameters& aContainerParameters)
 {
   const gfx3DMatrix& newTransformMatrix = 
     GetTransform(mFrame->PresContext()->AppUnitsPerDevPixel());
 
-  if (newTransformMatrix.IsSingular() ||
-      (mFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN &&
-       newTransformMatrix.GetNormalVector().z <= 0.0)) {
+  if (!IsFrameVisible(mFrame, newTransformMatrix)) {
     return nsnull;
   }
 
   nsRefPtr<ContainerLayer> container = aBuilder->LayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetList(),
                            aContainerParameters, &newTransformMatrix);
 
   // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags,
@@ -2639,21 +2652,18 @@ void nsDisplayTransform::HitTest(nsDispl
    *    anything).
    * 2. Invert the matrix.
    * 3. Use it to transform the rect into the correct space.
    * 4. Pass that rect down through to the list's version of HitTest.
    */
   float factor = nsPresContext::AppUnitsPerCSSPixel();
   gfx3DMatrix matrix = GetTransform(factor);
 
-  /* If the matrix is singular, or a hidden backface is shown, we didn't hit anything. */
-  if (matrix.IsSingular() ||
-      (mFrame->GetStyleDisplay()->mBackfaceVisibility == NS_STYLE_BACKFACE_VISIBILITY_HIDDEN &&
-       matrix.GetNormalVector().z <= 0.0)) {
-          return;
+  if (!IsFrameVisible(mFrame, matrix)) {
+    return;
   }
 
   /* We want to go from transformed-space to regular space.
    * Thus we have to invert the matrix, which normally does
    * the reverse operation (e.g. regular->transformed)
    */
 
   /* Now, apply the transform and pass it down the channel. */
@@ -2701,19 +2711,17 @@ void nsDisplayTransform::HitTest(nsDispl
 }
 
 float
 nsDisplayTransform::GetHitDepthAtPoint(const nsPoint& aPoint)
 {
   float factor = nsPresContext::AppUnitsPerCSSPixel();
   gfx3DMatrix matrix = GetTransform(factor);
 
-  NS_ASSERTION(!matrix.IsSingular(), "We can't have hit a singular matrix!");
-  NS_ASSERTION(mFrame->GetStyleDisplay()->mBackfaceVisibility != NS_STYLE_BACKFACE_VISIBILITY_HIDDEN || 
-               matrix.GetNormalVector().z > 0.0, "We can't have hit the hidden backface of a layer!");
+  NS_ASSERTION(IsFrameVisible(mFrame, matrix), "We can't have hit a frame that isn't visible!");
     
   gfxPoint point = 
     matrix.Inverse().ProjectPoint(gfxPoint(NSAppUnitsToFloatPixels(aPoint.x, factor),
                                            NSAppUnitsToFloatPixels(aPoint.y, factor)));
 
   gfxPoint3D transformed = matrix.Transform3D(gfxPoint3D(point.x, point.y, 0));
   return transformed.z;
 }
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -113,30 +113,33 @@
 
 // Needed for Start/Stop of Image Animation
 #include "imgIContainer.h"
 #include "nsIImageLoadingContent.h"
 
 //needed for resetting of image service color
 #include "nsLayoutCID.h"
 
+#include "nsCSSParser.h"
+
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static nscolor
-MakeColorPref(const nsCString& aColor)
+MakeColorPref(const nsString& aColor)
 {
-  PRUint32 red, green, blue;
-  nscolor colorref;
-
-  // 4.x stored RGB color values as a string rather than as an int,
-  // thus we need to do this conversion
-  PR_sscanf(aColor.get(), "#%02x%02x%02x", &red, &green, &blue);
-  colorref = NS_RGB(red, green, blue);
-  return colorref;
+  nscolor color;
+  nsCSSParser parser;
+  nsresult rv =
+    parser.ParseColorString(aColor, nsnull, 0, &color);
+  if (NS_FAILED(rv)) {
+    // Any better choices?
+    color = NS_RGB(0, 0, 0);
+  }
+  return color;
 }
 
 int
 nsPresContext::PrefChangedCallback(const char* aPrefName, void* instance_data)
 {
   nsPresContext*  presContext = (nsPresContext*)instance_data;
 
   NS_ASSERTION(nsnull != presContext, "bad instance data");
@@ -596,24 +599,24 @@ nsPresContext::GetDocumentColorPreferenc
 
   }
   if (usePrefColors) {
     usePrefColors =
       !Preferences::GetBool("browser.display.use_system_colors", false);
   }
 
   if (usePrefColors) {
-    nsAdoptingCString colorStr =
-      Preferences::GetCString("browser.display.foreground_color");
+    nsAdoptingString colorStr =
+      Preferences::GetString("browser.display.foreground_color");
 
     if (!colorStr.IsEmpty()) {
       mDefaultColor = MakeColorPref(colorStr);
     }
 
-    colorStr = Preferences::GetCString("browser.display.background_color");
+    colorStr = Preferences::GetString("browser.display.background_color");
 
     if (!colorStr.IsEmpty()) {
       mBackgroundColor = MakeColorPref(colorStr);
     }
   }
   else {
     mDefaultColor =
       LookAndFeel::GetColor(LookAndFeel::eColorID_WindowForeground,
@@ -651,47 +654,47 @@ nsPresContext::GetUserPreferences()
   mSendAfterPaintToContent =
     Preferences::GetBool("dom.send_after_paint_to_content",
                          mSendAfterPaintToContent);
 
   // * link colors
   mUnderlineLinks =
     Preferences::GetBool("browser.underline_anchors", mUnderlineLinks);
 
-  nsAdoptingCString colorStr = Preferences::GetCString("browser.anchor_color");
+  nsAdoptingString colorStr = Preferences::GetString("browser.anchor_color");
 
   if (!colorStr.IsEmpty()) {
     mLinkColor = MakeColorPref(colorStr);
   }
 
-  colorStr = Preferences::GetCString("browser.active_color");
+  colorStr = Preferences::GetString("browser.active_color");
 
   if (!colorStr.IsEmpty()) {
     mActiveLinkColor = MakeColorPref(colorStr);
   }
 
-  colorStr = Preferences::GetCString("browser.visited_color");
+  colorStr = Preferences::GetString("browser.visited_color");
 
   if (!colorStr.IsEmpty()) {
     mVisitedLinkColor = MakeColorPref(colorStr);
   }
 
   mUseFocusColors =
     Preferences::GetBool("browser.display.use_focus_colors", mUseFocusColors);
 
   mFocusTextColor = mDefaultColor;
   mFocusBackgroundColor = mBackgroundColor;
 
-  colorStr = Preferences::GetCString("browser.display.focus_text_color");
+  colorStr = Preferences::GetString("browser.display.focus_text_color");
 
   if (!colorStr.IsEmpty()) {
     mFocusTextColor = MakeColorPref(colorStr);
   }
 
-  colorStr = Preferences::GetCString("browser.display.focus_background_color");
+  colorStr = Preferences::GetString("browser.display.focus_background_color");
 
   if (!colorStr.IsEmpty()) {
     mFocusBackgroundColor = MakeColorPref(colorStr);
   }
 
   mFocusRingWidth =
     Preferences::GetInt("browser.display.focus_ring_width", mFocusRingWidth);
 
@@ -2147,18 +2150,19 @@ static PRUint32 sInterruptMaxCounter = 1
 // Used for the "counter" mode.  This counts up to sInterruptMaxCounter and is
 // then reset to 0.
 static PRUint32 sInterruptCounter;
 // Number of interrupt checks to skip before really trying to interrupt.
 // Controlled by the GECKO_REFLOW_INTERRUPT_CHECKS_TO_SKIP env var.
 static PRUint32 sInterruptChecksToSkip = 200;
 // Number of milliseconds that a reflow should be allowed to run for before we
 // actually allow interruption.  Controlled by the
-// GECKO_REFLOW_MIN_NOINTERRUPT_DURATION env var.
-static TimeDuration sInterruptTimeout = TimeDuration::FromMilliseconds(100);
+// GECKO_REFLOW_MIN_NOINTERRUPT_DURATION env var.  Can't be initialized here,
+// because TimeDuration/TimeStamp is not safe to use in static constructors..
+static TimeDuration sInterruptTimeout;
 
 static void GetInterruptEnv()
 {
   char *ev = PR_GetEnv("GECKO_REFLOW_INTERRUPT_MODE");
   if (ev) {
 #ifndef XP_WIN
     if (PL_strcasecmp(ev, "random") == 0) {
       ev = PR_GetEnv("GECKO_REFLOW_INTERRUPT_SEED");
@@ -2179,19 +2183,18 @@ static void GetInterruptEnv()
     }
   }
   ev = PR_GetEnv("GECKO_REFLOW_INTERRUPT_CHECKS_TO_SKIP");
   if (ev) {
     sInterruptChecksToSkip = atoi(ev);
   }
 
   ev = PR_GetEnv("GECKO_REFLOW_MIN_NOINTERRUPT_DURATION");
-  if (ev) {
-    sInterruptTimeout = TimeDuration::FromMilliseconds(atoi(ev));
-  }
+  int duration_ms = ev ? atoi(ev) : 100;
+  sInterruptTimeout = TimeDuration::FromMilliseconds(duration_ms);
 }
 
 bool
 nsPresContext::HavePendingInputEvent()
 {
   switch (sInterruptMode) {
 #ifndef XP_WIN
     case ModeRandom:
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -6571,17 +6571,17 @@ nsIFrame::FinishAndStoreOverflow(nsOverf
      * correct dimensions by overriding the stored bounding rectangle with the value the caller has
      * ensured us we'll use.
      */
     nsRect newBounds(nsPoint(0, 0), aNewSize);
     // Transform affects both overflow areas.
     if (!Preserves3DChildren()) {
       NS_FOR_FRAME_OVERFLOW_TYPES(otype) {
         nsRect& o = aOverflowAreas.Overflow(otype);
-       o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
+        o = nsDisplayTransform::TransformRect(o, this, nsPoint(0, 0), &newBounds);
       }
     } else {
       ComputePreserve3DChildrenOverflow(aOverflowAreas, newBounds);
     }
   }
 
   bool visualOverflowChanged =
     !GetVisualOverflowRect().IsEqualInterior(aOverflowAreas.VisualOverflow());
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1973,17 +1973,18 @@ const ContentTouchHandler = {
 
     if (dragger.contentMouseCapture)
       this.touchTimeout = setTimeout(function() dragger.contentMouseCapture = false, kTouchTimeout);
 
     this._dispatchMouseEvent("Browser:MouseDown", aX, aY);
   },
 
   tapOver: function tapOver(aX, aY) {
-    this._dispatchMouseEvent("Browser:MouseOver", aX, aY);
+    if (!this.clickPrevented)
+      this._dispatchMouseEvent("Browser:MouseOver", aX, aY);
   },
 
   tapUp: function tapUp(aX, aY) {
     let browser = getBrowser();
     browser.messageManager.sendAsyncMessage("Browser:MouseCancel", {});
   },
 
   tapSingle: function tapSingle(aX, aY, aModifiers) {
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -620,18 +620,18 @@ pref("privacy.donottrackheader.enabled",
 pref("dom.event.contextmenu.enabled",       true);
 
 pref("javascript.enabled",                  true);
 pref("javascript.options.strict",           false);
 #ifdef DEBUG
 pref("javascript.options.strict.debug",     true);
 #endif
 pref("javascript.options.relimit",          true);
-pref("javascript.options.tracejit.content",  true);
-pref("javascript.options.tracejit.chrome",   true);
+pref("javascript.options.tracejit.content",  false);
+pref("javascript.options.tracejit.chrome",   false);
 pref("javascript.options.methodjit.content", true);
 pref("javascript.options.methodjit.chrome",  true);
 pref("javascript.options.jitprofiling.content", true);
 pref("javascript.options.jitprofiling.chrome",  true);
 pref("javascript.options.pccounts.content", false);
 pref("javascript.options.pccounts.chrome",  false);
 pref("javascript.options.methodjit_always", false);
 pref("javascript.options.typeinference", true);
--- a/toolkit/content/tests/fennec-tile-testapp/defaults/preferences/prefs.js
+++ b/toolkit/content/tests/fennec-tile-testapp/defaults/preferences/prefs.js
@@ -1,4 +1,4 @@
 pref("toolkit.defaultChromeURI", "chrome://tile/content/foo.xul");
-pref("javascript.options.tracejit.chrome",  true);
+pref("javascript.options.tracejit.chrome",  false);
 pref("javascript.options.tracejit.content", false);
 pref("browser.dom.window.dump.enabled", true);
--- a/widget/src/windows/GfxInfo.cpp
+++ b/widget/src/windows/GfxInfo.cpp
@@ -817,17 +817,16 @@ static const PRUint32 deviceFamilyNvidia
     0x014f, /* NV43 [GeForce 6200 (TM)] */
     0x0161, /* NV44 [GeForce 6200 TurboCache (TM)] */
     0x0162, /* NV44 [GeForce 6200SE TurboCache (TM)] */
     0x0163, /* NV44 [GeForce 6200 LE (TM)] */
     0x0164, /* NV44 [GeForce Go 6200 (TM)] */
     0x0167, /* NV43 [GeForce Go 6200/6400 (TM)] */
     0x0168, /* NV43 [GeForce Go 6200/6400 (TM)] */
     0x0169, /* NV44 [GeForce 6250 (TM)] */
-    0x0221, /* NV44A [GeForce 6200 (TM)] */
     0x0222, /* NV44 [GeForce 6200 A-LE (TM)] */
     0x0240, /* C51PV [GeForce 6150 (TM)] */
     0x0241, /* C51 [GeForce 6150 LE (TM)] */
     0x0244, /* C51 [Geforce Go 6150 (TM)] */
     0x0245, /* C51 [Quadro NVS 210S/GeForce 6150LE (TM)] */
     0x0247, /* C51 [GeForce Go 6100 (TM)] */
     0x03d0, /* C61 [GeForce 6150SE nForce 430 (TM)] */
     0x03d1, /* C61 [GeForce 6100 nForce 405 (TM)] */
--- a/xpcom/glue/nsCOMPtr.h
+++ b/xpcom/glue/nsCOMPtr.h
@@ -438,19 +438,26 @@ nsCOMPtr_base
             No client should ever see or have to type the name of this class.  It is the
             artifact that makes it a compile-time error to call |AddRef| and |Release|
             on a |nsCOMPtr|.  DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
 
             See |nsCOMPtr::operator->| and |nsRefPtr::operator->|.
           */
         {
           private:
-            using T::AddRef;
-            using T::Release;
-            
+            NS_METHOD_(nsrefcnt) AddRef();
+            NS_METHOD_(nsrefcnt) Release();
+            //using T::AddRef;
+            //using T::Release;
+            /*
+             We could use |using| above, except that gcc 4.2 on Mac has a bug
+             which causes |using| be unable to make the function private in
+             templated derived classes (see bug 689397).
+            */
+
             ~nsDerivedSafe(); // NOT TO BE IMPLEMENTED
             /* 
               This dtor is added to make this class compatible with GCC 4.6.
               If the destructor for T is private, nsDerivedSafe's unimplemented destructor 
               will be implicitly-declared by the compiler as deleted.
               Therefore this explicit dtor exists to avoid that deletion. See bug 689301.
             */
 
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -321,32 +321,35 @@ public:
  *
  * The implementations here should match NS_IMPL_ADDREF/NS_IMPL_RELEASE, minus
  * the nsrefcnt return-value and the NS_ASSERT_OWNINGTHREAD() call.
  *
  * @param _class The name of the class implementing the method
  */
 #define NS_INLINE_DECL_REFCOUNTING(_class)                                    \
 public:                                                                       \
-  void AddRef(void) {                                                         \
+  NS_METHOD_(nsrefcnt) AddRef(void) {                                         \
     NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");                 \
     NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class);                          \
     ++mRefCnt;                                                                \
     NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this));                     \
+    return mRefCnt;                                                           \
   }                                                                           \
-  void Release(void) {                                                        \
+  NS_METHOD_(nsrefcnt) Release(void) {                                        \
     NS_PRECONDITION(0 != mRefCnt, "dup release");                             \
     NS_ASSERT_OWNINGTHREAD_AND_NOT_CCTHREAD(_class);                          \
     --mRefCnt;                                                                \
     NS_LOG_RELEASE(this, mRefCnt, #_class);                                   \
     if (mRefCnt == 0) {                                                       \
       NS_ASSERT_OWNINGTHREAD(_class);                                         \
       mRefCnt = 1; /* stabilize */                                            \
       delete this;                                                            \
+      return 0;                                                               \
     }                                                                         \
+    return mRefCnt;                                                           \
   }                                                                           \
 protected:                                                                    \
   nsAutoRefCnt mRefCnt;                                                       \
   NS_DECL_OWNINGTHREAD                                                        \
 public:
 
 /**
  * Use this macro to implement the AddRef method for a given <i>_class</i>
--- a/xpcom/stub/Makefile.in
+++ b/xpcom/stub/Makefile.in
@@ -118,11 +118,11 @@ EXTRA_DSO_LDOPTS +=				\
 	$(NSPR_LIBS)				\
 	$(MOZALLOC_LIB)				\
 	$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 libs:: $(FINAL_TARGET)/dependentlibs.list
 
-$(FINAL_TARGET)/dependentlibs.list: Makefile.in
+$(FINAL_TARGET)/dependentlibs.list: Makefile.in $(DEPTH)/config/autoconf.mk
 	$(EXIT_ON_ERROR) \
 	( $(foreach dlib,$(DEPENDENT_LIBS_LIST),echo $(dlib);) ) > $@