Merge m-i to m-c
authorPhil Ringnalda <philringnalda@gmail.com>
Mon, 28 Oct 2013 16:57:08 -0700
changeset 168088 518f5bff0ae4fbf98899dc158961e89bd14fd797
parent 168037 f1010aef5c033fbb33e5162203c27a42608431a0 (current diff)
parent 168087 3ca982c90f009b939853a494d026c2c0c3377236 (diff)
child 168114 f601c574012014847e4f4034ef910c42fa4e1887
child 168168 622032a3228473d3716e3308afd70a20acd38005
child 168200 7a3702a0463c1d20bbe1b025ebeb65894c326e2d
child 171475 a791d9a5ff780609d47f1cd262e5844a5878ccff
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone28.0a1
first release with
nightly linux32
518f5bff0ae4 / 28.0a1 / 20131029030201 / files
nightly linux64
518f5bff0ae4 / 28.0a1 / 20131029030201 / files
nightly mac
518f5bff0ae4 / 28.0a1 / 20131029030201 / files
nightly win32
518f5bff0ae4 / 28.0a1 / 20131029030201 / files
nightly win64
518f5bff0ae4 / 28.0a1 / 20131029030201 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-i to m-c
media/kiss_fft/Makefile.in
security/sandbox/LICENSE
security/sandbox/Sandbox.cpp
security/sandbox/Sandbox.h
security/sandbox/android_arm_ucontext.h
security/sandbox/android_i386_ucontext.h
security/sandbox/android_ucontext.h
security/sandbox/arm_linux_syscalls.h
security/sandbox/linux_seccomp.h
security/sandbox/linux_syscalls.h
security/sandbox/seccomp_filter.h
security/sandbox/x86_32_linux_syscalls.h
security/sandbox/x86_64_linux_syscalls.h
--- a/build/docs/test_manifests.rst
+++ b/build/docs/test_manifests.rst
@@ -48,17 +48,21 @@ for manifest destiny manifests describes
 In summary, manifests are ini files with section names describing test files::
 
     [test_foo.js]
     [test_bar.js]
 
 Keys under sections can hold metadata about each test::
 
     [test_foo.js]
-    skip-if = os == win
+    skip-if = os == "win"
+    [test_foo.js]
+    skip-if = os == "linux" && debug
+    [test_baz.js]
+    fail-if = os == "mac" || os == "android"
 
 There is a special **DEFAULT** section whose keys/metadata apply to all
 sections/tests::
 
     [DEFAULT]
     property = value
 
     [test_foo.js]
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -1,18 +1,14 @@
 # -*- Makefile -*-
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-# For sanity's sake, we compile nsinstall without the wrapped system
-# headers, so that we can use it to set up the wrapped system headers.
-VISIBILITY_FLAGS =
-
 # STDCXX_COMPAT is not needed here, and will actually fail because
 # libstdc++-compat is not built yet.
 MOZ_LIBSTDCXX_HOST_VERSION =
 
 ifneq (WINNT,$(HOST_OS_ARCH))
 HOST_PROGRAM	= nsinstall_real$(HOST_BIN_SUFFIX)
 endif
 
--- a/config/moz.build
+++ b/config/moz.build
@@ -1,15 +1,18 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 NO_DIST_INSTALL = True
+# For sanity's sake, we compile nsinstall without the wrapped system
+# headers, so that we can use it to set up the wrapped system headers.
+NO_VISIBILITY_FLAGS = True
 
 CONFIGURE_SUBST_FILES += [
     'autoconf.mk',
     'doxygen.cfg',
     'emptyvars.mk',
     'makefiles/test/Makefile',
     'tests/makefiles/autodeps/Makefile',
     'tests/src-simple/Makefile',
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -4609,19 +4609,16 @@ HTMLInputElement::SetSelectionRange(int3
       nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eForward;
       if (aDirection.WasPassed() && aDirection.Value().EqualsLiteral("backward")) {
         dir = nsITextControlFrame::eBackward;
       }
 
       aRv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
       if (!aRv.Failed()) {
         aRv = textControlFrame->ScrollSelectionIntoView();
-        nsRefPtr<nsAsyncDOMEvent> event =
-          new nsAsyncDOMEvent(this, NS_LITERAL_STRING("select"), true, false);
-        event->PostDOMEvent();
       }
     }
   }
 }
 
 NS_IMETHODIMP
 HTMLInputElement::SetSelectionRange(int32_t aSelectionStart,
                                     int32_t aSelectionEnd,
@@ -4735,16 +4732,21 @@ HTMLInputElement::SetRangeText(const nsA
       else if ((uint32_t)aSelectionEnd > aStart)
         aSelectionEnd = newEnd;
     }
     break;
   }
 
   Optional<nsAString> direction;
   SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv);
+  if (!aRv.Failed()) {
+    nsRefPtr<nsAsyncDOMEvent> event =
+      new nsAsyncDOMEvent(this, NS_LITERAL_STRING("select"), true, false);
+    event->PostDOMEvent();
+  }
 }
 
 int32_t
 HTMLInputElement::GetSelectionStart(ErrorResult& aRv)
 {
   int32_t selEnd, selStart;
   aRv = GetSelectionRange(&selStart, &selEnd);
 
--- a/content/html/content/src/HTMLTextAreaElement.cpp
+++ b/content/html/content/src/HTMLTextAreaElement.cpp
@@ -883,19 +883,16 @@ HTMLTextAreaElement::SetSelectionRange(u
       nsITextControlFrame::SelectionDirection dir = nsITextControlFrame::eForward;
       if (aDirection.WasPassed() && aDirection.Value().EqualsLiteral("backward")) {
         dir = nsITextControlFrame::eBackward;
       }
 
       rv = textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd, dir);
       if (NS_SUCCEEDED(rv)) {
         rv = textControlFrame->ScrollSelectionIntoView();
-        nsRefPtr<nsAsyncDOMEvent> event =
-          new nsAsyncDOMEvent(this, NS_LITERAL_STRING("select"), true, false);
-        event->PostDOMEvent();
       }
     }
   }
 
   if (NS_FAILED(rv)) {
     aError.Throw(rv);
   }
 }
@@ -990,16 +987,21 @@ HTMLTextAreaElement::SetRangeText(const 
       else if ((uint32_t)aSelectionEnd > aStart)
         aSelectionEnd = newEnd;
     }
     break;
   }
 
   Optional<nsAString> direction;
   SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv);
+  if (!aRv.Failed()) {
+    nsRefPtr<nsAsyncDOMEvent> event =
+      new nsAsyncDOMEvent(this, NS_LITERAL_STRING("select"), true, false);
+    event->PostDOMEvent();
+  }
 }
 
 nsresult
 HTMLTextAreaElement::Reset()
 {
   nsresult rv;
 
   // To get the initial spellchecking, reset value to
--- a/content/html/content/test/forms/test_set_range_text.html
+++ b/content/html/content/test/forms/test_set_range_text.html
@@ -76,33 +76,35 @@ https://bugzilla.mozilla.org/show_bug.cg
           opThrows = true;
       }
       is(opThrows, false, msg + " should not throw NotSupportedError");
 
       elem.addEventListener("select", function (aEvent) {
         ok(true, "select event should be fired for " + aEvent.target.id);
         if (++numOfSelectCalls == expectedNumOfSelectCalls) {
           SimpleTest.finish();
+        } else if (numOfSelectCalls > expectedNumOfSelectCalls) {
+          ok(false, "Too many select events were fired");
         }
       }, false);
 
       elem.addEventListener("input", function (aEvent) {
         ok(false, "input event should NOT be fired for " + + aEvent.target.id);
       }, false);
 
       //test setRange(replacement)
       elem.value = "0123456789ABCDEF";
       elem.setSelectionRange(1, 6);
       elem.setRangeText("xyz");
       is(elem.value, "0xyz6789ABCDEF", msg + ".value == \"0xyz6789ABCDEF\"");
       is(elem.selectionStart, 1, msg + ".selectionStart == 1");
       is(elem.selectionEnd, 4, msg + ".selectionEnd == 4");
       elem.setRangeText("mnk");
       is(elem.value, "0mnk6789ABCDEF", msg + ".value == \"0mnk6789ABCDEF\"");
-      expectedNumOfSelectCalls += 3;
+      expectedNumOfSelectCalls += 2;
 
       //test SetRange(replacement, start, end, mode) with start > end
       try {
         elem.setRangeText("abc", 20, 4);
       } catch (ex) {
         opThrows = (ex.name == "IndexSizeError" && ex.code == DOMException.INDEX_SIZE_ERR);
       }
       is(opThrows, true, msg + " should throw IndexSizeError");
@@ -154,44 +156,44 @@ https://bugzilla.mozilla.org/show_bug.cg
 
       //subcase: selection{Start|End} > end
       elem.value = "0123456789";
       elem.setSelectionRange(6, 9);
       elem.setRangeText("Z", 1, 2, "preserve");
       is(elem.value, "0Z23456789", msg + ".value == \"0Z23456789\"");
       is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"preserve\"");
       is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"preserve\"");
-      expectedNumOfSelectCalls += 2;
+      expectedNumOfSelectCalls += 1;
 
       //subcase: selection{Start|End} < end
       elem.value = "0123456789";
       elem.setSelectionRange(4, 5);
       elem.setRangeText("QRST", 2, 9, "preserve");
       is(elem.value, "01QRST9", msg + ".value == \"01QRST9\"");
       is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"preserve\"");
       is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"preserve\"");
-      expectedNumOfSelectCalls += 2;
+      expectedNumOfSelectCalls += 1;
 
       //subcase: selectionStart > end, selectionEnd < end
       elem.value = "0123456789";
       elem.setSelectionRange(8, 4);
       elem.setRangeText("QRST", 1, 5);
       is(elem.value, "0QRST56789", msg + ".value == \"0QRST56789\"");
       is(elem.selectionStart, 1, msg + ".selectionStart == 1, with \"default\"");
       is(elem.selectionEnd, 5, msg + ".selectionEnd == 5, with \"default\"");
-      expectedNumOfSelectCalls += 2;
+      expectedNumOfSelectCalls += 1;
 
       //subcase: selectionStart < end, selectionEnd > end
       elem.value = "0123456789";
       elem.setSelectionRange(4, 9);
       elem.setRangeText("QRST", 2, 6);
       is(elem.value, "01QRST6789", msg + ".value == \"01QRST6789\"");
       is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"default\"");
       is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"default\"");
-      expectedNumOfSelectCalls += 2;
+      expectedNumOfSelectCalls += 1;
     }
   }
 
   addLoadEvent(TestInputs);
 
 </script>
 </pre>
 </body>
--- a/content/html/document/src/HTMLAllCollection.cpp
+++ b/content/html/document/src/HTMLAllCollection.cpp
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/HTMLAllCollection.h"
 
 #include "mozilla/HoldDropJSObjects.h"
 #include "nsDOMClassInfo.h"
 #include "nsHTMLDocument.h"
 #include "jsapi.h"
-#include "js/GCAPI.h"
+#include "nsWrapperCacheInlines.h"
 
 namespace mozilla {
 namespace dom {
 
 HTMLAllCollection::HTMLAllCollection(nsHTMLDocument* aDocument)
   : mDocument(aDocument)
 {
   MOZ_ASSERT(mDocument);
--- a/content/media/TextTrack.cpp
+++ b/content/media/TextTrack.cpp
@@ -177,16 +177,16 @@ TextTrack::ReadyState() const
 {
   return mReadyState;
 }
 
 void
 TextTrack::SetReadyState(uint16_t aState)
 {
   mReadyState = aState;
-  if (mReadyState == HTMLTrackElement::LOADED ||
-      mReadyState == HTMLTrackElement::ERROR) {
+  if (mMediaElement && (mReadyState == HTMLTrackElement::LOADED ||
+      mReadyState == HTMLTrackElement::ERROR)) {
     mMediaElement->RemoveTextTrack(this, true);
   }
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/media/WebVTTListener.cpp
+++ b/content/media/WebVTTListener.cpp
@@ -102,17 +102,18 @@ WebVTTListener::OnStartRequest(nsIReques
 }
 
 NS_IMETHODIMP
 WebVTTListener::OnStopRequest(nsIRequest* aRequest,
                               nsISupports* aContext,
                               nsresult aStatus)
 {
   if (mElement->ReadyState() != HTMLTrackElement::ERROR) {
-    mElement->mTrack->SetReadyState(HTMLTrackElement::LOADED);
+    TextTrack* track = mElement->Track();
+    track->SetReadyState(HTMLTrackElement::LOADED);
   }
   // Attempt to parse any final data the parser might still have.
   mParserWrapper->Flush();
   return NS_OK;
 }
 
 NS_METHOD
 WebVTTListener::ParseChunk(nsIInputStream* aInStream, void* aClosure,
--- a/content/media/gstreamer/GStreamerLoader.cpp
+++ b/content/media/gstreamer/GStreamerLoader.cpp
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <dlfcn.h>
 #include <stdio.h>
 
 #include "GStreamerLoader.h"
+#include "mozilla/NullPtr.h"
 
 #define LIBGSTREAMER 0
 #define LIBGSTAPP 1
 #define LIBGSTVIDEO 2
 
 namespace mozilla {
 
 /*
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -28,16 +28,17 @@
 #include "nsXBLPrototypeBinding.h"
 #include "nsXBLDocumentInfo.h"
 #include "mozilla/dom/XBLChildrenElement.h"
 
 #include "nsIStyleRuleProcessor.h"
 #include "nsRuleProcessorData.h"
 #include "nsIWeakReference.h"
 
+#include "nsWrapperCacheInlines.h"
 #include "nsIXPConnect.h"
 #include "nsDOMCID.h"
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsTHashtable.h"
 
 #include "nsIScriptContext.h"
 #include "nsBindingManager.h"
--- a/db/sqlite3/src/Makefile.in
+++ b/db/sqlite3/src/Makefile.in
@@ -2,17 +2,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SHORT_LIBNAME    = mozsqlt3
 ifndef MOZ_FOLD_LIBS
 FORCE_SHARED_LIB = 1
 endif
-VISIBILITY_FLAGS =
 LIB_IS_C_ONLY    = 1
 
 ifeq ($(OS_ARCH),WINNT)
 DEFFILE = $(CURDIR)/sqlite-processed.def
 RCFILE  = sqlite.rc
 RESFILE = sqlite.res
 
 GARBAGE += \
--- a/db/sqlite3/src/moz.build
+++ b/db/sqlite3/src/moz.build
@@ -1,15 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MODULE = 'sqlite3'
+NO_VISIBILITY_FLAGS = True
 
 EXPORTS += [
     'sqlite3.h',
 ]
 
 LIBRARY_NAME = 'mozsqlite3'
 
 SOURCES += [
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -651,17 +651,17 @@ VibrateWindowListener::HandleEvent(nsIDO
   if (!doc || doc->Hidden()) {
     // It's important that we call CancelVibrate(), not Vibrate() with an
     // empty list, because Vibrate() will fail if we're no longer focused, but
     // CancelVibrate() will succeed, so long as nobody else has started a new
     // vibration pattern.
     nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mWindow);
     hal::CancelVibrate(window);
     RemoveListener();
-    gVibrateWindowListener = NULL;
+    gVibrateWindowListener = nullptr;
     // Careful: The line above might have deleted |this|!
   }
 
   return NS_OK;
 }
 
 void
 VibrateWindowListener::RemoveListener()
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -3601,17 +3601,17 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
       return NS_ERROR_FAILURE;
     }
     *objp = obj;
 
     return NS_OK;
   }
 
   // Handle resolving if id refers to a name resolved by DOM worker code.
-  JS::Rooted<JSObject*> tmp(cx, NULL);
+  JS::Rooted<JSObject*> tmp(cx, nullptr);
   if (!ResolveWorkerClasses(cx, obj, id, flags, &tmp)) {
     return NS_ERROR_FAILURE;
   }
   if (tmp) {
     *objp = tmp;
     return NS_OK;
   }
 
--- a/dom/base/nsDOMJSUtils.h
+++ b/dom/base/nsDOMJSUtils.h
@@ -32,15 +32,15 @@ JSObject* GetDefaultScopeFromJSContext(J
 
 // A factory function for turning a JS::Value argv into an nsIArray
 // but also supports an effecient way of extracting the original argv.
 // Bug 312003 describes why this must be "void *", but argv will be cast to
 // JS::Value* and the args are found at:
 //    ((JS::Value*)aArgv)[0], ..., ((JS::Value*)aArgv)[aArgc - 1]
 // The resulting object will take a copy of the array, and ensure each
 // element is rooted.
-// Optionally, aArgv may be NULL, in which case the array is allocated and
-// rooted, but all items remain NULL.  This presumably means the caller will
-// then QI us for nsIJSArgArray, and set our array elements.
+// Optionally, aArgv may be nullptr, in which case the array is allocated and
+// rooted, but all items remain nullptr.  This presumably means the caller
+// will then QI us for nsIJSArgArray, and set our array elements.
 nsresult NS_CreateJSArgv(JSContext *aContext, uint32_t aArgc, void *aArgv,
                          nsIJSArgArray **aArray);
 
 #endif // nsDOMJSUtils_h__
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -140,17 +140,17 @@ nsFocusManager* nsFocusManager::sInstanc
 bool nsFocusManager::sMouseFocusesFormControl = false;
 bool nsFocusManager::sTestMode = false;
 
 static const char* kObservedPrefs[] = {
   "accessibility.browsewithcaret",
   "accessibility.tabfocus_applies_to_xul",
   "accessibility.mouse_focuses_formcontrol",
   "focusmanager.testmode",
-  NULL
+  nullptr
 };
 
 nsFocusManager::nsFocusManager()
 { }
 
 nsFocusManager::~nsFocusManager()
 {
   Preferences::RemoveObservers(this, kObservedPrefs);
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -513,17 +513,17 @@ private:
   // synchronized actions cannot be interrupted with events, so queue these up
   // and fire them later.
   nsTArray<nsDelayedBlurOrFocusEvent> mDelayedBlurFocusEvents;
 
   // A document which is handling a mouse button down event.
   // When a mouse down event process is finished, ESM sets focus to the target
   // content.  Therefore, while DOM event handlers are handling mouse down
   // events, the handlers should be able to steal focus from any elements even
-  // if focus is in chrome content.  So, if this isn't NULL and the caller
+  // if focus is in chrome content.  So, if this isn't nullptr and the caller
   // can access the document node, the caller should succeed in moving focus.
   nsCOMPtr<nsIDocument> mMouseDownEventHandlingDocument;
 
   static bool sTestMode;
 
   // the single focus manager
   static nsFocusManager* sInstance;
 };
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -671,17 +671,17 @@ nsOuterWindowProxy::isExtensible(JSConte
   return true;
 }
 
 bool
 nsOuterWindowProxy::preventExtensions(JSContext *cx,
                                       JS::Handle<JSObject*> proxy)
 {
   // See above.
-  JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+  JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                        JSMSG_CANT_CHANGE_EXTENSIBILITY);
   return false;
 }
 
 const char *
 nsOuterWindowProxy::className(JSContext *cx, JS::Handle<JSObject*> proxy)
 {
     MOZ_ASSERT(js::IsProxy(proxy));
@@ -1217,17 +1217,17 @@ nsGlobalWindow::~nsGlobalWindow()
   if (gDOMLeakPRLog)
     PR_LOG(gDOMLeakPRLog, PR_LOG_DEBUG,
            ("DOMWINDOW %p destroyed", this));
 #endif
 
   if (IsOuterWindow()) {
     JSObject *proxy = GetWrapperPreserveColor();
     if (proxy) {
-      js::SetProxyExtra(proxy, 0, js::PrivateValue(NULL));
+      js::SetProxyExtra(proxy, 0, js::PrivateValue(nullptr));
     }
 
     // An outer window is destroyed with inner windows still possibly
     // alive, iterate through the inner windows and null out their
     // back pointer to this outer, and pull them out of the list of
     // inner windows.
 
     nsGlobalWindow *w;
@@ -2110,17 +2110,17 @@ CreateNativeGlobalForInner(JSContext* aC
                            nsIXPConnectJSObjectHolder** aHolder)
 {
   MOZ_ASSERT(aCx);
   MOZ_ASSERT(aNewInner);
   MOZ_ASSERT(aNewInner->IsInnerWindow());
   MOZ_ASSERT(aPrincipal);
   MOZ_ASSERT(aHolder);
 
-  nsGlobalWindow *top = NULL;
+  nsGlobalWindow *top = nullptr;
   if (aNewInner->GetOuterWindow()) {
     top = aNewInner->GetTop();
   }
   JS::CompartmentOptions options;
   if (top) {
     if (top->GetGlobalJSObject()) {
       options.setSameZoneAs(top->GetGlobalJSObject());
     }
@@ -2391,17 +2391,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       JS::Rooted<JSObject*> global(cx, newInnerWindow->mJSObject);
       JS::Rooted<JSObject*> outerObject(cx,
         NewOuterWindowProxy(cx, global, thisChrome));
       if (!outerObject) {
         NS_ERROR("out of memory");
         return NS_ERROR_FAILURE;
       }
 
-      js::SetProxyExtra(mJSObject, 0, js::PrivateValue(NULL));
+      js::SetProxyExtra(mJSObject, 0, js::PrivateValue(nullptr));
 
       JS::Rooted<JSObject*> obj(cx, mJSObject);
       outerObject = xpc::TransplantObject(cx, obj, outerObject);
       if (!outerObject) {
         NS_ERROR("unable to transplant wrappers, probably OOM");
         return NS_ERROR_FAILURE;
       }
 
@@ -3128,17 +3128,17 @@ nsGlobalWindow::DispatchDOMEvent(WidgetE
                                        aEvent, aDOMEvent, aPresContext,
                                        aEventStatus);
 }
 
 void
 nsGlobalWindow::OnFinalize(JSObject* aObject)
 {
   if (aObject == mJSObject) {
-    mJSObject = NULL;
+    mJSObject = nullptr;
   }
 }
 
 void
 nsGlobalWindow::PoisonOuterWindowProxy(JSObject *aObject)
 {
   MOZ_ASSERT(IsOuterWindow());
   if (aObject == mJSObject) {
@@ -5613,17 +5613,17 @@ nsGlobalWindow::SetFullScreenInternal(bo
   if (!mWakeLock && mFullScreen) {
     nsCOMPtr<nsIPowerManagerService> pmService =
       do_GetService(POWERMANAGERSERVICE_CONTRACTID);
     NS_ENSURE_TRUE(pmService, NS_OK);
 
     pmService->NewWakeLock(NS_LITERAL_STRING("DOM_Fullscreen"), this, getter_AddRefs(mWakeLock));
   } else if (mWakeLock && !mFullScreen) {
     mWakeLock->Unlock();
-    mWakeLock = NULL;
+    mWakeLock = nullptr;
   }
 
   return NS_OK;
 }
 
 bool
 nsGlobalWindow::GetFullScreen(ErrorResult& aError)
 {
@@ -10436,17 +10436,17 @@ nsGlobalWindow::ShowSlowScriptDialog()
     tmp = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
                                              "KillScriptMessage",
                                              msg);
     if (NS_FAILED(tmp)) {
       rv = tmp;
     }
   }
 
-  // GetStringFromName can return NS_OK and still give NULL string
+  // GetStringFromName can return NS_OK and still give nullptr string
   if (NS_FAILED(rv) || !title || !msg || !stopButton || !waitButton ||
       (!debugButton && debugPossible) || !neverShowDlg) {
     NS_ERROR("Failed to get localized strings.");
     return ContinueSlowScript;
   }
 
   // Append file and line number information, if available
   if (script) {
@@ -10951,17 +10951,17 @@ nsGlobalWindow::GetParentInternal()
 
   nsCOMPtr<nsIDOMWindow> parent;
   GetParent(getter_AddRefs(parent));
 
   if (parent && parent != static_cast<nsIDOMWindow *>(this)) {
     return parent;
   }
 
-  return NULL;
+  return nullptr;
 }
 
 void
 nsGlobalWindow::UnblockScriptedClosing()
 {
   mBlockScriptedClosingFlag = false;
 }
 
@@ -12692,17 +12692,17 @@ nsGlobalWindow::EnumGamepadsForSync(cons
   return PL_DHASH_NEXT;
 }
 
 void
 nsGlobalWindow::SyncGamepadState()
 {
   FORWARD_TO_INNER_VOID(SyncGamepadState, ());
   if (mHasSeenGamepadInput) {
-    mGamepads.EnumerateRead(EnumGamepadsForSync, NULL);
+    mGamepads.EnumerateRead(EnumGamepadsForSync, nullptr);
   }
 }
 #endif
 // nsGlobalChromeWindow implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1057,17 +1057,17 @@ nsJSContext::BindCompiledEventHandler(ns
   JSObject* funobj;
   // Make sure the handler function is parented by its event target object
   if (aHandler) {
     funobj = JS_CloneFunctionObject(cx, aHandler, target);
     if (!funobj) {
       rv = NS_ERROR_OUT_OF_MEMORY;
     }
   } else {
-    funobj = NULL;
+    funobj = nullptr;
   }
 
   aBoundHandler.set(funobj);
 
   return rv;
 }
 
 nsIScriptGlobalObject *
@@ -1182,19 +1182,18 @@ nsJSContext::SetProperty(JS::Handle<JSOb
   }
 
   JSObject *args = ::JS_NewArrayObject(mContext, argc, array.array);
   if (!args) {
     return NS_ERROR_FAILURE;
   }
   JS::Value vargs = OBJECT_TO_JSVAL(args);
 
-  return JS_DefineProperty(mContext, aTarget, aPropName, vargs, NULL, NULL, 0)
-    ? NS_OK
-    : NS_ERROR_FAILURE;
+  return JS_DefineProperty(mContext, aTarget, aPropName, vargs,
+  						   nullptr, nullptr, 0) ? NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsJSContext::ConvertSupportsTojsvals(nsISupports *aArgs,
                                      JS::Handle<JSObject*> aScope,
                                      uint32_t *aArgc,
                                      JS::Value **aArgv,
                                      Maybe<nsRootedJSValueArray> &aTempStorage)
@@ -2514,17 +2513,17 @@ DOMGCSliceCallback(JSRuntime *aRt, JS::G
   }
 
   // The GC has more work to do, so schedule another GC slice.
   if (aProgress == JS::GC_SLICE_END) {
     nsJSContext::KillInterSliceGCTimer();
     if (!sShuttingDown) {
       CallCreateInstance("@mozilla.org/timer;1", &sInterSliceGCTimer);
       sInterSliceGCTimer->InitWithFuncCallback(InterSliceGCTimerFired,
-                                               NULL,
+                                               nullptr,
                                                NS_INTERSLICE_GC_DELAY,
                                                nsITimer::TYPE_ONE_SHOT);
     }
   }
 
   if (aProgress == JS::GC_CYCLE_END) {
     // May need to kill the inter-slice GC timer
     nsJSContext::KillInterSliceGCTimer();
--- a/dom/base/nsJSTimeoutHandler.cpp
+++ b/dom/base/nsJSTimeoutHandler.cpp
@@ -88,17 +88,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsJSScriptTimeoutHandler)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     nsAutoCString name("nsJSScriptTimeoutHandler");
     if (tmp->mFunction) {
       JSFunction* fun =
         JS_GetObjectFunction(js::UncheckedUnwrap(tmp->mFunction->Callable()));
       if (fun && JS_GetFunctionId(fun)) {
         JSFlatString *funId = JS_ASSERT_STRING_IS_FLAT(JS_GetFunctionId(fun));
-        size_t size = 1 + JS_PutEscapedFlatString(NULL, 0, funId, 0);
+        size_t size = 1 + JS_PutEscapedFlatString(nullptr, 0, funId, 0);
         char *funIdName = new char[size];
         if (funIdName) {
           JS_PutEscapedFlatString(funIdName, size, funId, 0);
           name.AppendLiteral(" [");
           name.Append(funIdName);
           delete[] funIdName;
           name.AppendLiteral("]");
         }
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -95,17 +95,17 @@ nsWindowMemoryReporter::Init()
   sWindowReporter = new nsWindowMemoryReporter();
   ClearOnShutdown(&sWindowReporter);
   NS_RegisterMemoryReporter(sWindowReporter);
   RegisterNonJSSizeOfTab(NonJSSizeOfTab);
 
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
     // DOM_WINDOW_DESTROYED_TOPIC announces what we call window "detachment",
-    // when a window's docshell is set to NULL.
+    // when a window's docshell is set to nullptr.
     os->AddObserver(sWindowReporter, DOM_WINDOW_DESTROYED_TOPIC,
                     /* weakRef = */ true);
     os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
                     /* weakRef = */ true);
   }
 
   NS_RegisterMemoryReporter(new GhostWindowsReporter());
   RegisterGhostWindowsDistinguishedAmount(GhostWindowsReporter::DistinguishedAmount);
@@ -180,17 +180,17 @@ CollectWindowReports(nsGlobalWindow *aWi
                      WindowPaths *aTopWindowPaths,
                      nsIMemoryReporterCallback *aCb,
                      nsISupports *aClosure)
 {
   nsAutoCString windowPath;
 
   // Avoid calling aWindow->GetTop() if there's no outer window.  It will work
   // just fine, but will spew a lot of warnings.
-  nsGlobalWindow *top = NULL;
+  nsGlobalWindow *top = nullptr;
   nsCOMPtr<nsIURI> location;
   if (aWindow->GetOuterWindow()) {
     // Our window should have a null top iff it has a null docshell.
     MOZ_ASSERT(!!aWindow->GetTop() == !!aWindow->GetDocShell());
     top = aWindow->GetTop();
     if (top) {
       location = GetWindowURI(top);
     }
@@ -478,19 +478,22 @@ nsWindowMemoryReporter::CollectReports(n
                                 &reportGhostWindowsEnumData);
   nsresult rv = reportGhostWindowsEnumData.rv;
   NS_ENSURE_SUCCESS(rv, rv);
 
   WindowPaths windowPaths;
   WindowPaths topWindowPaths;
 
   // Collect window memory usage.
-  nsWindowSizes windowTotalSizes(NULL);
-  nsCOMPtr<amIAddonManager> addonManager =
-    do_GetService("@mozilla.org/addons/integration;1");
+  nsWindowSizes windowTotalSizes(nullptr);
+  nsCOMPtr<amIAddonManager> addonManager;
+  if (XRE_GetProcessType() == GeckoProcessType_Default) {
+    // Only try to access the service from the main process.
+    addonManager = do_GetService("@mozilla.org/addons/integration;1");
+  }
   for (uint32_t i = 0; i < windows.Length(); i++) {
     rv = CollectWindowReports(windows[i], addonManager,
                               &windowTotalSizes, &ghostWindows,
                               &windowPaths, &topWindowPaths, aCb,
                               aClosure);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -767,17 +770,17 @@ GetNonDetachedWindowDomainsEnumerator(co
  *   - If a window now meets ghost criterion (2) but didn't before, set its
  *     timestamp to now.
  *
  * Additionally, if aOutGhostIDs is not null, fill it with the window IDs of
  * all ghost windows we found.
  */
 void
 nsWindowMemoryReporter::CheckForGhostWindows(
-  nsTHashtable<nsUint64HashKey> *aOutGhostIDs /* = NULL */)
+  nsTHashtable<nsUint64HashKey> *aOutGhostIDs /* = nullptr */)
 {
   nsCOMPtr<nsIEffectiveTLDService> tldService = do_GetService(
     NS_EFFECTIVETLDSERVICE_CONTRACTID);
   if (!tldService) {
     NS_WARNING("Couldn't get TLDService.");
     return;
   }
 
--- a/dom/base/nsWindowMemoryReporter.h
+++ b/dom/base/nsWindowMemoryReporter.h
@@ -197,17 +197,17 @@ private:
    * which have been destroyed or are no longer detached.
    *
    * If aOutGhostIDs is non-null, we populate it with the Window IDs of the
    * ghost windows.
    *
    * This is called asynchronously after we observe a DOM window being detached
    * from its docshell, and also right before we generate a memory report.
    */
-  void CheckForGhostWindows(nsTHashtable<nsUint64HashKey> *aOutGhostIDs = NULL);
+  void CheckForGhostWindows(nsTHashtable<nsUint64HashKey> *aOutGhostIDs = nullptr);
 
   /**
    * Maps a weak reference to a detached window (nsIWeakReference) to the time
    * when we observed that the window met ghost criterion (2) above.
    *
    * If the window has not yet met criterion (2) it maps to the null timestamp.
    *
    * (Although windows are not added to this table until they're detached, it's
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -454,17 +454,17 @@ inline nsWrapperCache*
 GetWrapperCache(nsGlobalWindow*)
 {
   return nullptr;
 }
 
 inline nsWrapperCache*
 GetWrapperCache(void* p)
 {
-  return NULL;
+  return nullptr;
 }
 
 // Helper template for smart pointers to resolve ambiguity between
 // GetWrappeCache(void*) and GetWrapperCache(const ParentObject&).
 template <template <typename> class SmartPtr, typename T>
 inline nsWrapperCache*
 GetWrapperCache(const SmartPtr<T>& aObject)
 {
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -258,17 +258,17 @@ ErrorResult::ReportNotEnoughArgsError(JS
 namespace dom {
 
 bool
 DefineConstants(JSContext* cx, JS::Handle<JSObject*> obj,
                 const ConstantSpec* cs)
 {
   for (; cs->name; ++cs) {
     bool ok =
-      JS_DefineProperty(cx, obj, cs->name, cs->value, NULL, NULL,
+      JS_DefineProperty(cx, obj, cs->name, cs->value, nullptr, nullptr,
                         JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
     if (!ok) {
       return false;
     }
   }
   return true;
 }
 
@@ -324,32 +324,33 @@ enum {
 
 static bool
 InterfaceObjectToString(JSContext* cx, unsigned argc, JS::Value *vp)
 {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   JS::Rooted<JSObject*> callee(cx, &args.callee());
 
   if (!args.thisv().isObject()) {
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
-                         "null", "object");
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
+                         JSMSG_CANT_CONVERT_TO, "null", "object");
     return false;
   }
 
   JS::Value v = js::GetFunctionNativeReserved(callee,
                                               TOSTRING_CLASS_RESERVED_SLOT);
   const JSClass* clasp = static_cast<const JSClass*>(v.toPrivate());
 
   v = js::GetFunctionNativeReserved(callee, TOSTRING_NAME_RESERVED_SLOT);
   JSString* jsname = static_cast<JSString*>(JSVAL_TO_STRING(v));
   size_t length;
   const jschar* name = JS_GetInternedStringCharsAndLength(jsname, &length);
 
   if (js::GetObjectJSClass(&args.thisv().toObject()) != clasp) {
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
+                         JSMSG_INCOMPATIBLE_PROTO,
                          NS_ConvertUTF16toUTF8(name).get(), "toString",
                          "object");
     return false;
   }
 
   nsString str;
   str.AppendLiteral("function ");
   str.Append(name, length);
@@ -424,45 +425,45 @@ CreateInterfaceObject(JSContext* cx, JS:
     constructor = JS_NewObject(cx, constructorClass, constructorProto, global);
   } else {
     MOZ_ASSERT(constructorNative);
     MOZ_ASSERT(constructorProto == JS_GetFunctionPrototype(cx, global));
     constructor = CreateConstructor(cx, global, name, constructorNative,
                                     ctorNargs);
   }
   if (!constructor) {
-    return NULL;
+    return nullptr;
   }
 
   if (constructorClass) {
     // Have to shadow Function.prototype.toString, since that throws
     // on things that are not js::FunctionClass.
     JS::Rooted<JSFunction*> toString(cx,
       js::DefineFunctionWithReserved(cx, constructor,
                                      "toString",
                                      InterfaceObjectToString,
                                      0, 0));
     if (!toString) {
-      return NULL;
+      return nullptr;
     }
 
     JSString *str = ::JS_InternString(cx, name);
     if (!str) {
-      return NULL;
+      return nullptr;
     }
     JSObject* toStringObj = JS_GetFunctionObject(toString);
     js::SetFunctionNativeReserved(toStringObj, TOSTRING_CLASS_RESERVED_SLOT,
                                   PRIVATE_TO_JSVAL(const_cast<JSClass *>(constructorClass)));
 
     js::SetFunctionNativeReserved(toStringObj, TOSTRING_NAME_RESERVED_SLOT,
                                   STRING_TO_JSVAL(str));
 
     if (!JS_DefineProperty(cx, constructor, "length", JS::Int32Value(ctorNargs),
                            nullptr, nullptr, JSPROP_READONLY | JSPROP_PERMANENT)) {
-      return NULL;
+      return nullptr;
     }
   }
 
   if (properties) {
     if (properties->staticMethods &&
         !DefinePrefable(cx, constructor, properties->staticMethods)) {
       return nullptr;
     }
@@ -492,17 +493,17 @@ CreateInterfaceObject(JSContext* cx, JS:
 
     if (chromeOnlyProperties->constants &&
         !DefinePrefable(cx, constructor, chromeOnlyProperties->constants)) {
       return nullptr;
     }
   }
 
   if (proto && !JS_LinkConstructorAndPrototype(cx, constructor, proto)) {
-    return NULL;
+    return nullptr;
   }
 
   if (defineOnGlobal && !DefineConstructor(cx, global, name, constructor)) {
     return nullptr;
   }
 
   if (namedConstructors) {
     int namedConstructorSlot = DOM_INTERFACE_SLOTS_BASE;
@@ -553,17 +554,17 @@ CreateInterfacePrototypeObject(JSContext
                                JS::Handle<JSObject*> parentProto,
                                const JSClass* protoClass,
                                const NativeProperties* properties,
                                const NativeProperties* chromeOnlyProperties)
 {
   JS::Rooted<JSObject*> ourProto(cx,
     JS_NewObjectWithUniqueType(cx, protoClass, parentProto, global));
   if (!ourProto) {
-    return NULL;
+    return nullptr;
   }
 
   if (properties) {
     if (properties->methods &&
         !DefinePrefable(cx, ourProto, properties->methods)) {
       return nullptr;
     }
 
@@ -698,18 +699,18 @@ NativeInterface2JSObjectAndThrowIfFailed
       if (obj) {
         aRetval.setObject(*obj);
         return true;
       }
   }
 
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (!XPCConvert::NativeInterface2JSObject(aRetval, NULL, aHelper, aIID,
-                                            NULL, aAllowNativeWrapper, &rv)) {
+  if (!XPCConvert::NativeInterface2JSObject(aRetval, nullptr, aHelper, aIID,
+                                            nullptr, aAllowNativeWrapper, &rv)) {
     // I can't tell if NativeInterface2JSObject throws JS exceptions
     // or not.  This is a sloppy stab at the right semantics; the
     // method really ought to be fixed to behave consistently.
     if (!JS_IsExceptionPending(aCx)) {
       Throw(aCx, NS_FAILED(rv) ? rv : NS_ERROR_UNEXPECTED);
     }
     return false;
   }
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1027,17 +1027,17 @@ WrapObject(JSContext* cx, JS::Handle<JSO
 // Just like the WrapObject above, but without requiring you to pick which
 // interface you're wrapping as.  This should only be used for objects that have
 // classinfo, for which it doesn't matter what IID is used to wrap.
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, T* p,
            JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p, NULL, rval);
+  return WrapObject(cx, scope, p, nullptr, rval);
 }
 
 // Helper to make it possible to wrap directly out of an nsCOMPtr
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, const nsCOMPtr<T>& p,
            const nsIID* iid, JS::MutableHandle<JS::Value> rval)
 {
@@ -1045,17 +1045,17 @@ WrapObject(JSContext* cx, JS::Handle<JSO
 }
 
 // Helper to make it possible to wrap directly out of an nsCOMPtr
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, const nsCOMPtr<T>& p,
            JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p, NULL, rval);
+  return WrapObject(cx, scope, p, nullptr, rval);
 }
 
 // Helper to make it possible to wrap directly out of an nsRefPtr
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, const nsRefPtr<T>& p,
            const nsIID* iid, JS::MutableHandle<JS::Value> rval)
 {
@@ -1063,17 +1063,17 @@ WrapObject(JSContext* cx, JS::Handle<JSO
 }
 
 // Helper to make it possible to wrap directly out of an nsRefPtr
 template<class T>
 inline bool
 WrapObject(JSContext* cx, JS::Handle<JSObject*> scope, const nsRefPtr<T>& p,
            JS::MutableHandle<JS::Value> rval)
 {
-  return WrapObject(cx, scope, p, NULL, rval);
+  return WrapObject(cx, scope, p, nullptr, rval);
 }
 
 // Specialization to make it easy to use WrapObject in codegen.
 template<>
 inline bool
 WrapObject<JSObject>(JSContext* cx, JS::Handle<JSObject*> scope, JSObject* p,
                      JS::MutableHandle<JS::Value> rval)
 {
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -149,17 +149,18 @@ DOMProxyHandler::isExtensible(JSContext 
   *extensible = true;
   return true;
 }
 
 bool
 DOMProxyHandler::preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy)
 {
   // Throw a TypeError, per WebIDL.
-  JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CHANGE_EXTENSIBILITY);
+  JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
+                       JSMSG_CANT_CHANGE_EXTENSIBILITY);
   return false;
 }
 
 bool
 BaseDOMProxyHandler::getPropertyDescriptor(JSContext* cx,
                                            JS::Handle<JSObject*> proxy,
                                            JS::Handle<jsid> id,
                                            MutableHandle<JSPropertyDescriptor> desc,
@@ -187,17 +188,17 @@ BaseDOMProxyHandler::getPropertyDescript
 bool
 DOMProxyHandler::defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
                                 MutableHandle<JSPropertyDescriptor> desc, bool* defined)
 {
   if (desc.hasGetterObject() && desc.setter() == JS_StrictPropertyStub) {
     return JS_ReportErrorFlagsAndNumber(cx,
                                         JSREPORT_WARNING | JSREPORT_STRICT |
                                         JSREPORT_STRICT_MODE_ERROR,
-                                        js_GetErrorMessage, NULL,
+                                        js_GetErrorMessage, nullptr,
                                         JSMSG_GETTER_ONLY);
   }
 
   if (xpc::WrapperFactory::IsXrayWrapper(proxy)) {
     return true;
   }
 
   JSObject* expando = EnsureExpandoObject(cx, proxy);
--- a/dom/bluetooth/BluetoothService.h
+++ b/dom/bluetooth/BluetoothService.h
@@ -112,17 +112,17 @@ public:
     nsRefPtr<BluetoothService> service = Get();
     return service.forget();
   }
 
   /**
    * Returns the path of the default adapter, implemented via a platform
    * specific method.
    *
-   * @return Default adapter path/name on success, NULL otherwise
+   * @return NS_OK on success, NS_ERROR_FAILURE otherwise
    */
   virtual nsresult
   GetDefaultAdapterPathInternal(BluetoothReplyRunnable* aRunnable) = 0;
 
   /**
    * Returns the properties of paired devices, implemented via a platform
    * specific method.
    *
--- a/dom/bluetooth/BluetoothUtils.cpp
+++ b/dom/bluetooth/BluetoothUtils.cpp
@@ -106,17 +106,17 @@ GetAddressFromObjectPath(const nsAString
 bool
 BroadcastSystemMessage(const nsAString& aType,
                        const InfallibleTArray<BluetoothNamedValue>& aData)
 {
   mozilla::AutoSafeJSContext cx;
   NS_ASSERTION(!::JS_IsExceptionPending(cx),
       "Shouldn't get here when an exception is pending!");
 
-  JS::RootedObject obj(cx, JS_NewObject(cx, NULL, NULL, NULL));
+  JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
   if (!obj) {
     BT_WARNING("Failed to new JSObject for system message!");
     return false;
   }
 
   if (!SetJsObject(cx, aData, obj)) {
     BT_WARNING("Failed to set properties of system message!");
     return false;
--- a/dom/bluetooth/ObexBase.cpp
+++ b/dom/bluetooth/ObexBase.cpp
@@ -90,17 +90,17 @@ ParseHeaders(const uint8_t* aHeaderStart
 
     int contentLength = 0;
     uint8_t highByte, lowByte;
 
     // Defined in 2.1 OBEX Headers, IrOBEX 1.2
     switch (headerId >> 6)
     {
       case 0x00:
-        // NULL terminated Unicode text, length prefixed with 2-byte
+        // Null-terminated Unicode text, length prefixed with 2-byte
         // unsigned integer.
       case 0x01:
         // byte sequence, length prefixed with 2 byte unsigned integer.
         highByte = *ptr++;
         lowByte = *ptr++;
         contentLength = (((int)highByte << 8) | lowByte) - 3;
         break;
 
--- a/dom/bluetooth/linux/BluetoothDBusService.cpp
+++ b/dom/bluetooth/linux/BluetoothDBusService.cpp
@@ -575,17 +575,17 @@ ContainsIcon(const InfallibleTArray<Blue
 }
 
 static bool
 GetProperty(DBusMessageIter aIter, Properties* aPropertyTypes,
             int aPropertyTypeLen, int* aPropIndex,
             InfallibleTArray<BluetoothNamedValue>& aProperties)
 {
   DBusMessageIter prop_val, array_val_iter;
-  char* property = NULL;
+  char* property = nullptr;
   uint32_t array_type;
   int i, expectedType, receivedType;
 
   if (dbus_message_iter_get_arg_type(&aIter) != DBUS_TYPE_STRING) {
     return false;
   }
 
   dbus_message_iter_get_basic(&aIter, &property);
@@ -937,24 +937,24 @@ AgentEventFilter(DBusConnection *conn, D
     // Return directly
     DBusMessage *reply = dbus_message_new_method_return(msg);
 
     if (!reply) {
       errorStr.AssignLiteral("Memory can't be allocated for the message.");
       goto handle_error;
     }
 
-    dbus_connection_send(conn, reply, NULL);
+    dbus_connection_send(conn, reply, nullptr);
     dbus_message_unref(reply);
     v = parameters;
   } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE, "Authorize")) {
     // This method gets called when the service daemon needs to authorize a
     // connection/service request.
     const char *uuid;
-    if (!dbus_message_get_args(msg, NULL,
+    if (!dbus_message_get_args(msg, nullptr,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_STRING, &uuid,
                                DBUS_TYPE_INVALID)) {
       errorStr.AssignLiteral("Invalid arguments for Authorize() method");
       goto handle_error;
     }
 
     NS_ConvertUTF8toUTF16 uuidStr(uuid);
@@ -982,25 +982,25 @@ AgentEventFilter(DBusConnection *conn, D
                                      "The uuid is not authorized");
     }
 
     if (!reply) {
       errorStr.AssignLiteral("Memory can't be allocated for the message.");
       goto handle_error;
     }
 
-    dbus_connection_send(conn, reply, NULL);
+    dbus_connection_send(conn, reply, nullptr);
     dbus_message_unref(reply);
     return DBUS_HANDLER_RESULT_HANDLED;
   } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
                                          "RequestConfirmation")) {
     // This method gets called when the service daemon needs to confirm a
     // passkey for an authentication.
     uint32_t passkey;
-    if (!dbus_message_get_args(msg, NULL,
+    if (!dbus_message_get_args(msg, nullptr,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_UINT32, &passkey,
                                DBUS_TYPE_INVALID)) {
       errorStr.AssignLiteral("Invalid arguments: RequestConfirmation()");
       goto handle_error;
     }
 
     parameters.AppendElement(
@@ -1014,17 +1014,17 @@ AgentEventFilter(DBusConnection *conn, D
 
     v = parameters;
     isPairingReq = true;
   } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
                                          "RequestPinCode")) {
     // This method gets called when the service daemon needs to get the passkey
     // for an authentication. The return value should be a string of 1-16
     // characters length. The string can be alphanumeric.
-    if (!dbus_message_get_args(msg, NULL,
+    if (!dbus_message_get_args(msg, nullptr,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_INVALID)) {
       errorStr.AssignLiteral("Invalid arguments for RequestPinCode() method");
       goto handle_error;
     }
 
     parameters.AppendElement(
       BluetoothNamedValue(NS_LITERAL_STRING("path"),
@@ -1035,17 +1035,17 @@ AgentEventFilter(DBusConnection *conn, D
 
     v = parameters;
     isPairingReq = true;
   } else if (dbus_message_is_method_call(msg, DBUS_AGENT_IFACE,
                                          "RequestPasskey")) {
     // This method gets called when the service daemon needs to get the passkey
     // for an authentication. The return value should be a numeric value
     // between 0-999999.
-    if (!dbus_message_get_args(msg, NULL,
+    if (!dbus_message_get_args(msg, nullptr,
                                DBUS_TYPE_OBJECT_PATH, &objectPath,
                                DBUS_TYPE_INVALID)) {
       errorStr.AssignLiteral("Invalid arguments for RequestPasskey() method");
       goto handle_error;
     }
 
     parameters.AppendElement(BluetoothNamedValue(
                                NS_LITERAL_STRING("path"),
@@ -1063,17 +1063,17 @@ AgentEventFilter(DBusConnection *conn, D
     // unregistered.
     DBusMessage *reply = dbus_message_new_method_return(msg);
 
     if (!reply) {
       errorStr.AssignLiteral("Memory can't be allocated for the message.");
       goto handle_error;
     }
 
-    dbus_connection_send(conn, reply, NULL);
+    dbus_connection_send(conn, reply, nullptr);
     dbus_message_unref(reply);
 
     // Do not send an notification to upper layer, too annoying.
     return DBUS_HANDLER_RESULT_HANDLED;
   } else {
 #ifdef DEBUG
     BT_WARNING("agent handler %s: Unhandled event. Ignore.", __FUNCTION__);
 #endif
@@ -1133,17 +1133,17 @@ public:
     }
 
     // There is no "RegisterAgent" function defined in device interface.
     // When we call "CreatePairedDevice", it will do device agent registration
     // for us. (See maemo.org/api_refs/5.0/beta/bluez/adapter.html)
     if (!dbus_connection_register_object_path(threadConnection->GetConnection(),
                                               KEY_REMOTE_AGENT,
                                               mAgentVTable,
-                                              NULL)) {
+                                              nullptr)) {
       BT_WARNING("%s: Can't register object path %s for remote device agent!",
                  __FUNCTION__, KEY_REMOTE_AGENT);
       return;
     }
 
     NS_DispatchToMainThread(new PrepareProfileManagersRunnable());
   }
 
@@ -1152,17 +1152,17 @@ private:
 };
 
 class AddReservedServiceRecordsReplyHandler : public DBusReplyHandler
 {
 public:
   void Handle(DBusMessage* aReply)
   {
     static const DBusObjectPathVTable sAgentVTable = {
-      NULL, AgentEventFilter, NULL, NULL, NULL, NULL
+      nullptr, AgentEventFilter, nullptr, nullptr, nullptr, nullptr
     };
 
     MOZ_ASSERT(!NS_IsMainThread()); // DBus thread
 
     if (!aReply || (dbus_message_get_type(aReply) == DBUS_MESSAGE_TYPE_ERROR)) {
       return;
     }
 
@@ -1222,17 +1222,17 @@ private:
     // will be passed to local agent, some will be passed to device agent.
     // For example, if a remote device would like to pair with us, then the
     // signal will be passed to local agent. If we start pairing process with
     // calling CreatePairedDevice, we'll get signal which should be passed to
     // device agent.
     if (!dbus_connection_register_object_path(threadConnection->GetConnection(),
                                               KEY_LOCAL_AGENT,
                                               aAgentVTable,
-                                              NULL)) {
+                                              nullptr)) {
       BT_WARNING("%s: Can't register object path %s for agent!",
                  __FUNCTION__, KEY_LOCAL_AGENT);
       return false;
     }
 
     nsRefPtr<RegisterAgentReplyHandler> handler =
       new RegisterAgentReplyHandler(aAgentVTable);
     MOZ_ASSERT(handler.get());
@@ -1336,17 +1336,17 @@ EventFilter(DBusConnection* aConn, DBusM
   MOZ_ASSERT(!NS_IsMainThread(), "Shouldn't be called from Main Thread!");
 
   if (dbus_message_get_type(aMsg) != DBUS_MESSAGE_TYPE_SIGNAL) {
     BT_WARNING("%s: event handler not interested in %s (not a signal).\n",
         __FUNCTION__, dbus_message_get_member(aMsg));
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
-  if (dbus_message_get_path(aMsg) == NULL) {
+  if (dbus_message_get_path(aMsg) == nullptr) {
     BT_WARNING("DBusMessage %s has no bluetooth destination, ignoring\n",
                dbus_message_get_member(aMsg));
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
 
   DBusError err;
   dbus_error_init(&err);
 
@@ -1659,17 +1659,17 @@ BluetoothDBusService::StartInternal()
                        &err);
     if (dbus_error_is_set(&err)) {
       LOG_AND_FREE_DBUS_ERROR(&err);
     }
   }
 
   // Add a filter for all incoming messages_base
   if (!dbus_connection_add_filter(mConnection->GetConnection(),
-                                  EventFilter, NULL, NULL)) {
+                                  EventFilter, nullptr, nullptr)) {
     BT_WARNING("Cannot create DBus Event Filter for DBus Thread!");
     return NS_ERROR_FAILURE;
   }
 
   if (!sPairingReqTable) {
     sPairingReqTable = new nsDataHashtable<nsStringHashKey, DBusMessage* >;
   }
 
--- a/dom/browser-element/BrowserElementParent.cpp
+++ b/dom/browser-element/BrowserElementParent.cpp
@@ -221,17 +221,17 @@ BrowserElementParent::OpenWindowOOP(TabP
 /* static */
 BrowserElementParent::OpenWindowResult
 BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
                                           nsIURI* aURI,
                                           const nsAString& aName,
                                           const nsACString& aFeatures,
                                           nsIDOMWindow** aReturnWindow)
 {
-  *aReturnWindow = NULL;
+  *aReturnWindow = nullptr;
 
   // If we call window.open from an <iframe> inside an <iframe mozbrowser>,
   // it's as though the top-level document inside the <iframe mozbrowser>
   // called window.open.  (Indeed, in the OOP case, the inner <iframe> lives
   // out-of-process, so we couldn't touch it if we tried.)
   //
   // GetScriptableTop gets us the <iframe mozbrowser>'s window; we'll use its
   // frame element, rather than aOpenerWindow's frame element, as our "opener
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -23,17 +23,17 @@
 #include "mozilla/hal_sandbox/PHalChild.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/ipc/TestShellChild.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/Preferences.h"
-#ifdef MOZ_CONTENT_SANDBOX
+#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX)
 #include "mozilla/Sandbox.h"
 #endif
 #include "mozilla/unused.h"
 
 #include "nsIConsoleListener.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMemoryInfoDumper.h"
@@ -310,17 +310,17 @@ ContentChild::~ContentChild()
 
 bool
 ContentChild::Init(MessageLoop* aIOLoop,
                    base::ProcessHandle aParentHandle,
                    IPC::Channel* aChannel)
 {
 #ifdef MOZ_WIDGET_GTK
     // sigh
-    gtk_init(NULL, NULL);
+    gtk_init(nullptr, nullptr);
 #endif
 
 #ifdef MOZ_WIDGET_QT
     // sigh, seriously
     nsQAppInstance::AddRef();
 #endif
 
 #ifdef MOZ_X11
@@ -548,17 +548,17 @@ ContentChild::AllocPImageBridgeChild(moz
 bool
 ContentChild::RecvSetProcessPrivileges(const ChildPrivileges& aPrivs)
 {
   ChildPrivileges privs = (aPrivs == PRIVILEGES_DEFAULT) ?
                           GeckoChildProcessHost::DefaultChildPrivileges() :
                           aPrivs;
   // If this fails, we die.
   SetCurrentProcessPrivileges(privs);
-#ifdef MOZ_CONTENT_SANDBOX
+#if defined(MOZ_CONTENT_SANDBOX) && defined(XP_LINUX)
   // SetCurrentProcessSandbox should be moved close to process initialization
   // time if/when possible. SetCurrentProcessPrivileges should probably be
   // moved as well. Right now this is set ONLY if we receive the
   // RecvSetProcessPrivileges message. See bug 880808.
   SetCurrentProcessSandbox();
 #endif
   return true;
 }
@@ -571,26 +571,26 @@ static void FirstIdle(void)
     sFirstIdleTask = nullptr;
     ContentChild::GetSingleton()->SendFirstIdle();
 }
 
 mozilla::jsipc::PJavaScriptChild *
 ContentChild::AllocPJavaScriptChild()
 {
     nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
-    NS_ENSURE_TRUE(svc, NULL);
+    NS_ENSURE_TRUE(svc, nullptr);
 
     JSRuntime *rt;
     svc->GetRuntime(&rt);
-    NS_ENSURE_TRUE(svc, NULL);
+    NS_ENSURE_TRUE(svc, nullptr);
 
     mozilla::jsipc::JavaScriptChild *child = new mozilla::jsipc::JavaScriptChild(rt);
     if (!child->init()) {
         delete child;
-        return NULL;
+        return nullptr;
     }
     return child;
 }
 
 bool
 ContentChild::DeallocPJavaScriptChild(PJavaScriptChild *child)
 {
     delete child;
@@ -814,17 +814,17 @@ ContentChild::DeallocPHalChild(PHalChild
     delete aHal;
     return true;
 }
 
 PIndexedDBChild*
 ContentChild::AllocPIndexedDBChild()
 {
   NS_NOTREACHED("Should never get here!");
-  return NULL;
+  return nullptr;
 }
 
 bool
 ContentChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
 {
   delete aActor;
   return true;
 }
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1052,32 +1052,32 @@ ContentParent::ShutDownProcess(bool aClo
 void
 ContentParent::MarkAsDead()
 {
     if (!mAppManifestURL.IsEmpty()) {
         if (sAppContentParents) {
             sAppContentParents->Remove(mAppManifestURL);
             if (!sAppContentParents->Count()) {
                 delete sAppContentParents;
-                sAppContentParents = NULL;
+                sAppContentParents = nullptr;
             }
         }
     } else if (sNonAppContentParents) {
         sNonAppContentParents->RemoveElement(this);
         if (!sNonAppContentParents->Length()) {
             delete sNonAppContentParents;
-            sNonAppContentParents = NULL;
+            sNonAppContentParents = nullptr;
         }
     }
 
     if (sPrivateContent) {
         sPrivateContent->RemoveElement(this);
         if (!sPrivateContent->Length()) {
             delete sPrivateContent;
-            sPrivateContent = NULL;
+            sPrivateContent = nullptr;
         }
     }
 
     mIsAlive = false;
 }
 
 void
 ContentParent::OnNuwaForkTimeout()
@@ -1256,17 +1256,17 @@ ContentParent::ActorDestroy(ActorDestroy
                 // random child windows loaded in them.
                 //
                 // XXX would be nice if we could get both ...
                 if (!mAppManifestURL.IsEmpty()) {
                     crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("URL"),
                                                        NS_ConvertUTF16toUTF8(mAppManifestURL));
                 }
 
-                crashReporter->GenerateCrashReport(this, NULL);
+                crashReporter->GenerateCrashReport(this, nullptr);
 
                 nsAutoString dumpID(crashReporter->ChildDumpID());
                 props->SetPropertyAsAString(NS_LITERAL_STRING("dumpID"), dumpID);
             }
 #endif
         }
         obs->NotifyObservers((nsIPropertyBag2*) props, "ipc:content-shutdown", nullptr);
     }
@@ -1274,17 +1274,17 @@ ContentParent::ActorDestroy(ActorDestroy
     // If the child process was terminated due to a SIGKIL, ShutDownProcess
     // might not have been called yet.  We must call it to ensure that our
     // channel is closed, etc.
     ShutDownProcess(/* closeWithError */ true);
 
     MessageLoop::current()->
         PostTask(FROM_HERE,
                  NewRunnableFunction(DelayedDeleteSubprocess, mSubprocess));
-    mSubprocess = NULL;
+    mSubprocess = nullptr;
 
     // IPDL rules require actors to live on past ActorDestroy, but it
     // may be that the kungFuDeathGrip above is the last reference to
     // |this|.  If so, when we go out of scope here, we're deleted and
     // all hell breaks loose.
     //
     // This runnable ensures that a reference to |this| lives on at
     // least until after the current task finishes running.
@@ -1600,19 +1600,19 @@ ContentParent::~ContentParent()
 
     // We should be removed from all these lists in ActorDestroy.
     MOZ_ASSERT(!sPrivateContent || !sPrivateContent->Contains(this));
     if (mAppManifestURL.IsEmpty()) {
         MOZ_ASSERT(!sNonAppContentParents ||
                    !sNonAppContentParents->Contains(this));
     } else {
         // In general, we expect sAppContentParents->Get(mAppManifestURL) to be
-        // NULL.  But it could be that we created another ContentParent for this
-        // app after we did this->ActorDestroy(), so the right check is that
-        // sAppContentParents->Get(mAppManifestURL) != this.
+        // nullptr.  But it could be that we created another ContentParent for
+        // this app after we did this->ActorDestroy(), so the right check is
+        // that sAppContentParents->Get(mAppManifestURL) != this.
         MOZ_ASSERT(!sAppContentParents ||
                    sAppContentParents->Get(mAppManifestURL) != this);
     }
 }
 
 bool
 ContentParent::IsAlive()
 {
@@ -1728,17 +1728,17 @@ ContentParent::RecvSetClipboardText(cons
     
     nsCOMPtr<nsISupports> nsisupportsDataWrapper =
         do_QueryInterface(dataWrapper);
     
     rv = trans->SetTransferData(kUnicodeMime, nsisupportsDataWrapper,
                                 text.Length() * sizeof(PRUnichar));
     NS_ENSURE_SUCCESS(rv, true);
     
-    clipboard->SetData(trans, NULL, whichClipboard);
+    clipboard->SetData(trans, nullptr, whichClipboard);
     return true;
 }
 
 bool
 ContentParent::RecvGetClipboardText(const int32_t& whichClipboard, nsString* text)
 {
     nsresult rv;
     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
@@ -2131,17 +2131,17 @@ ContentParent::RecvGetXPCOMProcessAttrib
 }
 
 mozilla::jsipc::PJavaScriptParent *
 ContentParent::AllocPJavaScriptParent()
 {
     mozilla::jsipc::JavaScriptParent *parent = new mozilla::jsipc::JavaScriptParent();
     if (!parent->init()) {
         delete parent;
-        return NULL;
+        return nullptr;
     }
     return parent;
 }
 
 bool
 ContentParent::DeallocPJavaScriptParent(PJavaScriptParent *parent)
 {
     static_cast<mozilla::jsipc::JavaScriptParent *>(parent)->destroyFromContent();
@@ -3161,17 +3161,17 @@ ContentParent::RecvPrivateDocShellsExist
   if (aExist) {
     sPrivateContent->AppendElement(this);
   } else {
     sPrivateContent->RemoveElement(this);
     if (!sPrivateContent->Length()) {
       nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
       obs->NotifyObservers(nullptr, "last-pb-context-exited", nullptr);
       delete sPrivateContent;
-      sPrivateContent = NULL;
+      sPrivateContent = nullptr;
     }
   }
   return true;
 }
 
 bool
 ContentParent::DoSendAsyncMessage(JSContext* aCx,
                                   const nsAString& aMessage,
--- a/dom/ipc/CrashReporterParent.cpp
+++ b/dom/ipc/CrashReporterParent.cpp
@@ -61,17 +61,17 @@ CrashReporterParent::CloneProtocol(Chann
 #endif
 }
 
 CrashReporterParent::CrashReporterParent()
     :
 #ifdef MOZ_CRASHREPORTER
       mNotes(4),
 #endif
-      mStartTime(time(NULL))
+      mStartTime(time(nullptr))
     , mInitialized(false)
 {
     MOZ_COUNT_CTOR(CrashReporterParent);
 }
 
 CrashReporterParent::~CrashReporterParent()
 {
     MOZ_COUNT_DTOR(CrashReporterParent);
--- a/dom/ipc/CrashReporterParent.h
+++ b/dom/ipc/CrashReporterParent.h
@@ -117,17 +117,17 @@ CrashReporterParent::GeneratePairedMinid
 }
 
 template<class Toplevel>
 inline bool
 CrashReporterParent::GenerateCrashReport(Toplevel* t,
                                          const AnnotationTable* processNotes)
 {
   nsCOMPtr<nsIFile> crashDump;
-  if (t->TakeMinidump(getter_AddRefs(crashDump), NULL) &&
+  if (t->TakeMinidump(getter_AddRefs(crashDump), nullptr) &&
       CrashReporter::GetIDFromMinidump(crashDump, mChildDumpID)) {
     return GenerateChildData(processNotes);
   }
   return false;
 }
 
 template<class Toplevel>
 /* static */ bool
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1256,17 +1256,17 @@ TabChild::IsRootContentDocument()
 bool
 TabChild::RecvLoadURL(const nsCString& uri)
 {
     SetProcessNameToAppName();
 
     nsresult rv = mWebNav->LoadURI(NS_ConvertUTF8toUTF16(uri).get(),
                                    nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
                                    nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_OWNER,
-                                   NULL, NULL, NULL);
+                                   nullptr, nullptr, nullptr);
     if (NS_FAILED(rv)) {
         NS_WARNING("mWebNav->LoadURI failed. Eating exception, what else can I do?");
     }
 
 #ifdef MOZ_CRASHREPORTER
     CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("URL"), uri);
 #endif
 
@@ -1698,17 +1698,17 @@ TabChild::RecvMouseWheelEvent(const Widg
 
 void
 TabChild::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
                                         const LayoutDevicePoint& aRefPoint)
 {
   MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN ||
              aMsg == NS_MOUSE_BUTTON_UP);
 
-  WidgetMouseEvent event(true, aMsg, NULL,
+  WidgetMouseEvent event(true, aMsg, nullptr,
                          WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
   event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
   event.time = aTime;
   event.button = WidgetMouseEvent::eLeftButton;
   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
   if (aMsg != NS_MOUSE_MOVE) {
     event.clickCount = 1;
   }
@@ -2382,17 +2382,17 @@ TabChild::GetMessageManager(nsIContentFr
 }
 
 PIndexedDBChild*
 TabChild::AllocPIndexedDBChild(
                             const nsCString& aGroup,
                             const nsCString& aASCIIOrigin, bool* /* aAllowed */)
 {
   NS_NOTREACHED("Should never get here!");
-  return NULL;
+  return nullptr;
 }
 
 bool
 TabChild::DeallocPIndexedDBChild(PIndexedDBChild* aActor)
 {
   delete aActor;
   return true;
 }
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -188,17 +188,17 @@ namespace dom {
 TabParent* sEventCapturer;
 
 TabParent *TabParent::mIMETabParent = nullptr;
 
 NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
 
 TabParent::TabParent(ContentParent* aManager, const TabContext& aContext)
   : TabContext(aContext)
-  , mFrameElement(NULL)
+  , mFrameElement(nullptr)
   , mIMESelectionAnchor(0)
   , mIMESelectionFocus(0)
   , mIMEComposing(false)
   , mIMECompositionEnding(false)
   , mIMECompositionStart(0)
   , mIMESeqno(0)
   , mEventCaptureDepth(0)
   , mRect(0, 0, 0, 0)
--- a/dom/media/bridge/MediaModule.cpp
+++ b/dom/media/bridge/MediaModule.cpp
@@ -21,23 +21,23 @@ namespace sipcc
 // Factory defined in sipcc::, defines sipcc::PeerConnectionImplConstructor
 NS_GENERIC_FACTORY_CONSTRUCTOR(PeerConnectionImpl)
 }
 
 // Defines kPEERCONNECTION_CID
 NS_DEFINE_NAMED_CID(PEERCONNECTION_CID);
 
 static const mozilla::Module::CIDEntry kCIDs[] = {
-  { &kPEERCONNECTION_CID, false, NULL, sipcc::PeerConnectionImplConstructor },
-  { NULL }
+  { &kPEERCONNECTION_CID, false, nullptr, sipcc::PeerConnectionImplConstructor },
+  { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kContracts[] = {
   { PEERCONNECTION_CONTRACTID, &kPEERCONNECTION_CID },
-  { NULL }
+  { nullptr }
 };
 
 static const mozilla::Module kModule = {
   mozilla::Module::kVersion,
   kCIDs,
   kContracts
 };
 
--- a/dom/mobilemessage/src/MmsMessage.cpp
+++ b/dom/mobilemessage/src/MmsMessage.cpp
@@ -490,43 +490,43 @@ MmsMessage::GetAttachments(JSContext* aC
     // Get |attachment.mId|.
     tmpJsStr = JS_NewUCStringCopyN(aCx,
                                    attachment.id.get(),
                                    attachment.id.Length());
     NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY);
 
     tmpJsVal.setString(tmpJsStr);
     if (!JS_DefineProperty(aCx, attachmentObj, "id", tmpJsVal,
-                           NULL, NULL, JSPROP_ENUMERATE)) {
+                           nullptr, nullptr, JSPROP_ENUMERATE)) {
       return NS_ERROR_FAILURE;
     }
 
     // Get |attachment.mLocation|.
     tmpJsStr = JS_NewUCStringCopyN(aCx,
                                    attachment.location.get(),
                                    attachment.location.Length());
     NS_ENSURE_TRUE(tmpJsStr, NS_ERROR_OUT_OF_MEMORY);
 
     tmpJsVal.setString(tmpJsStr);
     if (!JS_DefineProperty(aCx, attachmentObj, "location", tmpJsVal,
-                           NULL, NULL, JSPROP_ENUMERATE)) {
+                           nullptr, nullptr, JSPROP_ENUMERATE)) {
       return NS_ERROR_FAILURE;
     }
 
     // Get |attachment.mContent|.
     JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
     nsresult rv = nsContentUtils::WrapNative(aCx,
                                              global,
                                              attachment.content,
                                              &NS_GET_IID(nsIDOMBlob),
                                              &tmpJsVal);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (!JS_DefineProperty(aCx, attachmentObj, "content", tmpJsVal,
-                           NULL, NULL, JSPROP_ENUMERATE)) {
+                           nullptr, nullptr, JSPROP_ENUMERATE)) {
       return NS_ERROR_FAILURE;
     }
 
     tmpJsVal = OBJECT_TO_JSVAL(attachmentObj);
     if (!JS_SetElement(aCx, attachments, i, &tmpJsVal)) {
       return NS_ERROR_FAILURE;
     }
   }
--- a/dom/mobilemessage/src/MobileMessageCallback.cpp
+++ b/dom/mobilemessage/src/MobileMessageCallback.cpp
@@ -158,17 +158,18 @@ MobileMessageCallback::NotifyMessageDele
   nsresult rv;
   nsIScriptContext* sc = mDOMRequest->GetContextForEventHandlers(&rv);
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(sc, NS_ERROR_FAILURE);
 
   AutoPushJSContext cx(sc->GetNativeContext());
   NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
 
-  JS::Rooted<JSObject*> deleteArrayObj(cx, JS_NewArrayObject(cx, aSize, NULL));
+  JS::Rooted<JSObject*> deleteArrayObj(cx,
+                                       JS_NewArrayObject(cx, aSize, nullptr));
   JS::Rooted<JS::Value> value(cx);
   for (uint32_t i = 0; i < aSize; i++) {
     value.setBoolean(aDeleted[i]);
     JS_SetElement(cx, deleteArrayObj, i, &value);
   }
 
   JS::Rooted<JS::Value> deleteArrayVal(cx, JS::ObjectValue(*deleteArrayObj));
   return NotifySuccess(deleteArrayVal);
--- a/dom/src/json/nsJSON.cpp
+++ b/dom/src/json/nsJSON.cpp
@@ -211,17 +211,17 @@ nsJSON::EncodeInternal(JSContext* cx, co
    * perfectly fine for GetMethod to fail
    */
   JS::Rooted<JS::Value> val(cx, aValue);
   JS::Rooted<JS::Value> toJSON(cx);
   if (JS_GetProperty(cx, obj, "toJSON", &toJSON) &&
       toJSON.isObject() &&
       JS_ObjectIsCallable(cx, &toJSON.toObject())) {
     // If toJSON is implemented, it must not throw
-    if (!JS_CallFunctionValue(cx, obj, toJSON, 0, NULL, val.address())) {
+    if (!JS_CallFunctionValue(cx, obj, toJSON, 0, nullptr, val.address())) {
       if (JS_IsExceptionPending(cx))
         // passing NS_OK will throw the pending exception
         return NS_OK;
 
       // No exception, but still failed
       return NS_ERROR_FAILURE;
     }
 
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -131,17 +131,17 @@ struct Paths {
     macLocalApplicationsDir.SetIsVoid(true);
 #endif // defined(XP_MACOSX)
   }
 };
 
 /**
  * System directories.
  */
-Paths* gPaths = NULL;
+Paths* gPaths = nullptr;
 
 }
 
 /**
  * Return the path to one of the special directories.
  *
  * @param aKey The key to the special directory (e.g. "TmpD", "ProfD", ...)
  * @param aOutPath The path to the special directory. In case of error,
@@ -298,17 +298,17 @@ void CleanupOSFileConstants()
  * Produces a |ConstantSpec|.
  */
 #define INT_CONSTANT(name)      \
   { #name, INT_TO_JSVAL(name) }
 
 /**
  * End marker for ConstantSpec
  */
-#define PROP_END { NULL, JS::UndefinedValue() }
+#define PROP_END { nullptr, JS::UndefinedValue() }
 
 
 // Define missing constants for Android
 #if !defined(S_IRGRP)
 #define S_IXOTH 0001
 #define S_IWOTH 0002
 #define S_IROTH 0004
 #define S_IRWXO 0007
@@ -509,16 +509,21 @@ static const dom::ConstantSpec gLibcProp
   { "OSFILE_SIZEOF_DIRENT", INT_TO_JSVAL(sizeof (dirent)) },
 
   // Offset of field |d_name|.
   { "OSFILE_OFFSETOF_DIRENT_D_NAME", INT_TO_JSVAL(offsetof (struct dirent, d_name)) },
   // An upper bound to the length of field |d_name| of struct |dirent|.
   // (may not be exact, depending on padding).
   { "OSFILE_SIZEOF_DIRENT_D_NAME", INT_TO_JSVAL(sizeof (struct dirent) - offsetof (struct dirent, d_name)) },
 
+  // Defining |timeval|.
+  { "OSFILE_SIZEOF_TIMEVAL", INT_TO_JSVAL(sizeof (struct timeval)) },
+  { "OSFILE_OFFSETOF_TIMEVAL_TV_SEC", INT_TO_JSVAL(offsetof (struct timeval, tv_sec)) },
+  { "OSFILE_OFFSETOF_TIMEVAL_TV_USEC", INT_TO_JSVAL(offsetof (struct timeval, tv_usec)) },
+
 #if defined(DT_UNKNOWN)
   // Position of field |d_type| in |dirent|
   // Not strictly posix, but seems defined on all platforms
   // except mingw32.
   { "OSFILE_OFFSETOF_DIRENT_D_TYPE", INT_TO_JSVAL(offsetof (struct dirent, d_type)) },
 #endif // defined(DT_UNKNOWN)
 
   // Under MacOS X and BSDs, |dirfd| is a macro rather than a
@@ -666,28 +671,29 @@ static const dom::ConstantSpec gWinPrope
  * If the field does not exist, create it. If it exists but is not an
  * object, throw a JS error.
  */
 JSObject *GetOrCreateObjectProperty(JSContext *cx, JS::Handle<JSObject*> aObject,
                                     const char *aProperty)
 {
   JS::Rooted<JS::Value> val(cx);
   if (!JS_GetProperty(cx, aObject, aProperty, &val)) {
-    return NULL;
+    return nullptr;
   }
   if (!val.isUndefined()) {
     if (val.isObject()) {
       return &val.toObject();
     }
 
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
       JSMSG_UNEXPECTED_TYPE, aProperty, "not an object");
-    return NULL;
+    return nullptr;
   }
-  return JS_DefineObject(cx, aObject, aProperty, NULL, NULL, JSPROP_ENUMERATE);
+  return JS_DefineObject(cx, aObject, aProperty, nullptr, nullptr,
+                         JSPROP_ENUMERATE);
 }
 
 /**
  * Set a property of an object from a nsString.
  *
  * If the nsString is void (i.e. IsVoid is true), do nothing.
  */
 bool SetStringProperty(JSContext *cx, JS::Handle<JSObject*> aObject, const char *aProperty,
@@ -707,22 +713,22 @@ bool SetStringProperty(JSContext *cx, JS
  *
  * This function creates or uses JS object |OS.Constants| to store
  * all its constants.
  */
 bool DefineOSFileConstants(JSContext *cx, JS::Handle<JSObject*> global)
 {
   MOZ_ASSERT(gInitialized);
 
-  if (gPaths == NULL) {
+  if (gPaths == nullptr) {
     // If an initialization error was ignored, we may end up with
-    // |gInitialized == true| but |gPaths == NULL|. We cannot
+    // |gInitialized == true| but |gPaths == nullptr|. We cannot
     // |MOZ_ASSERT| this, as this would kill precompile_cache.js,
     // so we simply return an error.
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
       JSMSG_CANT_OPEN, "OSFileConstants", "initialization has failed");
     return false;
   }
 
   JS::Rooted<JSObject*> objOS(cx);
   if (!(objOS = GetOrCreateObjectProperty(cx, global, "OS"))) {
     return false;
   }
--- a/dom/system/gonk/AutoMounter.cpp
+++ b/dom/system/gonk/AutoMounter.cpp
@@ -373,17 +373,17 @@ AutoMounter::UpdateState()
   bool  umsAvail = false;
   bool  umsEnabled = false;
 
   if (access(ICS_SYS_USB_FUNCTIONS, F_OK) == 0) {
     umsAvail = (access(ICS_SYS_UMS_DIRECTORY, F_OK) == 0);
     if (umsAvail) {
       char functionsStr[60];
       if (ReadSysFile(ICS_SYS_USB_FUNCTIONS, functionsStr, sizeof(functionsStr))) {
-        umsEnabled = strstr(functionsStr, "mass_storage") != NULL;
+        umsEnabled = strstr(functionsStr, "mass_storage") != nullptr;
       } else {
         ERR("Error reading file '%s': %s", ICS_SYS_USB_FUNCTIONS, strerror(errno));
         umsEnabled = false;
       }
     } else {
       umsEnabled = false;
     }
   } else {
@@ -551,17 +551,17 @@ InitAutoMounterIOThread()
   sAutoMounter = new AutoMounter();
 }
 
 static void
 ShutdownAutoMounterIOThread()
 {
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
 
-  sAutoMounter = NULL;
+  sAutoMounter = nullptr;
   ShutdownVolumeManager();
 }
 
 static void
 SetAutoMounterModeIOThread(const int32_t& aMode)
 {
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
   MOZ_ASSERT(sAutoMounter);
@@ -657,21 +657,21 @@ InitVolumeConfig()
 
     if (line[0] == '#')
       continue;
     if (!(command = strtok_r(line, delim, &save_ptr))) {
       // Blank line - ignore
       continue;
     }
     if (!strcmp(command, "create")) {
-      if (!(vol_name_cstr = strtok_r(NULL, delim, &save_ptr))) {
+      if (!(vol_name_cstr = strtok_r(nullptr, delim, &save_ptr))) {
         ERR("No vol_name in %s line %d",  filename, n);
         continue;
       }
-      if (!(mount_point_cstr = strtok_r(NULL, delim, &save_ptr))) {
+      if (!(mount_point_cstr = strtok_r(nullptr, delim, &save_ptr))) {
         ERR("No mount point for volume '%s'. %s line %d", vol_name_cstr, filename, n);
         continue;
       }
       nsString  mount_point = NS_ConvertUTF8toUTF16(mount_point_cstr);
       nsString vol_name = NS_ConvertUTF8toUTF16(vol_name_cstr);
       nsresult rv;
       rv = vs->CreateFakeVolume(vol_name, mount_point);
       NS_ENSURE_SUCCESS_VOID(rv);
@@ -734,18 +734,18 @@ SetAutoMounterSharingMode(const nsCStrin
       FROM_HERE,
       NewRunnableFunction(SetAutoMounterSharingModeIOThread, 
                           aVolumeName, aAllowSharing));
 }
 
 void
 ShutdownAutoMounter()
 {
-  sAutoMounterSetting = NULL;
-  sUsbCableObserver = NULL;
+  sAutoMounterSetting = nullptr;
+  sUsbCableObserver = nullptr;
 
   XRE_GetIOMessageLoop()->PostTask(
       FROM_HERE,
       NewRunnableFunction(ShutdownAutoMounterIOThread));
 }
 
 } // system
 } // mozilla
--- a/dom/system/gonk/VolumeManager.cpp
+++ b/dom/system/gonk/VolumeManager.cpp
@@ -106,27 +106,27 @@ void VolumeManager::UnregisterStateObser
   mStateObserverList.RemoveObserver(aObserver);
 }
 
 //static
 TemporaryRef<Volume>
 VolumeManager::FindVolumeByName(const nsCSubstring& aName)
 {
   if (!sVolumeManager) {
-    return NULL;
+    return nullptr;
   }
   VolumeArray::size_type  numVolumes = NumVolumes();
   VolumeArray::index_type volIndex;
   for (volIndex = 0; volIndex < numVolumes; volIndex++) {
     RefPtr<Volume> vol = GetVolume(volIndex);
     if (vol->Name().Equals(aName)) {
       return vol;
     }
   }
-  return NULL;
+  return nullptr;
 }
 
 //static
 TemporaryRef<Volume>
 VolumeManager::FindAddVolumeByName(const nsCSubstring& aName)
 {
   RefPtr<Volume> vol = FindVolumeByName(aName);
   if (vol) {
@@ -386,17 +386,17 @@ InitVolumeManagerIOThread()
   InitVolumeServiceTestIOThread();
 }
 
 static void
 ShutdownVolumeManagerIOThread()
 {
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
 
-  sVolumeManager = NULL;
+  sVolumeManager = nullptr;
 }
 
 /**************************************************************************
 *
 *   Public API
 *
 *   Since the VolumeManager runs in IO Thread context, we need to switch
 *   to IOThread context before we can do anything.
--- a/dom/system/gonk/VolumeServiceIOThread.cpp
+++ b/dom/system/gonk/VolumeServiceIOThread.cpp
@@ -70,13 +70,13 @@ InitVolumeServiceIOThread(nsVolumeServic
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
   sVolumeServiceIOThread = new VolumeServiceIOThread(aVolumeService);
 }
 
 void
 ShutdownVolumeServiceIOThread()
 {
   MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
-  sVolumeServiceIOThread = NULL;
+  sVolumeServiceIOThread = nullptr;
 }
 
 } // system
 } // mozilla
--- a/dom/system/gonk/VolumeServiceTest.cpp
+++ b/dom/system/gonk/VolumeServiceTest.cpp
@@ -188,14 +188,14 @@ InitVolumeServiceTestIOThread()
 #endif
 }
 
 void
 ShutdownVolumeServiceTest()
 {
 #if TEST_NSVOLUME_OBSERVER
   DBG("ShutdownVolumeServiceTestIOThread called");
-  sTestObserver = NULL;
+  sTestObserver = nullptr;
 #endif
 }
 
 } // system
 } // mozilla
--- a/dom/system/unix/nsHapticFeedback.cpp
+++ b/dom/system/unix/nsHapticFeedback.cpp
@@ -45,17 +45,17 @@ nsHapticFeedback::PerformSimpleAction(in
 
     dbus_message_set_no_reply(msg, true);
 
     DBusMessageIter iter;
     dbus_message_iter_init_append(msg, &iter);
     const char* pattern = "PatternTouchscreen";
     dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &pattern);
 
-    if (dbus_connection_send(connection, msg, NULL)) {
+    if (dbus_connection_send(connection, msg, nullptr)) {
         dbus_connection_flush(connection);
         dbus_message_unref(msg);
     } else {
         dbus_message_unref(msg);
         return NS_ERROR_FAILURE;
     }
 #elif defined(MOZ_ENABLE_QTMOBILITY)
     if (aType == ShortPress)
--- a/dom/wifi/NetUtils.cpp
+++ b/dom/wifi/NetUtils.cpp
@@ -123,17 +123,17 @@ int32_t NetUtils::do_dhcp_do_request(con
     USE_DLFUNC(dhcp_do_request)
     ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns1, dns2,
                           server, lease, vendorinfo);
   } else if (sdkVersion == 18) {
     // JB 4.3
     // http://androidxref.com/4.3_r2.1/xref/system/core/libnetutils/dhcp_utils.c#181
     DEFINE_DLFUNC(dhcp_do_request, int32_t, const char*, char*, char*,  uint32_t*, char**, char*, uint32_t*, char*, char*)
     USE_DLFUNC(dhcp_do_request)
-    char *dns[3] = {dns1, dns2, NULL};
+    char *dns[3] = {dns1, dns2, nullptr};
     char domains[PROPERTY_VALUE_MAX];
     ret = dhcp_do_request(ifname, ipaddr, gateway, prefixLength, dns,
                           server, lease, vendorinfo, domains);
   } else {
     NS_WARNING("Unable to perform do_dhcp_request: unsupported sdk version!");
   }
   return ret;
 }
--- a/dom/workers/DOMBindingBase.h
+++ b/dom/workers/DOMBindingBase.h
@@ -79,17 +79,17 @@ public:
 template <class T>
 class DOMBindingAnchor
 {
   T* mBinding;
   JS::Anchor<JSObject*> mAnchor;
 
 public:
   DOMBindingAnchor()
-  : mBinding(NULL)
+  : mBinding(nullptr)
   { }
 
   DOMBindingAnchor(T* aBinding)
   {
     *this = aBinding;
   }
 
   DOMBindingAnchor&
--- a/dom/workers/DOMBindingInlines.h
+++ b/dom/workers/DOMBindingInlines.h
@@ -60,30 +60,30 @@ template <class T>
 inline JSObject*
 Wrap(JSContext* aCx, JSObject* aGlobal, nsRefPtr<T>& aConcreteObject)
 {
   MOZ_ASSERT(aCx);
 
   if (!aGlobal) {
     aGlobal = JS::CurrentGlobalOrNull(aCx);
     if (!aGlobal) {
-      return NULL;
+      return nullptr;
     }
   }
 
   JS::Rooted<JSObject*> global(aCx, aGlobal);
   JSObject* proto = WrapPrototypeTraits<T>::GetProtoObject(aCx, global);
   if (!proto) {
-    return NULL;
+    return nullptr;
   }
 
   JSObject* wrapper =
     JS_NewObject(aCx, WrapPrototypeTraits<T>::GetJSClass(), proto, global);
   if (!wrapper) {
-    return NULL;
+    return nullptr;
   }
 
   js::SetReservedSlot(wrapper, DOM_OBJECT_SLOT,
                       PRIVATE_TO_JSVAL(aConcreteObject));
 
   aConcreteObject->SetIsDOMBinding();
   aConcreteObject->SetWrapper(wrapper);
 
--- a/dom/workers/EventListenerManager.cpp
+++ b/dom/workers/EventListenerManager.cpp
@@ -30,17 +30,17 @@ struct EventListenerManager::ListenerCol
 
   static ListenerCollection*
   Add(JSContext* aCx, LinkedList<ListenerCollection>& aCollections, jsid aTypeId)
   {
     ListenerCollection* collection =
       static_cast<ListenerCollection*>(JS_malloc(aCx,
                                                  sizeof(ListenerCollection)));
     if (!collection) {
-      return NULL;
+      return nullptr;
     }
 
     new (collection) ListenerCollection(aTypeId);
     aCollections.insertBack(collection);
 
     return collection;
   }
 
@@ -67,17 +67,17 @@ struct ListenerData : LinkedListElement<
 
   static ListenerData*
   Add(JSContext* aCx, LinkedList<ListenerData>& aListeners, JSObject* aListener,
       EventListenerManager::Phase aPhase, bool aWantsUntrusted)
   {
     ListenerData* listenerData =
       static_cast<ListenerData*>(JS_malloc(aCx, sizeof(ListenerData)));
     if (!listenerData) {
-      return NULL;
+      return nullptr;
     }
 
     new (listenerData) ListenerData(aListener, aPhase, aWantsUntrusted);
     aListeners.insertBack(listenerData);
     return listenerData;
   }
 
   static void
@@ -278,17 +278,17 @@ EventListenerManager::GetEventListener(c
          listenerData;
          listenerData = listenerData->getNext()) {
         if (listenerData->mPhase == Onfoo) {
           return listenerData->mListener;
       }
     }
   }
 
-  return NULL;
+  return nullptr;
 }
 
 bool
 EventListenerManager::DispatchEvent(JSContext* aCx, const EventTarget& aTarget,
                                     JSObject* event, ErrorResult& aRv) const
 {
   JS::Rooted<JSObject*> aEvent(aCx, event);
   using namespace mozilla::dom::workers::events;
--- a/dom/workers/Events.cpp
+++ b/dom/workers/Events.cpp
@@ -48,60 +48,60 @@ public:
   static JSObject*
   InitClass(JSContext* aCx, JS::Handle<JSObject*> aObj, bool aMainRuntime)
   {
     JS::Rooted<JSObject*> parentProto(aCx);
 
     if (aMainRuntime) {
       JS::Rooted<JS::Value> windowPropVal(aCx);
       if (!JS_GetProperty(aCx, aObj, sClass.name, &windowPropVal)) {
-        return NULL;
+        return nullptr;
       }
 
       if (!JSVAL_IS_PRIMITIVE(windowPropVal)) {
         JS::Rooted<JS::Value> protoVal(aCx);
         if (!JS_GetProperty(aCx, JSVAL_TO_OBJECT(windowPropVal), "prototype",
                             &protoVal)) {
-          return NULL;
+          return nullptr;
         }
 
         if (!JSVAL_IS_PRIMITIVE(protoVal)) {
           parentProto = JSVAL_TO_OBJECT(protoVal);
         }
       }
     }
 
     const JSClass* clasp = parentProto ? &sMainRuntimeClass : &sClass;
 
     JS::Rooted<JSObject*> proto(aCx, JS_InitClass(aCx, aObj, parentProto, clasp, Construct, 0,
                                                   sProperties, sFunctions, nullptr, nullptr));
     if (!proto) {
-      return NULL;
+      return nullptr;
     }
 
     JS::Rooted<JSObject*> ctor(aCx, JS_GetConstructor(aCx, proto));
     if (!ctor) {
-      return NULL;
+      return nullptr;
     }
 
     if (!dom::DefineConstants(aCx, ctor, sStaticConstants) ||
         !dom::DefineConstants(aCx, proto, sStaticConstants)) {
-      return NULL;
+      return nullptr;
     }
 
     return proto;
   }
 
   static JSObject*
   Create(JSContext* aCx, JS::Handle<JSObject*> aParent, JS::Handle<JSString*> aType,
          bool aBubbles, bool aCancelable, bool aMainRuntime)
   {
     const JSClass* clasp = aMainRuntime ? &sMainRuntimeClass : &sClass;
 
-    JSObject* obj = JS_NewObject(aCx, clasp, NULL, aParent);
+    JSObject* obj = JS_NewObject(aCx, clasp, nullptr, aParent);
     if (obj) {
       Event* priv = new Event();
       SetJSPrivateSafeish(obj, priv);
       InitEventCommon(obj, priv, aType, aBubbles, aCancelable, true);
     }
     return obj;
   }
 
@@ -175,20 +175,20 @@ protected:
 
   static Event*
   GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
   {
     Event* priv = GetPrivate(aObj);
     if (priv) {
       return priv;
     }
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
                          JS_GetClass(aObj)->name);
-    return NULL;
+    return nullptr;
   }
 
   static void
   InitEventCommon(JSObject* aObj, Event* aEvent, JSString* aType,
                   bool aBubbles, bool aCancelable, bool aIsTrusted)
   {
     aEvent->mStopPropagationCalled = false;
     aEvent->mStopImmediatePropagationCalled = false;
@@ -206,17 +206,17 @@ protected:
     JS_SetReservedSlot(aObj, SLOT_isTrusted,
                        aIsTrusted ? JSVAL_TRUE : JSVAL_FALSE);
   }
 
 private:
   static bool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr, JSMSG_WRONG_CONSTRUCTOR,
                          sClass.name);
     return false;
   }
 
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
@@ -405,47 +405,47 @@ public:
 
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto,
             bool aMainRuntime)
   {
     const JSClass* clasp = aMainRuntime ? &sMainRuntimeClass : &sClass;
 
     return JS_InitClass(aCx, aObj, aParentProto, clasp, Construct, 0,
-                        sProperties, sFunctions, NULL, NULL);
+                        sProperties, sFunctions, nullptr, nullptr);
   }
 
   static JSObject*
   Create(JSContext* aCx, JS::Handle<JSObject*> aParent,
          JSAutoStructuredCloneBuffer& aData,
          nsTArray<nsCOMPtr<nsISupports> >& aClonedObjects,
          bool aMainRuntime)
   {
     JS::Rooted<JSString*> type(aCx, JS_InternString(aCx, "message"));
     if (!type) {
-      return NULL;
+      return nullptr;
     }
 
     const JSClass* clasp = aMainRuntime ? &sMainRuntimeClass : &sClass;
 
-    JS::Rooted<JSObject*> obj(aCx, JS_NewObject(aCx, clasp, NULL, aParent));
+    JS::Rooted<JSObject*> obj(aCx, JS_NewObject(aCx, clasp, nullptr, aParent));
     if (!obj) {
-      return NULL;
+      return nullptr;
     }
 
     JS::Rooted<JSObject*> ports(aCx, JS_NewArrayObject(aCx, 0, nullptr));
     if (!ports) {
-      return NULL;
+      return nullptr;
     }
 
     MessageEvent* priv = new MessageEvent(aMainRuntime);
     SetJSPrivateSafeish(obj, priv);
 
-    InitMessageEventCommon(aCx, obj, priv, type, false, false, NULL, NULL, NULL,
-                           ports, true);
+    InitMessageEventCommon(aCx, obj, priv, type, false, false, nullptr,
+                           nullptr, nullptr, ports, true);
 
     priv->mBuffer.swap(aData);
     priv->mClonedObjects.SwapElements(aClonedObjects);
 
     return obj;
   }
 
   static JSObject*
@@ -465,17 +465,17 @@ public:
     if (aMessagePort) {
       JS::Value port = OBJECT_TO_JSVAL(aMessagePort);
       ports = JS_NewArrayObject(aCx, 1, &port);
     } else {
       ports = JS_NewArrayObject(aCx, 0, nullptr);
     }
 
     if (!ports) {
-      return NULL;
+      return nullptr;
     }
 
     MessageEvent* priv = new MessageEvent(false);
     SetJSPrivateSafeish(obj, priv);
 
     InitMessageEventCommon(aCx, obj, priv, aType, aBubbles, aCancelable, aData,
                            aOrigin, aSource, ports, aIsTrusted);
 
@@ -508,20 +508,20 @@ private:
   static MessageEvent*
   GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
   {
     const JSClass* classPtr = JS_GetClass(aObj);
     if (IsThisClass(classPtr)) {
       return GetJSPrivateSafeish<MessageEvent>(aObj);
     }
 
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
                          classPtr->name);
-    return NULL;
+    return nullptr;
   }
 
   static void
   InitMessageEventCommon(JSContext* aCx, JSObject* aObj, Event* aEvent,
                          JSString* aType, bool aBubbles, bool aCancelable,
                          JSString* aData, JSString* aOrigin, JSObject* aSource,
                          JS::Handle<JSObject*> aMessagePorts, bool aIsTrusted)
   {
@@ -535,18 +535,18 @@ private:
                        aOrigin ? STRING_TO_JSVAL(aOrigin) : emptyString);
     JS_SetReservedSlot(aObj, SLOT_source, OBJECT_TO_JSVAL(aSource));
     JS_SetReservedSlot(aObj, SLOT_ports, OBJECT_TO_JSVAL(aMessagePorts));
   }
 
   static bool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
-                         sClass.name);
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
+                         JSMSG_WRONG_CONSTRUCTOR, sClass.name);
     return false;
   }
 
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     MessageEvent* priv = GetJSPrivateSafeish<MessageEvent>(aObj);
@@ -688,33 +688,33 @@ public:
 
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto,
             bool aMainRuntime)
   {
     const JSClass* clasp = aMainRuntime ? &sMainRuntimeClass : &sClass;
 
     return JS_InitClass(aCx, aObj, aParentProto, clasp, Construct, 0,
-                        sProperties, sFunctions, NULL, NULL);
+                        sProperties, sFunctions, nullptr, nullptr);
   }
 
   static JSObject*
   Create(JSContext* aCx, JS::Handle<JSObject*> aParent, JS::Handle<JSString*> aMessage,
          JS::Handle<JSString*> aFilename, uint32_t aLineNumber, bool aMainRuntime)
   {
     JS::Rooted<JSString*> type(aCx, JS_InternString(aCx, "error"));
     if (!type) {
-      return NULL;
+      return nullptr;
     }
 
     const JSClass* clasp = aMainRuntime ? &sMainRuntimeClass : &sClass;
 
-    JS::Rooted<JSObject*> obj(aCx, JS_NewObject(aCx, clasp, NULL, aParent));
+    JS::Rooted<JSObject*> obj(aCx, JS_NewObject(aCx, clasp, nullptr, aParent));
     if (!obj) {
-      return NULL;
+      return nullptr;
     }
 
     ErrorEvent* priv = new ErrorEvent();
     SetJSPrivateSafeish(obj, priv);
     InitErrorEventCommon(obj, priv, type, false, true, aMessage, aFilename,
                          aLineNumber, true);
     return obj;
   }
@@ -743,20 +743,20 @@ private:
   static ErrorEvent*
   GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
   {
     const JSClass* classPtr = JS_GetClass(aObj);
     if (IsThisClass(classPtr)) {
       return GetJSPrivateSafeish<ErrorEvent>(aObj);
     }
 
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
                          classPtr->name);
-    return NULL;
+    return nullptr;
   }
 
   static void
   InitErrorEventCommon(JSObject* aObj, Event* aEvent, JSString* aType,
                        bool aBubbles, bool aCancelable,
                        JSString* aMessage, JSString* aFilename,
                        uint32_t aLineNumber, bool aIsTrusted)
   {
@@ -765,18 +765,18 @@ private:
     JS_SetReservedSlot(aObj, SLOT_message, STRING_TO_JSVAL(aMessage));
     JS_SetReservedSlot(aObj, SLOT_filename, STRING_TO_JSVAL(aFilename));
     JS_SetReservedSlot(aObj, SLOT_lineno, INT_TO_JSVAL(aLineNumber));
   }
 
   static bool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
-                         sClass.name);
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
+                         JSMSG_WRONG_CONSTRUCTOR, sClass.name);
     return false;
   }
 
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(IsThisClass(JS_GetClass(aObj)));
     delete GetJSPrivateSafeish<ErrorEvent>(aObj);
@@ -882,31 +882,32 @@ public:
   {
     return &sClass;
   }
 
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto)
   {
     return JS_InitClass(aCx, aObj, aParentProto, &sClass, Construct, 0,
-                        sProperties, NULL, NULL, NULL);
+                        sProperties, nullptr, nullptr, nullptr);
   }
 
   static JSObject*
   Create(JSContext* aCx, JS::Handle<JSObject*> aParent, JS::Handle<JSString*> aType,
          bool aLengthComputable, double aLoaded, double aTotal)
   {
     JS::Rooted<JSString*> type(aCx, JS_InternJSString(aCx, aType));
     if (!type) {
-      return NULL;
+      return nullptr;
     }
 
-    JS::Rooted<JSObject*> obj(aCx, JS_NewObject(aCx, &sClass, NULL, aParent));
+    JS::Rooted<JSObject*> obj(aCx,
+                              JS_NewObject(aCx, &sClass, nullptr, aParent));
     if (!obj) {
-      return NULL;
+      return nullptr;
     }
 
     ProgressEvent* priv = new ProgressEvent();
     SetJSPrivateSafeish(obj, priv);
     InitProgressEventCommon(obj, priv, type, false, false, aLengthComputable,
                             aLoaded, aTotal, true);
     return obj;
   }
@@ -935,20 +936,20 @@ private:
   static ProgressEvent*
   GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
   {
     const JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr == &sClass) {
       return GetJSPrivateSafeish<ProgressEvent>(aObj);
     }
 
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
                          classPtr->name);
-    return NULL;
+    return nullptr;
   }
 
   static void
   InitProgressEventCommon(JSObject* aObj, Event* aEvent, JSString* aType,
                           bool aBubbles, bool aCancelable,
                           bool aLengthComputable, double aLoaded,
                           double aTotal, bool aIsTrusted)
   {
@@ -958,18 +959,18 @@ private:
                        aLengthComputable ? JSVAL_TRUE : JSVAL_FALSE);
     JS_SetReservedSlot(aObj, SLOT_loaded, DOUBLE_TO_JSVAL(aLoaded));
     JS_SetReservedSlot(aObj, SLOT_total, DOUBLE_TO_JSVAL(aTotal));
   }
 
   static bool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
-                         sClass.name);
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
+                         JSMSG_WRONG_CONSTRUCTOR, sClass.name);
     return false;
   }
 
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
     delete GetJSPrivateSafeish<ProgressEvent>(aObj);
@@ -1033,17 +1034,17 @@ Event::GetPrivate(JSObject* aObj)
     const JSClass* classPtr = JS_GetClass(aObj);
     if (IsThisClass(classPtr) ||
         MessageEvent::IsThisClass(classPtr) ||
         ErrorEvent::IsThisClass(classPtr) ||
         classPtr == ProgressEvent::Class()) {
       return GetJSPrivateSafeish<Event>(aObj);
     }
   }
-  return NULL;
+  return nullptr;
 }
 
 } /* anonymous namespace */
 
 BEGIN_WORKERS_NAMESPACE
 
 namespace events {
 
--- a/dom/workers/File.cpp
+++ b/dom/workers/File.cpp
@@ -34,26 +34,26 @@ class Blob
   static const JSClass sClass;
   static const JSPropertySpec sProperties[];
   static const JSFunctionSpec sFunctions[];
 
 public:
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj)
   {
-    return JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0, sProperties,
-                        sFunctions, NULL, NULL);
+    return JS_InitClass(aCx, aObj, nullptr, &sClass, Construct, 0,
+                        sProperties, sFunctions, nullptr, nullptr);
   }
 
   static JSObject*
   Create(JSContext* aCx, nsIDOMBlob* aBlob)
   {
     JS_ASSERT(SameCOMIdentity(static_cast<nsISupports*>(aBlob), aBlob));
 
-    JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
+    JSObject* obj = JS_NewObject(aCx, &sClass, nullptr, nullptr);
     if (obj) {
       JS_SetPrivate(obj, aBlob);
       NS_ADDREF(aBlob);
     }
     return obj;
   }
 
   static nsIDOMBlob*
@@ -63,20 +63,20 @@ private:
   static nsIDOMBlob*
   GetInstancePrivate(JSContext* aCx, JS::Handle<JSObject*> aObj, const char* aFunctionName)
   {
     nsIDOMBlob* blob = GetPrivate(aObj);
     if (blob) {
       return blob;
     }
 
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
                          JS_GetClass(aObj)->name);
-    return NULL;
+    return nullptr;
   }
 
   static nsIDOMBlob*
   Unwrap(JSContext* aCx, JSObject* aObj)
   {
     return GetPrivate(aObj);
   }
 
@@ -235,25 +235,25 @@ class File : public Blob
   static const JSClass sClass;
   static const JSPropertySpec sProperties[];
 
 public:
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto)
   {
     return JS_InitClass(aCx, aObj, aParentProto, &sClass, Construct, 0,
-                        sProperties, NULL, NULL, NULL);
+                        sProperties, nullptr, nullptr, nullptr);
   }
 
   static JSObject*
   Create(JSContext* aCx, nsIDOMFile* aFile)
   {
     JS_ASSERT(SameCOMIdentity(static_cast<nsISupports*>(aFile), aFile));
 
-    JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
+    JSObject* obj = JS_NewObject(aCx, &sClass, nullptr, nullptr);
     if (obj) {
       JS_SetPrivate(obj, aFile);
       NS_ADDREF(aFile);
     }
     return obj;
   }
 
   static nsIDOMFile*
@@ -263,17 +263,17 @@ public:
       const JSClass* classPtr = JS_GetClass(aObj);
       if (classPtr == &sClass) {
         nsISupports* priv = static_cast<nsISupports*>(JS_GetPrivate(aObj));
         nsCOMPtr<nsIDOMFile> file = do_QueryInterface(priv);
         JS_ASSERT_IF(priv, file);
         return file;
       }
     }
-    return NULL;
+    return nullptr;
   }
 
   static const JSClass*
   Class()
   {
     return &sClass;
   }
 
@@ -281,26 +281,27 @@ private:
   static nsIDOMFile*
   GetInstancePrivate(JSContext* aCx, JS::Handle<JSObject*> aObj, const char* aFunctionName)
   {
     nsIDOMFile* file = GetPrivate(aObj);
     if (file) {
       return file;
     }
 
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
                          JSMSG_INCOMPATIBLE_PROTO, sClass.name, aFunctionName,
                          JS_GetClass(aObj)->name);
-    return NULL;
+    return nullptr;
   }
 
   static bool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
+                         JSMSG_WRONG_CONSTRUCTOR,
                          sClass.name);
     return false;
   }
 
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == &sClass);
@@ -449,17 +450,17 @@ Blob::GetPrivate(JSObject* aObj)
     const JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr == &sClass || classPtr == File::Class()) {
       nsISupports* priv = static_cast<nsISupports*>(JS_GetPrivate(aObj));
       nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(priv);
       JS_ASSERT_IF(priv, blob);
       return blob;
     }
   }
-  return NULL;
+  return nullptr;
 }
 
 } // anonymous namespace
 
 BEGIN_WORKERS_NAMESPACE
 
 namespace file {
 
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -782,17 +782,17 @@ CreateJSContextForWorker(WorkerPrivate* 
       JS_SetGCParameter(aRuntime, setting.key, setting.value);
     }
   }
 
   JS_SetNativeStackQuota(aRuntime, WORKER_CONTEXT_NATIVE_STACK_LIMIT);
 
   // Security policy:
   static JSSecurityCallbacks securityCallbacks = {
-    NULL,
+    nullptr,
     ContentSecurityPolicyAllows
   };
   JS_SetSecurityCallbacks(aRuntime, &securityCallbacks);
 
   // DOM helpers:
   static js::DOMCallbacks DOMCallbacks = {
     InstanceClassHasProtoAtDepth
   };
--- a/dom/workers/Worker.cpp
+++ b/dom/workers/Worker.cpp
@@ -62,31 +62,31 @@ public:
 
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto,
             bool aMainRuntime)
   {
     JS::Rooted<JSObject*> proto(aCx,
       js::InitClassWithReserved(aCx, aObj, aParentProto, ProtoClass(),
                                 Construct, 0, sProperties, sFunctions,
-                                NULL, NULL));
+                                nullptr, nullptr));
     if (!proto) {
-      return NULL;
+      return nullptr;
     }
 
     js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
                         JS::PrivateValue(const_cast<DOMClass *>(DOMClassStruct())));
 
     if (!aMainRuntime) {
       WorkerPrivate* parent = GetWorkerPrivateFromContext(aCx);
       parent->AssertIsOnWorkerThread();
 
       JSObject* constructor = JS_GetConstructor(aCx, proto);
       if (!constructor)
-        return NULL;
+        return nullptr;
       js::SetFunctionNativeReserved(constructor, CONSTRUCTOR_SLOT_PARENT,
                                     PRIVATE_TO_JSVAL(parent));
     }
 
     return proto;
   }
 
   static WorkerPrivate*
@@ -116,17 +116,17 @@ protected:
       return false;
     }
 
     JS::Rooted<JS::Value> priv(aCx,
       js::GetFunctionNativeReserved(&aArgs.callee(), CONSTRUCTOR_SLOT_PARENT));
 
     WorkerPrivate* parent;
     if (priv.isUndefined()) {
-      parent = NULL;
+      parent = nullptr;
     } else {
       parent = static_cast<WorkerPrivate*>(priv.get().toPrivate());
       parent->AssertIsOnWorkerThread();
     }
 
     JS::Rooted<JSObject*> obj(aCx,
       Create(aCx, parent, scriptURL, aIsChromeWorker, false, EmptyString()));
     if (!obj) {
@@ -341,17 +341,17 @@ private:
 
 const DOMJSClass Worker::sClass = {
   {
     "Worker",
     JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(3) |
     JSCLASS_IMPLEMENTS_BARRIERS,
     JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-    NULL, NULL, NULL, NULL, Trace
+    nullptr, nullptr, nullptr, nullptr, Trace
   },
   {
     INTERFACE_CHAIN_1(prototypes::id::EventTarget_workers),
     false,
     &sWorkerNativePropertyHooks
   }
 };
 
@@ -422,31 +422,32 @@ public:
   }
 
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto,
             bool aMainRuntime)
   {
     JS::Rooted<JSObject*> proto(aCx,
       js::InitClassWithReserved(aCx, aObj, aParentProto, ProtoClass(),
-                                Construct, 0, NULL, NULL, NULL, NULL));
+                                Construct, 0, nullptr, nullptr, nullptr,
+                                nullptr));
     if (!proto) {
-      return NULL;
+      return nullptr;
     }
 
     js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
                         JS::PrivateValue(const_cast<DOMClass *>(DOMClassStruct())));
 
     if (!aMainRuntime) {
       WorkerPrivate* parent = GetWorkerPrivateFromContext(aCx);
       parent->AssertIsOnWorkerThread();
 
       JSObject* constructor = JS_GetConstructor(aCx, proto);
       if (!constructor)
-        return NULL;
+        return nullptr;
       js::SetFunctionNativeReserved(constructor, CONSTRUCTOR_SLOT_PARENT,
                                     PRIVATE_TO_JSVAL(parent));
     }
 
     return proto;
   }
 
 private:
@@ -498,17 +499,17 @@ private:
 };
 
 const DOMJSClass ChromeWorker::sClass = {
   { "ChromeWorker",
     JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(3) |
     JSCLASS_IMPLEMENTS_BARRIERS,
     JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize,
-    NULL, NULL, NULL, NULL, Trace,
+    nullptr, nullptr, nullptr, nullptr, Trace,
   },
   {
     INTERFACE_CHAIN_1(prototypes::id::EventTarget_workers),
     false,
     &sWorkerNativePropertyHooks
   }
 };
 
@@ -546,19 +547,20 @@ WorkerPrivate*
 Worker::GetInstancePrivate(JSContext* aCx, JSObject* aObj,
                            const char* aFunctionName)
 {
   const JSClass* classPtr = JS_GetClass(aObj);
   if (ClassIsWorker(classPtr)) {
     return UnwrapDOMObject<WorkerPrivate>(aObj);
   }
 
-  JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO,
-                       Class()->name, aFunctionName, classPtr->name);
-  return NULL;
+  JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
+                       JSMSG_INCOMPATIBLE_PROTO, Class()->name,
+                       aFunctionName, classPtr->name);
+  return nullptr;
 }
 
 JSObject*
 Worker::Create(JSContext* aCx, WorkerPrivate* aParent,
                const nsAString& aScriptURL, bool aIsChromeWorker,
                bool aIsSharedWorker, const nsAString& aSharedWorkerName)
 {
   MOZ_ASSERT_IF(aIsSharedWorker, !aSharedWorkerName.IsVoid());
@@ -627,24 +629,24 @@ InitClass(JSContext* aCx, JSObject* aGlo
 }
 
 } // namespace worker
 
 WorkerCrossThreadDispatcher*
 GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker)
 {
   if (JSVAL_IS_PRIMITIVE(aWorker)) {
-    return NULL;
+    return nullptr;
   }
 
   WorkerPrivate* w =
       Worker::GetInstancePrivate(aCx, JSVAL_TO_OBJECT(aWorker),
                                  "GetWorkerCrossThreadDispatcher");
   if (!w) {
-    return NULL;
+    return nullptr;
   }
   return w->GetCrossThreadDispatcher();
 }
 
 
 namespace chromeworker {
 
 bool
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -1985,16 +1985,21 @@ private:
     nsCOMPtr<nsIURI> scriptURI;
     if (NS_FAILED(NS_NewURI(getter_AddRefs(scriptURI),
                             mWorkerPrivate->ScriptURL()))) {
       return;
     }
 
     mAlreadyMappedToAddon = true;
 
+    if (XRE_GetProcessType() != GeckoProcessType_Default) {
+      // Only try to access the service from the main process.
+      return;
+    }
+
     nsAutoCString addonId;
     bool ok;
     nsCOMPtr<amIAddonManager> addonManager =
       do_GetService("@mozilla.org/addons/integration;1");
 
     if (!addonManager ||
         NS_FAILED(addonManager->MapURIToAddonID(scriptURI, addonId, &ok)) ||
         !ok) {
@@ -2382,17 +2387,17 @@ WorkerPrivateParent<Derived>::_finalize(
     NS_WARNING("Failed to terminate!");
   }
 
   // Before calling through to the base class we need to grab another reference
   // if we're on the main thread. Otherwise the base class' _Finalize method
   // will call Release, and some of our members cannot be released during
   // finalization. Of course, if those members are already gone then we can skip
   // this mess...
-  WorkerPrivateParent<Derived>* extraSelfRef = NULL;
+  WorkerPrivateParent<Derived>* extraSelfRef = nullptr;
 
   if (!mParent && !mMainThreadObjectsForgotten) {
     AssertIsOnMainThread();
     NS_ADDREF(extraSelfRef = this);
   }
 
   EventTarget::_finalize(aFop);
 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -102,17 +102,17 @@ public:
   {
     return &sClass;
   }
 
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto)
   {
     return JS_InitClass(aCx, aObj, aParentProto, Class(), Construct, 0,
-                        sProperties, sFunctions, NULL, NULL);
+                        sProperties, sFunctions, nullptr, nullptr);
   }
 
   using EventTarget::GetEventListener;
   using EventTarget::SetEventListener;
 
 protected:
   WorkerGlobalScope(JSContext* aCx, WorkerPrivate* aWorker)
   : EventTarget(aCx), mWorker(aWorker)
@@ -228,18 +228,18 @@ private:
   }
 
   static WorkerGlobalScope*
   GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName);
 
   static bool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
-                         sClass.name);
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
+                         JSMSG_WRONG_CONSTRUCTOR, sClass.name);
     return false;
   }
 
   static bool
   GetSelfImpl(JSContext* aCx, JS::CallArgs aArgs)
   {
     aArgs.rval().setObject(aArgs.thisv().toObject());
     return true;
@@ -317,17 +317,17 @@ private:
     JS::Rooted<JS::Value> rval(aCx, JS::UndefinedValue());
     if (!JS_CallFunctionValue(aCx, JSVAL_TO_OBJECT(scope), listener,
                               ArrayLength(argv), argv, rval.address())) {
       JS_ReportPendingException(aCx);
       return false;
     }
 
     if (JSVAL_IS_BOOLEAN(rval) && JSVAL_TO_BOOLEAN(rval) &&
-        !JS_CallFunctionName(aCx, event, "preventDefault", 0, NULL,
+        !JS_CallFunctionName(aCx, event, "preventDefault", 0, nullptr,
                              rval.address())) {
       return false;
     }
 
     return true;
   }
 
   static bool
@@ -752,17 +752,17 @@ public:
     return &sClass.mClass;
   }
 
   static JSObject*
   InitClass(JSContext* aCx, JSObject* aObj, JSObject* aParentProto)
   {
     JS::Rooted<JSObject*> proto(aCx,
       JS_InitClass(aCx, aObj, aParentProto, ProtoClass(), Construct, 0,
-                   sProperties, sFunctions, NULL, NULL));
+                   sProperties, sFunctions, nullptr, nullptr));
     if (proto) {
       void* domClass = const_cast<DOMClass *>(DOMClassStruct());
       js::SetReservedSlot(proto, DOM_PROTO_INSTANCE_CLASS_SLOT,
                           JS::PrivateValue(domClass));
     }
     return proto;
   }
 
@@ -882,40 +882,40 @@ private:
   static DedicatedWorkerGlobalScope*
   GetInstancePrivate(JSContext* aCx, JSObject* aObj, const char* aFunctionName)
   {
     const JSClass* classPtr = JS_GetClass(aObj);
     if (classPtr == Class()) {
       return UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj);
     }
 
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
                          JSMSG_INCOMPATIBLE_PROTO, Class()->name, aFunctionName,
                          classPtr->name);
-    return NULL;
+    return nullptr;
   }
 
   static bool
   Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
-    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
-                         Class()->name);
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, nullptr,
+                         JSMSG_WRONG_CONSTRUCTOR, Class()->name);
     return false;
   }
 
   static bool
   Resolve(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId,
           unsigned aFlags, JS::MutableHandle<JSObject*> aObjp)
   {
     bool resolved;
     if (!JS_ResolveStandardClass(aCx, aObj, aId, &resolved)) {
       return false;
     }
 
-    aObjp.set(resolved ? aObj.get() : NULL);
+    aObjp.set(resolved ? aObj.get() : nullptr);
     return true;
   }
 
   static void
   Finalize(JSFreeOp* aFop, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == Class());
     DedicatedWorkerGlobalScope* scope =
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -1263,17 +1263,17 @@ public:
   {
     if (mXMLHttpRequestPrivate) {
       mXMLHttpRequestPrivate->Unpin();
     }
   }
 
   void Clear()
   {
-    mXMLHttpRequestPrivate = NULL;
+    mXMLHttpRequestPrivate = nullptr;
   }
 
 private:
   XMLHttpRequest* mXMLHttpRequestPrivate;
 };
 
 } // anonymous namespace
 
@@ -1419,17 +1419,17 @@ Proxy::HandleEvent(nsIDOMEvent* aEvent)
       }
     }
   }
 
   return NS_OK;
 }
 
 XMLHttpRequest::XMLHttpRequest(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
-: XMLHttpRequestEventTarget(aCx), mJSObject(NULL), mUpload(NULL),
+: XMLHttpRequestEventTarget(aCx), mJSObject(nullptr), mUpload(nullptr),
   mWorkerPrivate(aWorkerPrivate),
   mResponseType(XMLHttpRequestResponseType::Text), mTimeout(0),
   mJSObjectRooted(false), mBackgroundRequest(false),
   mWithCredentials(false), mCanceled(false), mMozAnon(false), mMozSystem(false)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 }
 
@@ -1465,17 +1465,17 @@ XMLHttpRequest::Constructor(const Global
   JSContext* cx = aGlobal.GetContext();
   WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx);
   MOZ_ASSERT(workerPrivate);
 
   nsRefPtr<XMLHttpRequest> xhr = new XMLHttpRequest(cx, workerPrivate);
 
   if (!Wrap(cx, aGlobal.Get(), xhr)) {
     aRv.Throw(NS_ERROR_FAILURE);
-    return NULL;
+    return nullptr;
   }
 
   if (workerPrivate->XHRParamsAllowed()) {
     xhr->mMozAnon = aParams.mMozAnon;
     xhr->mMozSystem = aParams.mMozSystem;
   }
 
   xhr->mJSObject = xhr->GetJSObject();
@@ -1885,26 +1885,26 @@ XMLHttpRequest::SetMozBackgroundRequest(
 
 XMLHttpRequestUpload*
 XMLHttpRequest::GetUpload(ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   if (mCanceled) {
     aRv.Throw(UNCATCHABLE_EXCEPTION);
-    return NULL;
+    return nullptr;
   }
 
   if (!mUpload) {
     XMLHttpRequestUpload* upload =
       XMLHttpRequestUpload::Create(GetJSContext(), this);
 
     if (!upload) {
       aRv.Throw(NS_ERROR_FAILURE);
-      return NULL;
+      return nullptr;
     }
 
     mUpload = upload;
   }
 
   return mUpload;
 }
 
--- a/dom/workers/XMLHttpRequest.h
+++ b/dom/workers/XMLHttpRequest.h
@@ -227,23 +227,23 @@ public:
   GetResponse(JSContext* /* unused */, ErrorResult& aRv);
 
   void
   GetResponseText(nsAString& aResponseText, ErrorResult& aRv);
 
   JSObject*
   GetResponseXML() const
   {
-    return NULL;
+    return nullptr;
   }
 
   JSObject*
   GetChannel() const
   {
-    return NULL;
+    return nullptr;
   }
 
   JS::Value
   GetInterface(JSContext* cx, JS::Handle<JSObject*> aIID, ErrorResult& aRv)
   {
     aRv.Throw(NS_ERROR_FAILURE);
     return JSVAL_NULL;
   }
--- a/dom/workers/XMLHttpRequestUpload.cpp
+++ b/dom/workers/XMLHttpRequestUpload.cpp
@@ -11,17 +11,17 @@
 
 USING_WORKERS_NAMESPACE
 
 // static
 XMLHttpRequestUpload*
 XMLHttpRequestUpload::Create(JSContext* aCx, XMLHttpRequest* aXHR)
 {
   nsRefPtr<XMLHttpRequestUpload> upload = new XMLHttpRequestUpload(aCx, aXHR);
-  return Wrap(aCx, NULL, upload) ? upload : NULL;
+  return Wrap(aCx, nullptr, upload) ? upload : nullptr;
 }
 
 void
 XMLHttpRequestUpload::_trace(JSTracer* aTrc)
 {
   if (mXHR) {
     mXHR->TraceJSObject(aTrc, "mXHR");
   }
--- a/gfx/angle/Makefile.in
+++ b/gfx/angle/Makefile.in
@@ -1,16 +1,12 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
-
 # The below is a rough translation of build_angle.gypi:
 DEFINES += -DANGLE_DISABLE_TRACE
 DEFINES += -DANGLE_COMPILE_OPTIMIZATION_LEVEL=D3DCOMPILE_OPTIMIZATION_LEVEL1
 
 # Target: 'preprocessor'
 # src/compiler/preprocessor:
 VPATH += $(srcdir)/src/compiler/preprocessor
 
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -115,8 +115,11 @@ SOURCES += ['src/compiler/' + src for sr
     'TranslatorESSL.cpp',
     'TranslatorGLSL.cpp',
     'VersionGLSL.cpp',
 ]]
 
 LIBRARY_NAME = 'angle'
 LIBXUL_LIBRARY = True
 MSVC_ENABLE_PGO = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/gfx/graphite2/src/Makefile.in
+++ b/gfx/graphite2/src/Makefile.in
@@ -11,17 +11,16 @@ else
 _MACHINE = call
 endif
 
 # get the lists of source files and exported headers
 include $(srcdir)/files.mk
 
 # on Windows, we're going to link graphite with gkmedias instead of libxul
 ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
 endif
 
 ifeq (WINNT,$(OS_TARGET))
 DEFINES += -DGRAPHITE2_EXPORTING
 else
 # tell graphite2 not to export symbols, we'll be linking it directly with thebes
 DEFINES += -DGRAPHITE2_STATIC
 endif
--- a/gfx/graphite2/src/moz.build
+++ b/gfx/graphite2/src/moz.build
@@ -61,8 +61,10 @@ SOURCES += [
     'TtfUtil.cpp',
     'UtfCodec.cpp',
 ]
 
 LIBRARY_NAME = 'mozgraphite2'
 
 MSVC_ENABLE_PGO = True
 
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/gfx/layers/ipc/GestureEventListener.cpp
+++ b/gfx/layers/ipc/GestureEventListener.cpp
@@ -144,57 +144,56 @@ nsEventStatus GestureEventListener::Hand
           foundAlreadyExistingTouch = true;
           mTouches.RemoveElementAt(j);
         }
       }
     }
 
     NS_WARN_IF_FALSE(foundAlreadyExistingTouch, "Touch ended, but not in list");
 
-    if (event.mTime - mTapStartTime <= MAX_TAP_TIME) {
-      if (mState == GESTURE_WAITING_DOUBLE_TAP &&
-          event.mTime - mLastTapEndTime > MAX_TAP_TIME) {
-        // mDoubleTapTimeoutTask wasn't scheduled in time. We need to run the
-        // task synchronously to confirm the last tap.
-        CancelDoubleTapTimeoutTask();
+    if (mState == GESTURE_WAITING_DOUBLE_TAP) {
+      CancelDoubleTapTimeoutTask();
+      if (mTapStartTime - mLastTapEndTime > MAX_TAP_TIME ||
+          event.mTime - mTapStartTime > MAX_TAP_TIME) {
+        // Either the time between taps or the last tap took too long
+        // confirm previous tap and handle current tap seperately
         TimeoutDoubleTap();
-
-        // Change the state so we can proceed to process the current tap.
         mState = GESTURE_WAITING_SINGLE_TAP;
-      }
-
-      if (mState == GESTURE_WAITING_DOUBLE_TAP) {
-        CancelDoubleTapTimeoutTask();
+      } else {
         // We were waiting for a double tap and it has arrived.
         HandleDoubleTap(event);
         mState = GESTURE_NONE;
-      } else if (mState == GESTURE_WAITING_SINGLE_TAP) {
-        CancelLongTapTimeoutTask();
-        HandleSingleTapUpEvent(event);
-
-        // We were not waiting for anything but a single tap has happened that
-        // may turn into a double tap. Wait a while and if it doesn't turn into
-        // a double tap, send a single tap instead.
-        mState = GESTURE_WAITING_DOUBLE_TAP;
-
-        mDoubleTapTimeoutTask =
-          NewRunnableMethod(this, &GestureEventListener::TimeoutDoubleTap);
-
-        mAsyncPanZoomController->PostDelayedTask(
-          mDoubleTapTimeoutTask,
-          MAX_TAP_TIME);
       }
-
-      mLastTapEndTime = event.mTime;
     }
 
-    if (mState == GESTURE_WAITING_SINGLE_TAP) {
+    if (mState == GESTURE_WAITING_SINGLE_TAP &&
+        event.mTime - mTapStartTime > MAX_TAP_TIME) {
+      // Extended taps are immediately dispatched as single taps
+      CancelLongTapTimeoutTask();
+      HandleSingleTapConfirmedEvent(event);
       mState = GESTURE_NONE;
+    } else if (mState == GESTURE_WAITING_SINGLE_TAP) {
+      CancelLongTapTimeoutTask();
+      HandleSingleTapUpEvent(event);
+
+      // We were not waiting for anything but a single tap has happened that
+      // may turn into a double tap. Wait a while and if it doesn't turn into
+      // a double tap, send a single tap instead.
+      mState = GESTURE_WAITING_DOUBLE_TAP;
+
+      mDoubleTapTimeoutTask =
+        NewRunnableMethod(this, &GestureEventListener::TimeoutDoubleTap);
+
+      mAsyncPanZoomController->PostDelayedTask(
+        mDoubleTapTimeoutTask,
+        MAX_TAP_TIME);
     }
 
+    mLastTapEndTime = event.mTime;
+
     if (!mTouches.Length()) {
       mSpanChange = 0.0f;
     }
 
     break;
   }
   case MultiTouchInput::MULTITOUCH_CANCEL:
     // This gets called if there's a touch that has to bail for weird reasons
--- a/gfx/ots/src/Makefile.in
+++ b/gfx/ots/src/Makefile.in
@@ -21,17 +21,16 @@
 # ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
 # PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 #
 # Mozilla author(s): Jonathan Kew
 #
 
 
 ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
 endif
 
 CSRCS =   \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -DPACKAGE_VERSION="\"moz\""
--- a/gfx/ots/src/moz.build
+++ b/gfx/ots/src/moz.build
@@ -49,8 +49,10 @@ SOURCES += [
     'vmtx.cc',
     'vorg.cc',
 ]
 
 LIBRARY_NAME = 'mozots'
 
 MSVC_ENABLE_PGO = True
 
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/hal/windows/WindowsGamepad.cpp
+++ b/hal/windows/WindowsGamepad.cpp
@@ -227,39 +227,46 @@ public:
   NS_DECL_NSIOBSERVER
 
   Observer(WindowsGamepadService& svc) : mSvc(svc),
                                          mObserving(true) {
     nsresult rv;
     mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
     nsCOMPtr<nsIObserverService> observerService =
       mozilla::services::GetObserverService();
-    observerService->AddObserver(this, "devices-changed", false);
     observerService->AddObserver(this,
                                  NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID,
                                  false);
   }
 
   void Stop() {
     if (mTimer) {
       mTimer->Cancel();
     }
     if (mObserving) {
       nsCOMPtr<nsIObserverService> observerService =
         mozilla::services::GetObserverService();
-      observerService->RemoveObserver(this, "devices-changed");
       observerService->RemoveObserver(this, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID);
       mObserving = false;
     }
   }
 
   virtual ~Observer() {
     Stop();
   }
 
+  void SetDeviceChangeTimer() {
+    // set stable timer, since we will get multiple devices-changed
+    // notifications at once
+    if (mTimer) {
+      mTimer->Cancel();
+      mTimer->Init(this, kDevicesChangedStableDelay, nsITimer::TYPE_ONE_SHOT);
+    }
+  }
+
 private:
   // Gamepad service owns us, we just hold a reference back to it.
   WindowsGamepadService& mSvc;
   nsCOMPtr<nsITimer> mTimer;
   bool mObserving;
 };
 
 NS_IMPL_ISUPPORTS1(Observer, nsIObserver);
@@ -272,17 +279,21 @@ public:
     CloseHandle(mThreadExitEvent);
     CloseHandle(mThreadRescanEvent);
     if (dinput) {
       dinput->Release();
       dinput = nullptr;
     }
   }
 
-  void DevicesChanged();
+  enum DeviceChangeType {
+    DeviceChangeNotification,
+    DeviceChangeStable
+  };
+  void DevicesChanged(DeviceChangeType type);
   void Startup();
   void Shutdown();
 
 private:
   void ScanForDevices();
   void Cleanup();
   void CleanupGamepad(Gamepad& gamepad);
   // Callback for enumerating axes on a device
@@ -584,60 +595,98 @@ WindowsGamepadService::Cleanup() {
 void
 WindowsGamepadService::CleanupGamepad(Gamepad& gamepad) {
   gamepad.device->Unacquire();
   gamepad.device->SetEventNotification(nullptr);
   CloseHandle(gamepad.event);
 }
 
 void
-WindowsGamepadService::DevicesChanged() {
-  SetEvent(mThreadRescanEvent);
+WindowsGamepadService::DevicesChanged(DeviceChangeType type) {
+  if (type == DeviceChangeNotification) {
+    mObserver->SetDeviceChangeTimer();
+  } else if (type == DeviceChangeStable) {
+    SetEvent(mThreadRescanEvent);
+  }
 }
 
 NS_IMETHODIMP
 Observer::Observe(nsISupports* aSubject,
                   const char* aTopic,
                   const PRUnichar* aData) {
   if (strcmp(aTopic, "timer-callback") == 0) {
-    mSvc.DevicesChanged();
+    mSvc.DevicesChanged(WindowsGamepadService::DeviceChangeStable);
   } else if (strcmp(aTopic, NS_XPCOM_WILL_SHUTDOWN_OBSERVER_ID) == 0) {
     Stop();
-  } else if (strcmp(aTopic, "devices-changed")) {
-    // set stable timer, since we will get multiple devices-changed
-    // notifications at once
-    if (mTimer) {
-      mTimer->Cancel();
-      mTimer->Init(this, kDevicesChangedStableDelay, nsITimer::TYPE_ONE_SHOT);
+  }
+  return NS_OK;
+}
+
+WindowsGamepadService* gService = nullptr;
+HWND sHWnd = nullptr;
+
+static
+LRESULT CALLBACK
+GamepadWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+  const unsigned int DBT_DEVICEARRIVAL        = 0x8000;
+  const unsigned int DBT_DEVICEREMOVECOMPLETE = 0x8004;
+  const unsigned int DBT_DEVNODES_CHANGED     = 0x7;
+
+  if (msg == WM_DEVICECHANGE &&
+      (wParam == DBT_DEVICEARRIVAL ||
+       wParam == DBT_DEVICEREMOVECOMPLETE ||
+       wParam == DBT_DEVNODES_CHANGED)) {
+    if (gService) {
+      gService->DevicesChanged(WindowsGamepadService::DeviceChangeNotification);
     }
   }
-  return NS_OK;
+  return DefWindowProc(hwnd, msg, wParam, lParam);
 }
 
 } // namespace
 
 namespace mozilla {
 namespace hal_impl {
 
-WindowsGamepadService* gService = nullptr;
-
 void StartMonitoringGamepadStatus()
 {
   if (gService)
     return;
 
   gService = new WindowsGamepadService();
   gService->Startup();
+
+  if (sHWnd == nullptr) {
+    WNDCLASSW wc;
+    HMODULE hSelf = GetModuleHandle(nullptr);
+
+    if (!GetClassInfoW(hSelf, L"MozillaGamepadClass", &wc)) {
+      ZeroMemory(&wc, sizeof(WNDCLASSW));
+      wc.hInstance = hSelf;
+      wc.lpfnWndProc = GamepadWindowProc;
+      wc.lpszClassName = L"MozillaGamepadClass";
+      RegisterClassW(&wc);
+    }
+
+    sHWnd = CreateWindowW(L"MozillaGamepadClass", L"Gamepad Watcher",
+                          0, 0, 0, 0, 0,
+                          nullptr, nullptr, hSelf, nullptr);
+  }
 }
 
 void StopMonitoringGamepadStatus()
 {
   if (!gService)
     return;
 
+  if (sHWnd) {
+    DestroyWindow(sHWnd);
+    sHWnd = nullptr;
+  }
+
   gService->Shutdown();
   delete gService;
   gService = nullptr;
 }
 
 } // namespace hal_impl
 } // namespace mozilla
 
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -317,16 +317,17 @@ private:
         OP2_MOVSX_GvEb      = 0xBE,
         OP2_MOVSX_GvEw      = 0xBF,
         OP2_MOVZX_GvEb      = 0xB6,
         OP2_MOVZX_GvEw      = 0xB7,
         OP2_PEXTRW_GdUdIb   = 0xC5
     } TwoByteOpcodeID;
 
     typedef enum {
+        OP3_ROUNDSS_VsdWsd  = 0x0A,
         OP3_ROUNDSD_VsdWsd  = 0x0B,
         OP3_PTEST_VdVd      = 0x17,
         OP3_PINSRD_VsdWsd   = 0x22
     } ThreeByteOpcodeID;
 
     typedef enum {
         ESCAPE_PTEST        = 0x38,
         ESCAPE_PINSRD       = 0x3A,
@@ -516,17 +517,18 @@ public:
     {
         spew("addl       %s0x%x(%s), %s",
              PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4,dst));
         m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset);
     }
 
     void addl_rm(RegisterID src, int offset, RegisterID base)
     {
-        FIXME_INSN_PRINTING;
+        spew("addl       %s, %s0x%x(%s)",
+             nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_ADD_EvGv, src, base, offset);
     }
 
     void addl_ir(int imm, RegisterID dst)
     {
         spew("addl       $0x%x, %s", imm, nameIReg(4,dst));
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
@@ -632,17 +634,18 @@ public:
     {
         spew("andl       %s0x%x(%s), %s",
              PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4,dst));
         m_formatter.oneByteOp(OP_AND_GvEv, dst, base, offset);
     }
 
     void andl_rm(RegisterID src, int offset, RegisterID base)
     {
-        FIXME_INSN_PRINTING;
+        spew("andl       %s, %s0x%x(%s)",
+             nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_AND_EvGv, src, base, offset);
     }
 
     void andl_ir(int imm, RegisterID dst)
     {
         spew("andl       $0x%x, %s", imm, nameIReg(4,dst));
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
@@ -735,16 +738,21 @@ public:
         spew("fisttp     %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_FPU6, FPU6_OP_FISTTP, base, offset);
     }
     void fstp_m(int offset, RegisterID base)
     {
         spew("fstp       %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_FPU6, FPU6_OP_FSTP, base, offset);
     }
+    void fstp32_m(int offset, RegisterID base)
+    {
+        spew("fstp32       %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base));
+        m_formatter.oneByteOp(OP_FLD32, FPU6_OP_FSTP, base, offset);
+    }
 
     void negl_r(RegisterID dst)
     {
         spew("negl       %s", nameIReg(4,dst));
         m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NEG, dst);
     }
 
     void negl_m(int offset, RegisterID base)
@@ -769,23 +777,25 @@ public:
     {
         spew("orl        %s, %s",
              nameIReg(4,src), nameIReg(4,dst));
         m_formatter.oneByteOp(OP_OR_EvGv, src, dst);
     }
 
     void orl_mr(int offset, RegisterID base, RegisterID dst)
     {
-        FIXME_INSN_PRINTING;
+        spew("orl        %s0x%x(%s), %s",
+             PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4,dst));
         m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset);
     }
 
     void orl_rm(RegisterID src, int offset, RegisterID base)
     {
-        FIXME_INSN_PRINTING;
+        spew("orl        %s, %s0x%x(%s)",
+             nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_OR_EvGv, src, base, offset);
     }
 
     void orl_ir(int imm, RegisterID dst)
     {
         spew("orl        $0x%x, %s", imm, nameIReg(4,dst));
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
@@ -865,17 +875,18 @@ public:
     {
         spew("subl       %s0x%x(%s), %s",
              PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4,dst));
         m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset);
     }
 
     void subl_rm(RegisterID src, int offset, RegisterID base)
     {
-        FIXME_INSN_PRINTING;
+        spew("subl       %s, %s0x%x(%s)",
+             nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_SUB_EvGv, src, base, offset);
     }
 
     void subl_ir(int imm, RegisterID dst)
     {
         spew("subl       $0x%x, %s", imm, nameIReg(4, dst));
         if (CAN_SIGN_EXTEND_8_32(imm)) {
             m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
@@ -950,23 +961,25 @@ public:
     {
         spew("xorl       %s, %s",
              nameIReg(4,src), nameIReg(4,dst));
         m_formatter.oneByteOp(OP_XOR_EvGv, src, dst);
     }
 
     void xorl_mr(int offset, RegisterID base, RegisterID dst)
     {
-        FIXME_INSN_PRINTING;
+        spew("xorl       %s0x%x(%s), %s",
+             PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4,dst));
         m_formatter.oneByteOp(OP_XOR_GvEv, dst, base, offset);
     }
 
     void xorl_rm(RegisterID src, int offset, RegisterID base)
     {
-        FIXME_INSN_PRINTING;
+        spew("xorl       %s, %s0x%x(%s)",
+             nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_XOR_EvGv, src, base, offset);
     }
 
     void xorl_im(int imm, int offset, RegisterID base)
     {
         spew("xorl       $0x%x, %s0x%x(%s)",
              imm, PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         if (CAN_SIGN_EXTEND_8_32(imm)) {
@@ -1583,17 +1596,18 @@ public:
     {
         spew("movl       %s, %s0x%x(%s)",
              nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
     }
 
     void movl_rm_disp32(RegisterID src, int offset, RegisterID base)
     {
-        FIXME_INSN_PRINTING;
+        spew("movl       %s, %s0x%x(%s)",
+             nameIReg(4,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset);
     }
 
     void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
     {
         spew("movl       %s, %d(%s,%s,%d)",
              nameIReg(4, src), offset, nameIReg(base), nameIReg(index), 1<<scale);
         m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
@@ -1614,17 +1628,18 @@ public:
     {
         spew("movl       %s0x%x(%s), %s",
              PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4, dst));
         m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, offset);
     }
 
     void movl_mr_disp32(int offset, RegisterID base, RegisterID dst)
     {
-        FIXME_INSN_PRINTING;
+        spew("movl       %s0x%x(%s), %s",
+             PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameIReg(4,dst));
         m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset);
     }
 
     void movl_mr(const void* base, RegisterID index, int scale, RegisterID dst)
     {
         int32_t disp = addressImmediate(base);
 
         spew("movl       %d(,%s,%d), %s",
@@ -1745,22 +1760,24 @@ public:
     {
         spew("movq       %s, %s0x%x(%s)",
              nameIReg(8,src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
     }
 
     void movq_rm(RegisterID src, const void* addr)
     {
+        if (src == X86Registers::eax) {
+            movq_EAXm(addr);
+            return;
+        }
+
         spew("movq       %s, %p",
              nameIReg(8, src), addr);
-        if (src == X86Registers::eax)
-            movq_EAXm(addr);
-        else
-            m_formatter.oneByteOp64(OP_MOV_EvGv, src, addr);
+        m_formatter.oneByteOp64(OP_MOV_EvGv, src, addr);
     }
 
     void movq_mEAX(const void* addr)
     {
         spew("movq       %p, %%rax", addr);
         m_formatter.oneByteOp64(OP_MOV_EAXOv);
         m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
     }
@@ -1789,22 +1806,24 @@ public:
     {
         spew("movq       %d(%s,%s,%d), %s",
              offset, nameIReg(base), nameIReg(index), 1<<scale, nameIReg(8,dst));
         m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
     }
 
     void movq_mr(const void* addr, RegisterID dst)
     {
+        if (dst == X86Registers::eax) {
+            movq_mEAX(addr);
+            return;
+        }
+
         spew("movq       %p, %s",
              addr, nameIReg(8, dst));
-        if (dst == X86Registers::eax)
-            movq_mEAX(addr);
-        else
-            m_formatter.oneByteOp64(OP_MOV_GvEv, dst, addr);
+        m_formatter.oneByteOp64(OP_MOV_GvEv, dst, addr);
     }
 
     void leaq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
     {
         spew("leaq       %d(%s,%s,%d), %s",
              offset, nameIReg(base), nameIReg(index), 1<<scale, nameIReg(8,dst)),
         m_formatter.oneByteOp64(OP_LEA, dst, base, index, scale, offset);
     }
@@ -2933,16 +2952,25 @@ public:
     {
         spew("roundsd    %s, %s, %d",
              nameFPReg(src), nameFPReg(dst), (int)mode);
         m_formatter.prefix(PRE_SSE_66);
         m_formatter.threeByteOp(OP3_ROUNDSD_VsdWsd, ESCAPE_ROUNDSD, (RegisterID)dst, (RegisterID)src);
         m_formatter.immediate8(mode);
     }
 
+    void roundss_rr(XMMRegisterID src, XMMRegisterID dst, RoundingMode mode)
+    {
+        spew("roundss    %s, %s, %d",
+             nameFPReg(src), nameFPReg(dst), (int)mode);
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.threeByteOp(OP3_ROUNDSS_VsdWsd, ESCAPE_ROUNDSD, (RegisterID)dst, (RegisterID)src);
+        m_formatter.immediate8(mode); // modes are the same for roundsd and roundss
+    }
+
     void pinsrd_rr(RegisterID src, XMMRegisterID dst)
     {
         spew("pinsrd     $1, %s, %s",
              nameIReg(src), nameFPReg(dst));
         m_formatter.prefix(PRE_SSE_66);
         m_formatter.threeByteOp(OP3_PINSRD_VsdWsd, ESCAPE_PINSRD, (RegisterID)dst, (RegisterID)src);
         m_formatter.immediate8(0x01); // the $1
     }
--- a/js/src/builtin/ParallelArray.js
+++ b/js/src/builtin/ParallelArray.js
@@ -786,20 +786,20 @@ function ParallelArrayScatter(targets, d
   //
   // The unanswered question is which strategy performs better when
   // |targets.length| approximately equals |length|, especially for
   // special cases like collision-free scatters and permutations.
 
   var targetsLength = std_Math_min(targets.length, self.shape[0]);
 
   if (targetsLength >>> 0 !== targetsLength)
-    ThrowError(JSMSG_BAD_ARRAY_LENGTH, ".prototype.scatter");
+    ThrowError(JSMSG_PAR_ARRAY_BAD_ARG, ".prototype.scatter length");
 
   if (length >>> 0 !== length)
-    ThrowError(JSMSG_BAD_ARRAY_LENGTH, ".prototype.scatter");
+    ThrowError(JSMSG_PAR_ARRAY_BAD_ARG, ".prototype.scatter length");
 
   parallel: for (;;) { // see ParallelArrayBuild() to explain why for(;;) etc
     if (ShouldForceSequential())
       break parallel;
     if (!TRY_PARALLEL(mode))
       break parallel;
 
     if (forceDivideScatterVector())
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1301,17 +1301,17 @@ Deserialize(JSContext *cx, unsigned argc
     }
 
     bool hasTransferable;
     if (!JS_StructuredCloneHasTransferables(obj->data(), obj->nbytes(), &hasTransferable))
         return false;
 
     RootedValue deserialized(cx);
     if (!JS_ReadStructuredClone(cx, obj->data(), obj->nbytes(),
-                                JS_STRUCTURED_CLONE_VERSION, &deserialized, NULL, NULL)) {
+                                JS_STRUCTURED_CLONE_VERSION, &deserialized, nullptr, nullptr)) {
         return false;
     }
     args.rval().set(deserialized);
 
     if (hasTransferable)
         obj->discard();
 
     return true;
--- a/js/src/builtin/TypedObject.cpp
+++ b/js/src/builtin/TypedObject.cpp
@@ -338,17 +338,17 @@ TypeEquivalent(JSContext *cx, unsigned i
     nullptr,                                                                  \
     NumericType<constant_, type_>::call,                                      \
     nullptr,                                                                  \
     nullptr,                                                                  \
     nullptr                                                                   \
 },
 
 static const JSFunctionSpec NumericTypeObjectMethods[] = {
-    {"handle", {NULL, NULL}, 2, 0, "HandleCreate"},
+    {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
     JS_FS_END
 };
 
 const Class js::NumericTypeClasses[ScalarTypeRepresentation::TYPE_MAX] = {
     JS_FOR_EACH_SCALAR_TYPE_REPR(BINARYDATA_NUMERIC_CLASSES)
 };
 
 template <typename T>
@@ -541,17 +541,17 @@ const Class ArrayType::class_ = {
     nullptr
 };
 
 const JSPropertySpec ArrayType::typeObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec ArrayType::typeObjectMethods[] = {
-    {"handle", {NULL, NULL}, 2, 0, "HandleCreate"},
+    {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
     JS_FN("repeat", ArrayType::repeat, 1, 0),
     JS_FN("toSource", ArrayType::toSource, 0, 0),
     JS_FS_END
 };
 
 const JSPropertySpec ArrayType::typedObjectProperties[] = {
     JS_PS_END
 };
@@ -973,17 +973,17 @@ const Class StructType::class_ = {
     nullptr  /* trace */
 };
 
 const JSPropertySpec StructType::typeObjectProperties[] = {
     JS_PS_END
 };
 
 const JSFunctionSpec StructType::typeObjectMethods[] = {
-    {"handle", {NULL, NULL}, 2, 0, "HandleCreate"},
+    {"handle", {nullptr, nullptr}, 2, 0, "HandleCreate"},
     JS_FN("toSource", StructType::toSource, 0, 0),
     JS_FS_END
 };
 
 const JSPropertySpec StructType::typedObjectProperties[] = {
     JS_PS_END
 };
 
@@ -1076,19 +1076,19 @@ StructType::layout(JSContext *cx, Handle
                                   JSPROP_READONLY | JSPROP_PERMANENT))
         return false;
 
     // Construct the fieldNames, fieldOffsets and fieldTypes objects:
     // fieldNames : [ string ]
     // fieldOffsets : { string: integer, ... }
     // fieldTypes : { string: Type, ... }
     RootedObject fieldOffsets(
-        cx, NewObjectWithClassProto(cx, &JSObject::class_, NULL, NULL));
+        cx, NewObjectWithClassProto(cx, &JSObject::class_, nullptr, nullptr));
     RootedObject fieldTypes(
-        cx, NewObjectWithClassProto(cx, &JSObject::class_, NULL, NULL));
+        cx, NewObjectWithClassProto(cx, &JSObject::class_, nullptr, nullptr));
     for (size_t i = 0; i < typeRepr->fieldCount(); i++) {
         const StructField &field = typeRepr->field(i);
         RootedId fieldId(cx, field.id);
 
         // fieldOffsets[id] = offset
         RootedValue offset(cx, NumberValue(field.offset));
         if (!JSObject::defineGeneric(cx, fieldOffsets, fieldId,
                                      offset, nullptr, nullptr,
@@ -1333,28 +1333,28 @@ js_InitTypedObjectClass(JSContext *cx, H
     global->setReservedSlot(JSProto_TypedObject, moduleValue);
     global->setArrayType(arrayType);
     global->markStandardClassInitializedNoProto(&TypedObjectClass);
 
     //  Handle
 
     RootedObject handle(cx, NewBuiltinClassInstance(cx, &JSObject::class_));
     if (!module)
-        return NULL;
+        return nullptr;
 
     if (!JS_DefineFunctions(cx, handle, TypedHandle::handleStaticMethods))
-        return NULL;
+        return nullptr;
 
     RootedValue handleValue(cx, ObjectValue(*handle));
     if (!JSObject::defineProperty(cx, module, cx->names().Handle,
                                   handleValue,
-                                  NULL, NULL,
+                                  nullptr, nullptr,
                                   JSPROP_READONLY | JSPROP_PERMANENT))
     {
-        return NULL;
+        return nullptr;
     }
 
     return module;
 }
 
 JSObject *
 js_InitTypedObjectDummy(JSContext *cx, HandleObject obj)
 {
@@ -1422,17 +1422,17 @@ template<class T>
 TypedDatum::createUnattached(JSContext *cx,
                              HandleObject type)
 {
     JS_STATIC_ASSERT(T::IsTypedDatumClass);
     JS_ASSERT(IsTypeObject(*type));
 
     RootedObject obj(cx, createUnattachedWithClass(cx, &T::class_, type));
     if (!obj)
-        return NULL;
+        return nullptr;
 
     return &obj->as<T>();
 }
 
 /*static*/ TypedDatum *
 TypedDatum::createUnattachedWithClass(JSContext *cx,
                                       const Class *clasp,
                                       HandleObject type)
@@ -1452,19 +1452,19 @@ TypedDatum::createUnattachedWithClass(JS
                                    cx->names().prototype, &protoVal))
         {
             return nullptr;
         }
         proto = &protoVal.toObject();
     }
 
     RootedObject obj(
-        cx, NewObjectWithClassProto(cx, clasp, &*proto, NULL));
+        cx, NewObjectWithClassProto(cx, clasp, &*proto, nullptr));
     if (!obj)
-        return NULL;
+        return nullptr;
 
     obj->setPrivate(nullptr);
     obj->initReservedSlot(JS_DATUM_SLOT_TYPE_OBJ, ObjectValue(*type));
     obj->initReservedSlot(JS_DATUM_SLOT_OWNER, NullValue());
 
     // Tag the type object for this instance with the type
     // representation, if that has not been done already.
     if (cx->typeInferenceEnabled() && !IsNumericTypeObject(*type)) {
@@ -1537,17 +1537,17 @@ ReportDatumTypeError(JSContext *cx,
     RootedString result(cx, contents.finishString());
     if (!result)
         return false;
 
     char *typeReprStr = JS_EncodeString(cx, result.get());
     if (!typeReprStr)
         return false;
 
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                          errorNumber, typeReprStr);
 
     JS_free(cx, (void *) typeReprStr);
     return false;
 }
 
 /*static*/ void
 TypedDatum::obj_trace(JSTracer *trace, JSObject *object)
@@ -2169,20 +2169,20 @@ const Class TypedObject::class_ = {
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     TypedDatum::obj_finalize,
-    NULL,           /* checkAccess */
-    NULL,           /* call        */
-    NULL,           /* construct   */
-    NULL,           /* hasInstance */
+    nullptr,        /* checkAccess */
+    nullptr,        /* call        */
+    nullptr,        /* construct   */
+    nullptr,        /* hasInstance */
     TypedDatum::obj_trace,
     JS_NULL_CLASS_EXT,
     {
         TypedDatum::obj_lookupGeneric,
         TypedDatum::obj_lookupProperty,
         TypedDatum::obj_lookupElement,
         TypedDatum::obj_lookupSpecial,
         TypedDatum::obj_defineGeneric,
@@ -2199,32 +2199,32 @@ const Class TypedObject::class_ = {
         TypedDatum::obj_setElement,
         TypedDatum::obj_setSpecial,
         TypedDatum::obj_getGenericAttributes,
         TypedDatum::obj_setGenericAttributes,
         TypedDatum::obj_deleteProperty,
         TypedDatum::obj_deleteElement,
         TypedDatum::obj_deleteSpecial,
         TypedDatum::obj_enumerate,
-        NULL, /* thisObject */
+        nullptr, /* thisObject */
     }
 };
 
 /*static*/ JSObject *
 TypedObject::createZeroed(JSContext *cx, HandleObject type)
 {
     Rooted<TypedObject*> obj(cx, createUnattached<TypedObject>(cx, type));
     if (!obj)
-        return NULL;
+        return nullptr;
 
     TypeRepresentation *typeRepr = typeRepresentation(*type);
     size_t memsize = typeRepr->size();
     void *memory = JS_malloc(cx, memsize);
     if (!memory)
-        return NULL;
+        return nullptr;
     memset(memory, 0, memsize);
     obj->attach(memory);
     return obj;
 }
 
 /*static*/ bool
 TypedObject::construct(JSContext *cx, unsigned int argc, Value *vp)
 {
@@ -2259,20 +2259,20 @@ const Class TypedHandle::class_ = {
     JS_PropertyStub,
     JS_DeletePropertyStub,
     JS_PropertyStub,
     JS_StrictPropertyStub,
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub,
     TypedDatum::obj_finalize,
-    NULL,           /* checkAccess */
-    NULL,           /* call        */
-    NULL,           /* construct   */
-    NULL,           /* hasInstance */
+    nullptr,        /* checkAccess */
+    nullptr,        /* call        */
+    nullptr,        /* construct   */
+    nullptr,        /* hasInstance */
     TypedDatum::obj_trace,
     JS_NULL_CLASS_EXT,
     {
         TypedDatum::obj_lookupGeneric,
         TypedDatum::obj_lookupProperty,
         TypedDatum::obj_lookupElement,
         TypedDatum::obj_lookupSpecial,
         TypedDatum::obj_defineGeneric,
@@ -2289,25 +2289,25 @@ const Class TypedHandle::class_ = {
         TypedDatum::obj_setElement,
         TypedDatum::obj_setSpecial,
         TypedDatum::obj_getGenericAttributes,
         TypedDatum::obj_setGenericAttributes,
         TypedDatum::obj_deleteProperty,
         TypedDatum::obj_deleteElement,
         TypedDatum::obj_deleteSpecial,
         TypedDatum::obj_enumerate,
-        NULL, /* thisObject */
+        nullptr, /* thisObject */
     }
 };
 
 const JSFunctionSpec TypedHandle::handleStaticMethods[] = {
-    {"move", {NULL, NULL}, 3, 0, "HandleMove"},
-    {"get", {NULL, NULL}, 1, 0, "HandleGet"},
-    {"set", {NULL, NULL}, 2, 0, "HandleSet"},
-    {"isHandle", {NULL, NULL}, 1, 0, "HandleTest"},
+    {"move", {nullptr, nullptr}, 3, 0, "HandleMove"},
+    {"get", {nullptr, nullptr}, 1, 0, "HandleGet"},
+    {"set", {nullptr, nullptr}, 2, 0, "HandleSet"},
+    {"isHandle", {nullptr, nullptr}, 1, 0, "HandleTest"},
     JS_FS_END
 };
 
 ///////////////////////////////////////////////////////////////////////////
 // Intrinsics
 
 bool
 js::NewTypedHandle(JSContext *cx, unsigned argc, Value *vp)
@@ -2421,17 +2421,17 @@ const JSJitInfo js::ObjectIsTypedObjectJ
     JS_JITINFO_NATIVE_PARALLEL(
         JSParallelNativeThreadSafeWrapper<js::ObjectIsTypedObject>);
 
 bool
 js::IsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args[0].isObject() && IsTypedDatum(args[0].toObject()));
-    args.rval().setBoolean(TypedMem(args[0].toObject()) != NULL);
+    args.rval().setBoolean(TypedMem(args[0].toObject()) != nullptr);
     return true;
 }
 
 const JSJitInfo js::IsAttachedJitInfo =
     JS_JITINFO_NATIVE_PARALLEL(
         JSParallelNativeThreadSafeWrapper<js::IsAttached>);
 
 bool
--- a/js/src/builtin/TypedObject.h
+++ b/js/src/builtin/TypedObject.h
@@ -384,17 +384,17 @@ extern const JSJitInfo ObjectIsTypedHand
  */
 bool ObjectIsTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
 extern const JSJitInfo ObjectIsTypedObjectJitInfo;
 
 /*
  * Usage: IsAttached(obj)
  *
  * Given a TypedDatum `obj`, returns true if `obj` is
- * "attached" (i.e., its data pointer is NULL).
+ * "attached" (i.e., its data pointer is nullptr).
  */
 bool IsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp);
 extern const JSJitInfo IsAttachedJitInfo;
 
 /*
  * Usage: ClampToUint8(v)
  *
  * Same as the C function ClampDoubleToUint8. `v` must be a number.
--- a/js/src/config/Makefile.in
+++ b/js/src/config/Makefile.in
@@ -1,17 +1,13 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-# For sanity's sake, we compile nsinstall without the wrapped system
-# headers, so that we can use it to set up the wrapped system headers.
-VISIBILITY_FLAGS =
-
 ifneq (WINNT,$(HOST_OS_ARCH))
 HOST_PROGRAM	= nsinstall_real$(HOST_BIN_SUFFIX)
 endif
 
 # IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have
 # a recursive rule for finding nsinstall and the Perl scripts.
 ifdef NSBUILDROOT
 override NSBUILDROOT :=
--- a/js/src/config/moz.build
+++ b/js/src/config/moz.build
@@ -1,13 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 NO_DIST_INSTALL = True
+# For sanity's sake, we compile nsinstall without the wrapped system
+# headers, so that we can use it to set up the wrapped system headers.
+NO_VISIBILITY_FLAGS = True
 
 if CONFIG['HOST_OS_ARCH'] != 'WINNT':
     HOST_SOURCES += [
         'nsinstall.c',
         'pathsub.c',
     ]
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug930993.js
@@ -0,0 +1,6 @@
+x = {};
+y = x;
+x.toString = function() {
+    Int8Array(ArrayBuffer)[0] = Float32Array(ArrayBuffer)[0];
+}
+print(x << y);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug931496.js
@@ -0,0 +1,11 @@
+
+function g() {
+    yield
+}
+g()
+function f() {
+    g()
+}
+try {
+    new f
+} catch (e) {}
--- a/js/src/jit-test/tests/ion/testFloat32-correctness.js
+++ b/js/src/jit-test/tests/ion/testFloat32-correctness.js
@@ -222,8 +222,46 @@ test(setupTrigo, trigo);
 function otherMath() {
     for (var i = 0; i < 10; ++i) {
         assertNear(Math.fround(Math.exp(f32[i])), Math.exp(f32[i]));
         assertNear(Math.fround(Math.log(f32[i])), Math.log(f32[i]));
     }
 };
 test(setupComp, otherMath);
 
+function setupFloor() {
+    f32[0] = -5.5;
+    f32[1] = -0.5;
+    f32[2] = 0;
+    f32[3] = 1.5;
+}
+function setupFloorDouble() {
+    f32[4] = NaN;
+    f32[5] = -0;
+    f32[6] = Infinity;
+    f32[7] = -Infinity;
+    f32[8] = Math.pow(2,31); // too big to fit into a int
+}
+function testFloor() {
+    for (var i = 0; i < 4; ++i) {
+        var f = Math.floor(f32[i]);
+        assertFloat32(g, false); // f is an int32
+
+        var g = Math.floor(-0 + f32[i]);
+        assertFloat32(g, false);
+
+        assertEq(f, g);
+    }
+}
+function testFloorDouble() {
+    for (var i = 4; i < 9; ++i) {
+        var f = Math.fround(Math.floor(f32[i]));
+        assertFloat32(f, true);
+
+        var g = Math.floor(-0 + f32[i]);
+        assertFloat32(g, false);
+
+        assertEq(f, g);
+    }
+}
+test(setupFloor, testFloor);
+test(setupFloorDouble, testFloorDouble);
+
--- a/js/src/jit/AsmJSLink.cpp
+++ b/js/src/jit/AsmJSLink.cpp
@@ -678,17 +678,17 @@ js::NewAsmJSModuleFunction(ExclusiveCont
 
 bool
 js::IsAsmJSModuleNative(js::Native native)
 {
     return native == LinkAsmJS;
 }
 
 static bool
-IsMaybeWrappedNativeFunction(const Value &v, Native native, JSFunction **fun = NULL)
+IsMaybeWrappedNativeFunction(const Value &v, Native native, JSFunction **fun = nullptr)
 {
     if (!v.isObject())
         return false;
 
     JSObject *obj = CheckedUnwrap(&v.toObject());
     if (!obj)
         return false;
 
@@ -712,17 +712,17 @@ js::IsAsmJSModule(JSContext *cx, unsigne
 
 bool
 js::IsAsmJSModuleLoadedFromCache(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     JSFunction *fun;
     if (!args.hasDefined(0) || !IsMaybeWrappedNativeFunction(args[0], LinkAsmJS, &fun)) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_USE_ASM_TYPE_FAIL,
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_USE_ASM_TYPE_FAIL,
                              "argument passed to isAsmJSModuleLoadedFromCache is not a "
                              "validated asm.js module");
         return false;
     }
 
     JSObject &moduleObj = fun->getExtendedSlot(MODULE_FUN_SLOT).toObject();
     bool loadedFromCache = moduleObj.as<AsmJSModuleObject>().module().loadedFromCache();
 
--- a/js/src/jit/AsmJSModule.cpp
+++ b/js/src/jit/AsmJSModule.cpp
@@ -457,35 +457,35 @@ SerializeName(uint8_t *cursor, PropertyN
 
 static const uint8_t *
 DeserializeName(ExclusiveContext *cx, const uint8_t *cursor, PropertyName **name)
 {
     uint32_t length;
     cursor = ReadScalar<uint32_t>(cursor, &length);
 
     if (length == 0) {
-        *name = NULL;
+        *name = nullptr;
         return cursor;
     }
 
     Vector<jschar> tmp(cx);
     jschar *src;
     if ((size_t(cursor) & (sizeof(jschar) - 1)) != 0) {
         // Align 'src' for AtomizeChars.
         if (!tmp.resize(length))
-            return NULL;
+            return nullptr;
         memcpy(tmp.begin(), cursor, length * sizeof(jschar));
         src = tmp.begin();
     } else {
         src = (jschar *)cursor;
     }
 
     JSAtom *atom = AtomizeChars<CanGC>(cx, src, length);
     if (!atom)
-        return NULL;
+        return nullptr;
 
     *name = atom->asPropertyName();
     return cursor + length * sizeof(jschar);
 }
 
 template <class T>
 size_t
 SerializedVectorSize(const Vector<T, 0, SystemAllocPolicy> &vec)
@@ -508,20 +508,20 @@ SerializeVector(uint8_t *cursor, const V
 
 template <class T>
 const uint8_t *
 DeserializeVector(ExclusiveContext *cx, const uint8_t *cursor, Vector<T, 0, SystemAllocPolicy> *vec)
 {
     uint32_t length;
     cursor = ReadScalar<uint32_t>(cursor, &length);
     if (!vec->resize(length))
-        return NULL;
+        return nullptr;
     for (size_t i = 0; i < vec->length(); i++) {
         if (!(cursor = (*vec)[i].deserialize(cx, cursor)))
-            return NULL;
+            return nullptr;
     }
     return cursor;
 }
 
 template <class T, class AllocPolicy, class ThisVector>
 size_t
 SerializedPodVectorSize(const mozilla::VectorBase<T, 0, AllocPolicy, ThisVector> &vec)
 {
@@ -541,17 +541,17 @@ SerializePodVector(uint8_t *cursor, cons
 template <class T, class AllocPolicy, class ThisVector>
 const uint8_t *
 DeserializePodVector(ExclusiveContext *cx, const uint8_t *cursor,
                      mozilla::VectorBase<T, 0, AllocPolicy, ThisVector> *vec)
 {
     uint32_t length;
     cursor = ReadScalar<uint32_t>(cursor, &length);
     if (!vec->resize(length))
-        return NULL;
+        return nullptr;
     cursor = ReadBytes(cursor, vec->begin(), length * sizeof(T));
     return cursor;
 }
 
 uint8_t *
 AsmJSModule::Global::serialize(uint8_t *cursor) const
 {
     cursor = WriteBytes(cursor, &pod, sizeof(pod));
@@ -771,17 +771,17 @@ class MachineId
     }
 };
 
 struct PropertyNameWrapper
 {
     PropertyName *name;
 
     PropertyNameWrapper()
-      : name(NULL)
+      : name(nullptr)
     {}
     PropertyNameWrapper(PropertyName *name)
       : name(name)
     {}
     size_t serializedSize() const {
         return SerializedNameSize(name);
     }
     uint8_t *serialize(uint8_t *cursor) const {
@@ -892,17 +892,17 @@ class ModuleChars
 struct ScopedCacheEntryOpenedForWrite
 {
     ExclusiveContext *cx;
     const size_t serializedSize;
     uint8_t *memory;
     intptr_t handle;
 
     ScopedCacheEntryOpenedForWrite(ExclusiveContext *cx, size_t serializedSize)
-      : cx(cx), serializedSize(serializedSize), memory(NULL), handle(-1)
+      : cx(cx), serializedSize(serializedSize), memory(nullptr), handle(-1)
     {}
 
     ~ScopedCacheEntryOpenedForWrite() {
         if (memory)
             cx->asmJSCacheOps().closeEntryForWrite(cx->global(), serializedSize, memory, handle);
     }
 };
 
@@ -945,17 +945,17 @@ js::StoreAsmJSModuleInCache(AsmJSParser 
 struct ScopedCacheEntryOpenedForRead
 {
     ExclusiveContext *cx;
     size_t serializedSize;
     const uint8_t *memory;
     intptr_t handle;
 
     ScopedCacheEntryOpenedForRead(ExclusiveContext *cx)
-      : cx(cx), serializedSize(0), memory(NULL), handle(0)
+      : cx(cx), serializedSize(0), memory(nullptr), handle(0)
     {}
 
     ~ScopedCacheEntryOpenedForRead() {
         if (memory)
             cx->asmJSCacheOps().closeEntryForRead(cx->global(), serializedSize, memory, handle);
     }
 };
 
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -5369,20 +5369,16 @@ TryAttachScopeNameStub(JSContext *cx, Ha
             break;
 
         scopeChain = scopeChain->enclosingScope();
     }
 
     if (!IsCacheableGetPropReadSlot(scopeChain, scopeChain, shape))
         return true;
 
-    // Instantiate properties on singleton scope chain objects, for use during Ion compilation.
-    if (scopeChain->hasSingletonType() && IsIonEnabled(cx))
-        types::EnsureTrackPropertyTypes(cx, scopeChain, NameToId(name));
-
     bool isFixedSlot;
     uint32_t offset;
     GetFixedOrDynamicSlotOffset(scopeChain, shape->slot(), &isFixedSlot, &offset);
 
     ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
     ICStub *newStub;
 
     switch (shapes.length()) {
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -3894,29 +3894,30 @@ CodeGenerator::visitMathFunctionF(LMathF
     FloatRegister input = ToFloatRegister(ins->input());
     JS_ASSERT(ToFloatRegister(ins->output()) == ReturnFloatReg);
 
     masm.setupUnalignedABICall(1, temp);
     masm.passABIArg(input);
 
     void *funptr = nullptr;
     switch (ins->mir()->function()) {
-      case MMathFunction::Log:  funptr = JS_FUNC_TO_DATA_PTR(void *, logf);  break;
-      case MMathFunction::Sin:  funptr = JS_FUNC_TO_DATA_PTR(void *, sinf);  break;
-      case MMathFunction::Cos:  funptr = JS_FUNC_TO_DATA_PTR(void *, cosf);  break;
-      case MMathFunction::Exp:  funptr = JS_FUNC_TO_DATA_PTR(void *, expf);  break;
-      case MMathFunction::Tan:  funptr = JS_FUNC_TO_DATA_PTR(void *, tanf);  break;
-      case MMathFunction::ATan: funptr = JS_FUNC_TO_DATA_PTR(void *, atanf); break;
-      case MMathFunction::ASin: funptr = JS_FUNC_TO_DATA_PTR(void *, sinf);  break;
-      case MMathFunction::ACos: funptr = JS_FUNC_TO_DATA_PTR(void *, acosf); break;
+      case MMathFunction::Log:   funptr = JS_FUNC_TO_DATA_PTR(void *, logf);   break;
+      case MMathFunction::Sin:   funptr = JS_FUNC_TO_DATA_PTR(void *, sinf);   break;
+      case MMathFunction::Cos:   funptr = JS_FUNC_TO_DATA_PTR(void *, cosf);   break;
+      case MMathFunction::Exp:   funptr = JS_FUNC_TO_DATA_PTR(void *, expf);   break;
+      case MMathFunction::Tan:   funptr = JS_FUNC_TO_DATA_PTR(void *, tanf);   break;
+      case MMathFunction::ATan:  funptr = JS_FUNC_TO_DATA_PTR(void *, atanf);  break;
+      case MMathFunction::ASin:  funptr = JS_FUNC_TO_DATA_PTR(void *, sinf);   break;
+      case MMathFunction::ACos:  funptr = JS_FUNC_TO_DATA_PTR(void *, acosf);  break;
+      case MMathFunction::Floor: funptr = JS_FUNC_TO_DATA_PTR(void *, floorf); break;
       default:
         MOZ_ASSUME_UNREACHABLE("Unknown or unsupported float32 math function");
     }
 
-    masm.callWithABI(funptr, MacroAssembler::DOUBLE);
+    masm.callWithABI(funptr, MacroAssembler::FLOAT);
     return true;
 }
 
 bool
 CodeGenerator::visitModD(LModD *ins)
 {
     FloatRegister lhs = ToFloatRegister(ins->lhs());
     FloatRegister rhs = ToFloatRegister(ins->rhs());
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1548,28 +1548,61 @@ OffThreadCompilationAvailable(JSContext 
     // stores strings in the spsProfiler data structure, which is not protected
     // by a lock.
     return OffThreadIonCompilationEnabled(cx->runtime())
         && cx->runtime()->gcIncrementalState == gc::NO_INCREMENTAL
         && !cx->runtime()->profilingScripts
         && !cx->runtime()->spsProfiler.enabled();
 }
 
+static void
+TrackAllProperties(JSContext *cx, JSObject *obj)
+{
+    JS_ASSERT(obj->hasSingletonType());
+
+    for (Shape::Range<NoGC> range(obj->lastProperty()); !range.empty(); range.popFront())
+        types::EnsureTrackPropertyTypes(cx, obj, range.front().propid());
+}
+
+static void
+TrackPropertiesForSingletonScopes(JSContext *cx, JSScript *script, BaselineFrame *baselineFrame)
+{
+    // Ensure that all properties of singleton call objects which the script
+    // could access are tracked. These are generally accessed through
+    // ALIASEDVAR operations in baseline and will not be tracked even if they
+    // have been accessed in baseline code.
+    JSObject *environment = script->function() ? script->function()->environment() : NULL;
+
+    while (environment && !environment->is<GlobalObject>()) {
+        if (environment->is<CallObject>() && environment->hasSingletonType())
+            TrackAllProperties(cx, environment);
+        environment = environment->enclosingScope();
+    }
+
+    if (baselineFrame) {
+        JSObject *scope = baselineFrame->scopeChain();
+        if (scope->is<CallObject>() && scope->hasSingletonType())
+            TrackAllProperties(cx, scope);
+    }
+}
+
 static AbortReason
 IonCompile(JSContext *cx, JSScript *script,
            BaselineFrame *baselineFrame, jsbytecode *osrPc, bool constructing,
            ExecutionMode executionMode)
 {
 #if JS_TRACE_LOGGING
     AutoTraceLog logger(TraceLogging::defaultLogger(),
                         TraceLogging::ION_COMPILE_START,
                         TraceLogging::ION_COMPILE_STOP,
                         script);
 #endif
 
+    TrackPropertiesForSingletonScopes(cx, script, baselineFrame);
+
     LifoAlloc *alloc = cx->new_<LifoAlloc>(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
     if (!alloc)
         return AbortReason_Alloc;
 
     ScopedJSDeletePtr<LifoAlloc> autoDelete(alloc);
 
     TempAllocator *temp = alloc->new_<TempAllocator>(alloc);
     if (!temp)
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -280,17 +280,17 @@ IonBuilder::canInlineTarget(JSFunction *
 
     // Allow constructing lazy scripts when performing the definite properties
     // analysis, as baseline has not been used to warm the caller up yet.
     if (target->isInterpreted() && info().executionMode() == DefinitePropertiesAnalysis) {
         if (!target->getOrCreateScript(context()))
             return false;
 
         RootedScript script(context(), target->nonLazyScript());
-        if (!script->hasBaselineScript()) {
+        if (!script->hasBaselineScript() && script->canBaselineCompile()) {
             MethodStatus status = BaselineCompile(context(), script);
             if (status != Method_Compiled)
                 return false;
         }
     }
 
     if (!target->hasScript()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to lack of Non-Lazy script");
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -2984,17 +2984,17 @@ GetElementIC::canAttachGetProp(JSObject 
 
 static bool
 EqualStringsHelper(JSString *str1, JSString *str2)
 {
     JS_ASSERT(str1->isAtom());
     JS_ASSERT(!str2->isAtom());
     JS_ASSERT(str1->length() == str2->length());
 
-    const jschar *chars = str2->getChars(NULL);
+    const jschar *chars = str2->getChars(nullptr);
     if (!chars)
         return false;
     return mozilla::PodEqual(str1->asAtom().chars(), chars, str1->length());
 }
 
 bool
 GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
                             const Value &idval, HandlePropertyName name,
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -4361,28 +4361,35 @@ class LStringLength : public LInstructio
         setOperand(0, string);
     }
 
     const LAllocation *string() {
         return getOperand(0);
     }
 };
 
-// Take the floor of a number. Implements Math.floor().
+// Take the floor of a double precision number. Implements Math.floor().
 class LFloor : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Floor)
 
     LFloor(const LAllocation &num) {
         setOperand(0, num);
     }
-
-    MRound *mir() const {
-        return mir_->toRound();
+};
+
+// Take the floor of a single precision number. Implements Math.floor().
+class LFloorF : public LInstructionHelper<1, 1, 0>
+{
+  public:
+    LIR_HEADER(FloorF)
+
+    LFloorF(const LAllocation &num) {
+        setOperand(0, num);
     }
 };
 
 // Round a number. Implements Math.round().
 class LRound : public LInstructionHelper<1, 1, 1>
 {
   public:
     LIR_HEADER(Round)
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -241,16 +241,17 @@
     _(SetFrameArgumentC)            \
     _(SetFrameArgumentV)            \
     _(RunOncePrologue)              \
     _(Rest)                         \
     _(RestPar)                      \
     _(TypeOfV)                      \
     _(ToIdV)                        \
     _(Floor)                        \
+    _(FloorF)                       \
     _(Round)                        \
     _(In)                           \
     _(InArray)                      \
     _(InstanceOfO)                  \
     _(InstanceOfV)                  \
     _(CallInstanceOf)               \
     _(InterruptCheck)               \
     _(InterruptCheckImplicit)       \
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -1124,18 +1124,27 @@ bool
 LIRGenerator::visitUrsh(MUrsh *ins)
 {
     return lowerShiftOp(JSOP_URSH, ins);
 }
 
 bool
 LIRGenerator::visitFloor(MFloor *ins)
 {
-    JS_ASSERT(ins->num()->type() == MIRType_Double);
-    LFloor *lir = new LFloor(useRegister(ins->num()));
+    MIRType type = ins->num()->type();
+    JS_ASSERT(IsFloatingPointType(type));
+
+    if (type == MIRType_Double) {
+        LFloor *lir = new LFloor(useRegister(ins->num()));
+        if (!assignSnapshot(lir))
+            return false;
+        return define(lir, ins);
+    }
+
+    LFloorF *lir = new LFloorF(useRegister(ins->num()));
     if (!assignSnapshot(lir))
         return false;
     return define(lir, ins);
 }
 
 bool
 LIRGenerator::visitRound(MRound *ins)
 {
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -549,42 +549,41 @@ IonBuilder::inlineMathAbs(CallInfo &call
 
     current->push(ins);
     return InliningStatus_Inlined;
 }
 
 IonBuilder::InliningStatus
 IonBuilder::inlineMathFloor(CallInfo &callInfo)
 {
-
     if (callInfo.constructing())
         return InliningStatus_NotInlined;
 
     if (callInfo.argc() != 1)
         return InliningStatus_NotInlined;
 
     MIRType argType = callInfo.getArg(0)->type();
     MIRType returnType = getInlineReturnType();
 
     // Math.floor(int(x)) == int(x)
     if (argType == MIRType_Int32 && returnType == MIRType_Int32) {
         callInfo.unwrapArgs();
         current->push(callInfo.getArg(0));
         return InliningStatus_Inlined;
     }
 
-    if (argType == MIRType_Double && returnType == MIRType_Int32) {
+    if (IsFloatingPointType(argType) && returnType == MIRType_Int32) {
         callInfo.unwrapArgs();
         MFloor *ins = new MFloor(callInfo.getArg(0));
         current->add(ins);
         current->push(ins);
         return InliningStatus_Inlined;
     }
 
-    if (argType == MIRType_Double && returnType == MIRType_Double) {
+    if (IsFloatingPointType(argType) && returnType == MIRType_Double) {
         callInfo.unwrapArgs();
         MMathFunction *ins = MMathFunction::New(callInfo.getArg(0), MMathFunction::Floor, nullptr);
         current->add(ins);
         current->push(ins);
         return InliningStatus_Inlined;
     }
 
     return InliningStatus_NotInlined;
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -25,16 +25,33 @@
 
 using namespace js;
 using namespace js::jit;
 
 using mozilla::DoublesAreIdentical;
 using mozilla::IsFloat32Representable;
 using mozilla::Maybe;
 
+template<size_t Op> static void
+ConvertDefinitionToDouble(MDefinition *def, MInstruction *consumer)
+{
+    MInstruction *replace = MToDouble::New(def);
+    consumer->replaceOperand(Op, replace);
+    consumer->block()->insertBefore(consumer, replace);
+}
+
+static bool
+CheckUsesAreFloat32Consumers(MInstruction *ins)
+{
+    bool allConsumerUses = true;
+    for (MUseDefIterator use(ins); allConsumerUses && use; use++)
+        allConsumerUses &= use.def()->canConsumeFloat32();
+    return allConsumerUses;
+}
+
 void
 MDefinition::PrintOpcodeName(FILE *fp, MDefinition::Opcode op)
 {
     static const char * const names[] =
     {
 #define NAME(x) #x,
         MIR_OPCODE_LIST(NAME)
 #undef NAME
@@ -645,16 +662,32 @@ MStringLength::foldsTo(bool useValueNumb
         size_t length = JS_GetStringLength(value.toString());
 
         return MConstant::New(Int32Value(length));
     }
 
     return this;
 }
 
+void
+MFloor::trySpecializeFloat32()
+{
+    // No need to look at the output, as it's an integer (see IonBuilder::inlineMathFloor)
+    if (!input()->canProduceFloat32()) {
+        if (input()->type() == MIRType_Float32)
+            ConvertDefinitionToDouble<0>(input(), this);
+        return;
+    }
+
+    if (type() == MIRType_Double)
+        setResultType(MIRType_Float32);
+
+    setPolicyType(MIRType_Float32);
+}
+
 MTest *
 MTest::New(MDefinition *ins, MBasicBlock *ifTrue, MBasicBlock *ifFalse)
 {
     return new MTest(ins, ifTrue, ifFalse);
 }
 
 MCompare *
 MCompare::New(MDefinition *left, MDefinition *right, JSOp op)
@@ -1231,33 +1264,16 @@ MBinaryArithInstruction::foldsTo(bool us
         return this;
 
     if (IsConstant(lhs, getIdentity()))
         return rhs; // x op id => x
 
     return this;
 }
 
-template<size_t Op> static void
-ConvertDefinitionToDouble(MDefinition *def, MInstruction *consumer)
-{
-    MInstruction *replace = MToDouble::New(def);
-    consumer->replaceOperand(Op, replace);
-    consumer->block()->insertBefore(consumer, replace);
-}
-
-static bool
-CheckUsesAreFloat32Consumers(MInstruction *ins)
-{
-    bool allConsumerUses = true;
-    for (MUseDefIterator use(ins); allConsumerUses && use; use++)
-        allConsumerUses &= use.def()->canConsumeFloat32();
-    return allConsumerUses;
-}
-
 void
 MBinaryArithInstruction::trySpecializeFloat32()
 {
     MDefinition *left = lhs();
     MDefinition *right = rhs();
 
     if (!left->canProduceFloat32() || !right->canProduceFloat32()
         || !CheckUsesAreFloat32Consumers(this))
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3743,17 +3743,17 @@ class MMathFunction
 
     void printOpcode(FILE *fp) const;
 
     static const char *FunctionName(Function function);
 
     bool isFloat32Commutative() const {
         return function_ == Log || function_ == Sin || function_ == Cos
                || function_ == Exp || function_ == Tan || function_ == ATan
-               || function_ == ASin || function_ == ACos;
+               || function_ == ASin || function_ == ACos || function_ == Floor;
     }
     void trySpecializeFloat32();
 };
 
 class MAdd : public MBinaryArithInstruction
 {
     // Is this instruction really an int at heart?
     MAdd(MDefinition *left, MDefinition *right)
@@ -7590,37 +7590,47 @@ class MStringLength
     }
 
     void computeRange();
 };
 
 // Inlined version of Math.floor().
 class MFloor
   : public MUnaryInstruction,
-    public DoublePolicy<0>
+    public FloatingPointPolicy<0>
 {
   public:
     MFloor(MDefinition *num)
       : MUnaryInstruction(num)
     {
         setResultType(MIRType_Int32);
+        setPolicyType(MIRType_Double);
         setMovable();
     }
 
     INSTRUCTION_HEADER(Floor)
 
     MDefinition *num() const {
         return getOperand(0);
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
     TypePolicy *typePolicy() {
         return this;
     }
+    bool isFloat32Commutative() const {
+        return true;
+    }
+    void trySpecializeFloat32();
+#ifdef DEBUG
+    bool isConsistentFloat32Use() const {
+        return true;
+    }
+#endif
 };
 
 // Inlined version of Math.round().
 class MRound
   : public MUnaryInstruction,
     public DoublePolicy<0>
 {
   public:
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1198,16 +1198,28 @@ CodeGeneratorARM::visitFloor(LFloor *lir
     Label bail;
     masm.floor(input, output, &bail);
     if (!bailoutFrom(&bail, lir->snapshot()))
         return false;
     return true;
 }
 
 bool
+CodeGeneratorARM::visitFloorF(LFloorF *lir)
+{
+    FloatRegister input = ToFloatRegister(lir->input());
+    Register output = ToRegister(lir->output());
+    Label bail;
+    masm.floorf(input, output, &bail);
+    if (!bailoutFrom(&bail, lir->snapshot()))
+        return false;
+    return true;
+}
+
+bool
 CodeGeneratorARM::visitRound(LRound *lir)
 {
     FloatRegister input = ToFloatRegister(lir->input());
     Register output = ToRegister(lir->output());
     FloatRegister tmp = ToFloatRegister(lir->temp());
     Label bail;
     // Output is either correct, or clamped.  All -0 cases have been translated to a clamped
     // case.a
--- a/js/src/jit/arm/CodeGenerator-arm.h
+++ b/js/src/jit/arm/CodeGenerator-arm.h
@@ -105,16 +105,17 @@ class CodeGeneratorARM : public CodeGene
     virtual bool visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir);
     virtual bool visitNotI(LNotI *ins);
     virtual bool visitNotD(LNotD *ins);
     virtual bool visitNotF(LNotF *ins);
 
     virtual bool visitMathD(LMathD *math);
     virtual bool visitMathF(LMathF *math);
     virtual bool visitFloor(LFloor *lir);
+    virtual bool visitFloorF(LFloorF *lir);
     virtual bool visitRound(LRound *lir);
     virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins);
     virtual bool visitTruncateFToInt32(LTruncateFToInt32 *ins);
 
     // Out of line visitors.
     bool visitOutOfLineBailout(OutOfLineBailout *ool);
     bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool);
 
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -3825,16 +3825,68 @@ MacroAssemblerARMCompat::floor(FloatRegi
     // the int range, and special handling is required.
     // zero is also caught by this case, but floor of a negative number
     // should never be zero.
     ma_b(bail, Unsigned);
 
     bind(&fin);
 }
 
+void
+MacroAssemblerARMCompat::floorf(FloatRegister input, Register output, Label *bail)
+{
+    Label handleZero;
+    Label handleNeg;
+    Label fin;
+    compareFloat(input, InvalidFloatReg);
+    ma_b(&handleZero, Assembler::Equal);
+    ma_b(&handleNeg, Assembler::Signed);
+    // NaN is always a bail condition, just bail directly.
+    ma_b(bail, Assembler::Overflow);
+
+    // The argument is a positive number, truncation is the path to glory;
+    // Since it is known to be > 0.0, explicitly convert to a larger range,
+    // then a value that rounds to INT_MAX is explicitly different from an
+    // argument that clamps to INT_MAX
+    ma_vcvt_F32_U32(input, ScratchFloatReg);
+    ma_vxfer(VFPRegister(ScratchFloatReg).uintOverlay(), output);
+    ma_mov(output, output, SetCond);
+    ma_b(bail, Signed);
+    ma_b(&fin);
+
+    bind(&handleZero);
+    // Move the top word of the double into the output reg, if it is non-zero,
+    // then the original value was -0.0
+    as_vxfer(output, InvalidReg, VFPRegister(input).singleOverlay(), FloatToCore, Always, 0);
+    ma_cmp(output, Imm32(0));
+    ma_b(bail, NonZero);
+    ma_b(&fin);
+
+    bind(&handleNeg);
+    // Negative case, negate, then start dancing
+    ma_vneg_f32(input, input);
+    ma_vcvt_F32_U32(input, ScratchFloatReg);
+    ma_vxfer(VFPRegister(ScratchFloatReg).uintOverlay(), output);
+    ma_vcvt_U32_F32(ScratchFloatReg, ScratchFloatReg);
+    compareFloat(ScratchFloatReg, input);
+    ma_add(output, Imm32(1), output, NoSetCond, NotEqual);
+    // Negate the output.  Since INT_MIN < -INT_MAX, even after adding 1,
+    // the result will still be a negative number
+    ma_rsb(output, Imm32(0), output, SetCond);
+    // Flip the negated input back to its original value.
+    ma_vneg_f32(input, input);
+    // If the result looks non-negative, then this value didn't actually fit into
+    // the int range, and special handling is required.
+    // zero is also caught by this case, but floor of a negative number
+    // should never be zero.
+    ma_b(bail, Unsigned);
+
+    bind(&fin);
+}
+
 CodeOffsetLabel
 MacroAssemblerARMCompat::toggledJump(Label *label)
 {
     // Emit a B that can be toggled to a CMP. See ToggleToJmp(), ToggleToCmp().
     CodeOffsetLabel ret(nextOffset().getOffset());
     ma_b(label, Always, true);
     return ret;
 }
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1430,16 +1430,17 @@ class MacroAssemblerARMCompat : public M
         ma_add(address.base, Imm32(address.offset), dest, NoSetCond);
     }
     void computeEffectiveAddress(const BaseIndex &address, Register dest) {
         ma_alu(address.base, lsl(address.index, address.scale), dest, op_add, NoSetCond);
         if (address.offset)
             ma_add(dest, Imm32(address.offset), dest, NoSetCond);
     }
     void floor(FloatRegister input, Register output, Label *handleNotAnInt);
+    void floorf(FloatRegister input, Register output, Label *handleNotAnInt);
     void round(FloatRegister input, Register output, Label *handleNotAnInt, FloatRegister tmp);
 
     void clampCheck(Register r, Label *handleNotAnInt) {
         // check explicitly for r == INT_MIN || r == INT_MAX
         // this is the instruction sequence that gcc generated for this
         // operation.
         ma_sub(r, Imm32(0x80000001), ScratchRegister);
         ma_cmn(ScratchRegister, Imm32(3));
--- a/js/src/jit/shared/Assembler-x86-shared.h
+++ b/js/src/jit/shared/Assembler-x86-shared.h
@@ -1461,16 +1461,22 @@ class AssemblerX86Shared
         masm.sqrtss_rr(src.code(), dest.code());
     }
     void roundsd(const FloatRegister &src, const FloatRegister &dest,
                  JSC::X86Assembler::RoundingMode mode)
     {
         JS_ASSERT(HasSSE41());
         masm.roundsd_rr(src.code(), dest.code(), mode);
     }
+    void roundss(const FloatRegister &src, const FloatRegister &dest,
+                 JSC::X86Assembler::RoundingMode mode)
+    {
+        JS_ASSERT(HasSSE41());
+        masm.roundss_rr(src.code(), dest.code(), mode);
+    }
     void minsd(const FloatRegister &src, const FloatRegister &dest) {
         JS_ASSERT(HasSSE2());
         masm.minsd_rr(src.code(), dest.code());
     }
     void minsd(const Operand &src, const FloatRegister &dest) {
         JS_ASSERT(HasSSE2());
         switch (src.kind()) {
           case Operand::FPREG:
@@ -1523,16 +1529,25 @@ class AssemblerX86Shared
         switch (src.kind()) {
           case Operand::MEM_REG_DISP:
             masm.fstp_m(src.disp(), src.base());
             break;
           default:
             MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
         }
     }
+    void fstp32(const Operand &src) {
+        switch (src.kind()) {
+          case Operand::MEM_REG_DISP:
+            masm.fstp32_m(src.disp(), src.base());
+            break;
+          default:
+            MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
+        }
+    }
 
     // Defined for compatibility with ARM's assembler
     uint32_t actualOffset(uint32_t x) {
         return x;
     }
 
     uint32_t actualIndex(uint32_t x) {
         return x;
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -747,21 +747,21 @@ CodeGeneratorShared::visitOutOfLineTrunc
     masm.setupUnalignedABICall(1, dest);
     masm.passABIArg(src);
     if (gen->compilingAsmJS())
         masm.callWithABI(AsmJSImm_ToInt32);
     else
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, js::ToInt32));
     masm.storeCallResult(dest);
 
-    restoreVolatile(dest);
-
     if (ool->needFloat32Conversion())
         masm.pop(src);
 
+    restoreVolatile(dest);
+
     masm.jump(ool->rejoin());
     return true;
 }
 
 void
 CodeGeneratorShared::emitPreBarrier(Register base, const LAllocation *index, MIRType type)
 {
     if (index->isConstant()) {
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -1444,16 +1444,83 @@ CodeGeneratorX86Shared::visitFloor(LFloo
         }
 
         masm.bind(&end);
     }
     return true;
 }
 
 bool
+CodeGeneratorX86Shared::visitFloorF(LFloorF *lir)
+{
+    FloatRegister input = ToFloatRegister(lir->input());
+    FloatRegister scratch = ScratchFloatReg;
+    Register output = ToRegister(lir->output());
+
+    if (AssemblerX86Shared::HasSSE41()) {
+        // Bail on negative-zero.
+        Assembler::Condition bailCond = masm.testNegativeZeroFloat32(input, output);
+        if (!bailoutIf(bailCond, lir->snapshot()))
+            return false;
+
+        // Round toward -Infinity.
+        masm.roundss(input, scratch, JSC::X86Assembler::RoundDown);
+
+        masm.cvttss2si(scratch, output);
+        masm.cmp32(output, Imm32(INT_MIN));
+        if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+            return false;
+    } else {
+        Label negative, end;
+
+        // Branch to a slow path for negative inputs. Doesn't catch NaN or -0.
+        masm.xorps(scratch, scratch);
+        masm.branchFloat(Assembler::DoubleLessThan, input, scratch, &negative);
+
+        // Bail on negative-zero.
+        Assembler::Condition bailCond = masm.testNegativeZeroFloat32(input, output);
+        if (!bailoutIf(bailCond, lir->snapshot()))
+            return false;
+
+        // Input is non-negative, so truncation correctly rounds.
+        masm.cvttss2si(input, output);
+        masm.cmp32(output, Imm32(INT_MIN));
+        if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+            return false;
+
+        masm.jump(&end);
+
+        // Input is negative, but isn't -0.
+        // Negative values go on a comparatively expensive path, since no
+        // native rounding mode matches JS semantics. Still better than callVM.
+        masm.bind(&negative);
+        {
+            // Truncate and round toward zero.
+            // This is off-by-one for everything but integer-valued inputs.
+            masm.cvttss2si(input, output);
+            masm.cmp32(output, Imm32(INT_MIN));
+            if (!bailoutIf(Assembler::Equal, lir->snapshot()))
+                return false;
+
+            // Test whether the input double was integer-valued.
+            masm.convertInt32ToFloat32(output, scratch);
+            masm.branchFloat(Assembler::DoubleEqualOrUnordered, input, scratch, &end);
+
+            // Input is not integer-valued, so we rounded off-by-one in the
+            // wrong direction. Correct by subtraction.
+            masm.subl(Imm32(1), output);
+            // Cannot overflow: output was already checked against INT_MIN.
+        }
+
+        masm.bind(&end);
+    }
+    return true;
+}
+
+bool
 CodeGeneratorX86Shared::visitRound(LRound *lir)
 {
     FloatRegister input = ToFloatRegister(lir->input());
     FloatRegister temp = ToFloatRegister(lir->temp());
     FloatRegister scratch = ScratchFloatReg;
     Register output = ToRegister(lir->output());
 
     Label negative, end;
--- a/js/src/jit/shared/CodeGenerator-x86-shared.h
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.h
@@ -109,16 +109,17 @@ class CodeGeneratorX86Shared : public Co
     virtual bool visitCompareFAndBranch(LCompareFAndBranch *comp);
     virtual bool visitBitAndAndBranch(LBitAndAndBranch *baab);
     virtual bool visitNotI(LNotI *comp);
     virtual bool visitNotD(LNotD *comp);
     virtual bool visitNotF(LNotF *comp);
     virtual bool visitMathD(LMathD *math);
     virtual bool visitMathF(LMathF *math);
     virtual bool visitFloor(LFloor *lir);
+    virtual bool visitFloorF(LFloorF *lir);
     virtual bool visitRound(LRound *lir);
     virtual bool visitGuardShape(LGuardShape *guard);
     virtual bool visitGuardObjectType(LGuardObjectType *guard);
     virtual bool visitGuardClass(LGuardClass *guard);
     virtual bool visitEffectiveAddress(LEffectiveAddress *ins);
     virtual bool visitUDivOrMod(LUDivOrMod *ins);
     virtual bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins);
 
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -359,8 +359,16 @@ MacroAssemblerX64::handleFailureWithHand
 
 Assembler::Condition
 MacroAssemblerX64::testNegativeZero(const FloatRegister &reg, const Register &scratch)
 {
     movq(reg, scratch);
     cmpq(scratch, Imm32(1));
     return Overflow;
 }
+
+Assembler::Condition
+MacroAssemblerX64::testNegativeZeroFloat32(const FloatRegister &reg, const Register &scratch)
+{
+    movd(reg, scratch);
+    cmpl(scratch, Imm32(1));
+    return Overflow;
+}
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -76,17 +76,18 @@ class MacroAssemblerX64 : public MacroAs
     using MacroAssemblerX86Shared::call;
     using MacroAssemblerX86Shared::Push;
     using MacroAssemblerX86Shared::Pop;
     using MacroAssemblerX86Shared::callWithExitFrame;
     using MacroAssemblerX86Shared::branch32;
 
     enum Result {
         GENERAL,
-        DOUBLE
+        DOUBLE,
+        FLOAT
     };
 
     typedef MoveResolver::MoveOperand MoveOperand;
     typedef MoveResolver::Move Move;
 
     MacroAssemblerX64()
       : inCall_(false),
         enoughMemory_(true)
@@ -461,16 +462,17 @@ class MacroAssemblerX64 : public MacroAs
     void cmpPtr(const Register &lhs, const Register &rhs) {
         return cmpq(lhs, rhs);
     }
     void testPtr(const Register &lhs, const Register &rhs) {
         testq(lhs, rhs);
     }
 
     Condition testNegativeZero(const FloatRegister &reg, const Register &scratch);
+    Condition testNegativeZeroFloat32(const FloatRegister &reg, const Register &scratch);
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
     void reserveStack(uint32_t amount) {
         if (amount)
             subq(Imm32(amount), StackPointer);
         framePushed_ += amount;
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -234,16 +234,22 @@ MacroAssemblerX86::callWithABIPost(uint3
 {
     freeStack(stackAdjust);
     if (result == DOUBLE) {
         reserveStack(sizeof(double));
         fstp(Operand(esp, 0));
         loadDouble(Operand(esp, 0), ReturnFloatReg);
         freeStack(sizeof(double));
     }
+    if (result == FLOAT) {
+        reserveStack(sizeof(float));
+        fstp32(Operand(esp, 0));
+        loadFloat(Operand(esp, 0), ReturnFloatReg);
+        freeStack(sizeof(float));
+    }
     if (dynamicAlignment_)
         pop(esp);
 
     JS_ASSERT(inCall_);
     inCall_ = false;
 }
 
 void
@@ -396,8 +402,16 @@ MacroAssemblerX86::testNegativeZero(cons
     // Input register is either zero or negative zero. Test sign bit.
     movmskpd(reg, scratch);
     // If reg is -0, then a test of Zero is true.
     cmpl(scratch, Imm32(1));
 
     bind(&nonZero);
     return Zero;
 }
+
+Assembler::Condition
+MacroAssemblerX86::testNegativeZeroFloat32(const FloatRegister &reg, const Register &scratch)
+{
+    movd(reg, scratch);
+    cmpl(scratch, Imm32(1));
+    return Overflow;
+}
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -67,17 +67,18 @@ class MacroAssemblerX86 : public MacroAs
   public:
     using MacroAssemblerX86Shared::Push;
     using MacroAssemblerX86Shared::Pop;
     using MacroAssemblerX86Shared::callWithExitFrame;
     using MacroAssemblerX86Shared::branch32;
 
     enum Result {
         GENERAL,
-        DOUBLE
+        DOUBLE,
+        FLOAT
     };
 
     typedef MoveResolver::MoveOperand MoveOperand;
     typedef MoveResolver::Move Move;
 
     MacroAssemblerX86()
       : inCall_(false),
         enoughMemory_(true)
@@ -494,16 +495,17 @@ class MacroAssemblerX86 : public MacroAs
     void cmpPtr(Register lhs, Register rhs) {
         cmpl(lhs, rhs);
     }
     void testPtr(Register lhs, Register rhs) {
         testl(lhs, rhs);
     }
 
     Condition testNegativeZero(const FloatRegister &reg, const Register &scratch);
+    Condition testNegativeZeroFloat32(const FloatRegister &reg, const Register &scratch);
 
     /////////////////////////////////////////////////////////////////
     // Common interface.
     /////////////////////////////////////////////////////////////////
     void reserveStack(uint32_t amount) {
         if (amount)
             subl(Imm32(amount), StackPointer);
         framePushed_ += amount;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3073,18 +3073,17 @@ JS_NewArrayBufferWithContents(JSContext 
  * length set to 0 and its contents array cleared. The caller takes ownership
  * of |*contents| and must free it or transfer ownership via
  * JS_NewArrayBufferWithContents when done using it.
  * To free |*contents|, call free().
  * A pointer to the buffer's data is returned in |*data|. This pointer can
  * be used until |*contents| is freed or has its ownership transferred.
  */
 extern JS_PUBLIC_API(bool)
-JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
-                            uint8_t **data);
+JS_StealArrayBufferContents(JSContext *cx, JS::HandleObject obj, void **contents, uint8_t **data);
 
 /*
  * Allocate memory that may be eventually passed to
  * JS_NewArrayBufferWithContents. |nbytes| is the number of payload bytes
  * required. The pointer to pass to JS_NewArrayBufferWithContents is returned
  * in |contents|. The pointer to the |nbytes| of usable memory is returned in
  * |data|. (*|contents| will contain a header before |data|.) The only legal
  * operations on *|contents| is to free it, or pass it to
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -607,17 +607,17 @@ TypeScript::ArgTypes(JSScript *script, u
 template <typename TYPESET>
 /* static */ inline TYPESET *
 TypeScript::BytecodeTypes(JSScript *script, jsbytecode *pc, uint32_t *hint, TYPESET *typeArray)
 {
     JS_ASSERT(js_CodeSpec[*pc].format & JOF_TYPESET);
 #ifdef JS_ION
     uint32_t *bytecodeMap = script->baselineScript()->bytecodeTypeMap();
 #else
-    uint32_t *bytecodeMap = NULL;
+    uint32_t *bytecodeMap = nullptr;
     MOZ_CRASH();
 #endif
     uint32_t offset = pc - script->code;
     JS_ASSERT(offset < script->length);
 
     // See if this pc is the next typeset opcode after the last one looked up.
     if (bytecodeMap[*hint + 1] == offset && (*hint + 1) < script->nTypeSets) {
         (*hint)++;
@@ -653,17 +653,17 @@ TypeScript::BytecodeTypes(JSScript *scri
 
 /* static */ inline StackTypeSet *
 TypeScript::BytecodeTypes(JSScript *script, jsbytecode *pc)
 {
     JS_ASSERT(CurrentThreadCanAccessRuntime(script->runtimeFromMainThread()));
 #ifdef JS_ION
     uint32_t *hint = script->baselineScript()->bytecodeTypeMap() + script->nTypeSets;
 #else
-    uint32_t *hint = NULL;
+    uint32_t *hint = nullptr;
     MOZ_CRASH();
 #endif
     return BytecodeTypes(script, pc, hint, script->types->typeArray());
 }
 
 struct AllocationSiteKey : public DefaultHasher<AllocationSiteKey> {
     JSScript *script;
 
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1435,17 +1435,17 @@ GeneratorState::~GeneratorState()
 {
     gen_->fp->setSuspended();
 
     if (entered_)
         cx_->leaveGenerator(gen_);
 }
 
 StackFrame *
-GeneratorState::pushInterpreterFrame(JSContext *cx, FrameGuard *)
+GeneratorState::pushInterpreterFrame(JSContext *cx)
 {
     /*
      * Write barrier is needed since the generator stack can be updated,
      * and it's not barriered in any other way. We need to do it before
      * gen->state changes, which can cause us to trace the generator
      * differently.
      *
      * We could optimize this by setting a bit on the generator to signify
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -512,8 +512,42 @@ OPDEF(JSOP_IMPLICITTHIS,  226, "implicit
  * This opcode is the target of the entry jump for some loop. The uint8 argument
  * is the loop depth. This value starts at 1 and is just a hint: deeply
  * nested loops all have the same value.
  */
 OPDEF(JSOP_LOOPENTRY,     227, "loopentry",    NULL,  2,  0,  0,  JOF_UINT8)
 
 /* Notes the point at which a value is pushed as an argument. */
 OPDEF(JSOP_NOTEARG,       228, "notearg",      NULL,  1,  0,  0,  JOF_BYTE)
+
+/*
+ * Pad out the unused opcode space to the nearest power-of-two boundary. The
+ * interpreter uses this to construct a table which is a power-of-two size.
+ */
+#ifdef OPPAD
+OPPAD(229)
+OPPAD(230)
+OPPAD(231)
+OPPAD(232)
+OPPAD(233)
+OPPAD(234)
+OPPAD(235)
+OPPAD(236)
+OPPAD(237)
+OPPAD(238)
+OPPAD(239)
+OPPAD(240)
+OPPAD(241)
+OPPAD(242)
+OPPAD(243)
+OPPAD(244)
+OPPAD(245)
+OPPAD(246)
+OPPAD(247)
+OPPAD(248)
+OPPAD(249)
+OPPAD(250)
+OPPAD(251)
+OPPAD(252)
+OPPAD(253)
+OPPAD(254)
+OPPAD(255)
+#endif
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -124,18 +124,18 @@ static JS::Value gTimeoutFunc;
 
 static bool enableTypeInference = true;
 static bool enableDisassemblyDumps = false;
 static bool enableIon = true;
 static bool enableBaseline = true;
 static bool enableAsmJS = true;
 
 static bool printTiming = false;
-static const char *jsCacheDir = NULL;
-static const char *jsCacheAsmJSPath = NULL;
+static const char *jsCacheDir = nullptr;
+static const char *jsCacheAsmJSPath = nullptr;
 mozilla::Atomic<int32_t> jsCacheOpened(false);
 
 static bool
 SetTimeoutValue(JSContext *cx, double t);
 
 static bool
 InitWatchdog(JSRuntime *rt);
 
@@ -3668,17 +3668,17 @@ NestedShell(JSContext *cx, unsigned argc
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     AutoCStringVector argv(cx);
 
     // The first argument to the shell is its path, which we assume is our own
     // argv[0].
     if (sArgc < 1) {
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_NESTED_FAIL);
+        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL);
         return false;
     }
     if (!argv.append(strdup(sArgv[0])))
         return false;
 
     // The arguments to nestedShell are stringified and append to argv.
     RootedString str(cx);
     for (unsigned i = 0; i < args.length(); i++) {
@@ -3704,31 +3704,31 @@ NestedShell(JSContext *cx, unsigned argc
 #if defined(XP_WIN)
     if (!EscapeForShell(argv))
         return false;
     status = _spawnv(_P_WAIT, sArgv[0], argv.get());
 #else
     pid_t pid = fork();
     switch (pid) {
       case -1:
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_NESTED_FAIL);
+        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL);
         return false;
       case 0:
         (void)execv(sArgv[0], argv.get());
         exit(-1);
       default: {
         while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
             continue;
         break;
       }
     }
 #endif
 
     if (status != 0) {
-        JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_NESTED_FAIL);
+        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_NESTED_FAIL);
         return false;
     }
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
@@ -4026,17 +4026,17 @@ WithSourceHook(JSContext *cx, unsigned a
     js::SetSourceHook(cx->runtime(), savedHook);
     return result;
 }
 
 static bool
 IsCachingEnabled(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    args.rval().setBoolean(jsCacheAsmJSPath != NULL);
+    args.rval().setBoolean(jsCacheAsmJSPath != nullptr);
     return true;
 }
 
 static const JSFunctionSpecWithHelp shell_functions[] = {
     JS_FN_HELP("version", Version, 0, 0,
 "version([number])",
 "  Get or force a script compilation version number."),
 
@@ -5080,26 +5080,26 @@ ShellOpenAsmJSCacheEntryForRead(HandleOb
     off_t off = lseek(fd, 0, SEEK_END);
     if (off == -1 || off < (off_t)sizeof(uint32_t))
         return false;
 
     // Map the file into memory.
     void *memory;
 #ifdef XP_WIN
     HANDLE fdOsHandle = (HANDLE)_get_osfhandle(fd);
-    HANDLE fileMapping = CreateFileMapping(fdOsHandle, NULL, PAGE_READWRITE, 0, 0, NULL);
+    HANDLE fileMapping = CreateFileMapping(fdOsHandle, nullptr, PAGE_READWRITE, 0, 0, nullptr);
     if (!fileMapping)
         return false;
 
     memory = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, 0);
     CloseHandle(fileMapping);
     if (!memory)
         return false;
 #else
-    memory = mmap(NULL, off, PROT_READ, MAP_SHARED, fd, 0);
+    memory = mmap(nullptr, off, PROT_READ, MAP_SHARED, fd, 0);
     if (memory == MAP_FAILED)
         return false;
 #endif
 
     // Perform check described by asmJSCacheCookie comment.
     if (*(uint32_t *)memory != asmJSCacheCookie) {
 #ifdef XP_WIN
         UnmapViewOfFile(memory);
@@ -5178,26 +5178,26 @@ ShellOpenAsmJSCacheEntryForWrite(HandleO
     if (ftruncate(fd, serializedSize))
         return false;
 #endif
 
     // Map the file into memory.
     void *memory;
 #ifdef XP_WIN
     HANDLE fdOsHandle = (HANDLE)_get_osfhandle(fd);
-    HANDLE fileMapping = CreateFileMapping(fdOsHandle, NULL, PAGE_READWRITE, 0, 0, NULL);
+    HANDLE fileMapping = CreateFileMapping(fdOsHandle, nullptr, PAGE_READWRITE, 0, 0, nullptr);
     if (!fileMapping)
         return false;
 
     memory = MapViewOfFile(fileMapping, FILE_MAP_WRITE, 0, 0, 0);
     CloseHandle(fileMapping);
     if (!memory)
         return false;
 #else
-    memory = mmap(NULL, serializedSize, PROT_WRITE, MAP_SHARED, fd, 0);
+    memory = mmap(nullptr, serializedSize, PROT_WRITE, MAP_SHARED, fd, 0);
     if (memory == MAP_FAILED)
         return false;
 #endif
 
     // The embedding added the cookie so strip it off of the buffer returned to
     // the JS engine. The asmJSCacheCookie will be written on close, below.
     JS_ASSERT(*(uint32_t *)memory == 0);
     *memoryOut = (uint8_t *)memory + sizeof(uint32_t);
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -365,26 +365,26 @@ js::ValueToCallable(JSContext *cx, const
     ReportIsNotFunction(cx, v, numToSkip, construct);
     return nullptr;
 }
 
 static JS_NEVER_INLINE bool
 Interpret(JSContext *cx, RunState &state);
 
 StackFrame *
-InvokeState::pushInterpreterFrame(JSContext *cx, FrameGuard *fg)
+InvokeState::pushInterpreterFrame(JSContext *cx)
 {
-    return cx->runtime()->interpreterStack().pushInvokeFrame(cx, args_, initial_, fg);
+    return cx->runtime()->interpreterStack().pushInvokeFrame(cx, args_, initial_);
 }
 
 StackFrame *
-ExecuteState::pushInterpreterFrame(JSContext *cx, FrameGuard *fg)
+ExecuteState::pushInterpreterFrame(JSContext *cx)
 {
     return cx->runtime()->interpreterStack().pushExecuteFrame(cx, script_, thisv_, scopeChain_,
-                                                              type_, evalInFrame_, fg);
+                                                              type_, evalInFrame_);
 }
 
 bool
 js::RunScript(JSContext *cx, RunState &state)
 {
     JS_CHECK_RECURSION(cx, return false);
 
     SPSEntryMarker marker(cx->runtime());
@@ -935,33 +935,34 @@ TryNoteIter::settle()
          * depth exceeding the current one and this condition is what we use to
          * filter them out.
          */
         if (tn->stackDepth <= regs.stackDepth())
             break;
     }
 }
 
-#define PUSH_COPY(v)             do { *regs.sp++ = (v); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
-#define PUSH_COPY_SKIP_CHECK(v)  *regs.sp++ = (v)
-#define PUSH_NULL()              regs.sp++->setNull()
-#define PUSH_UNDEFINED()         regs.sp++->setUndefined()
-#define PUSH_BOOLEAN(b)          regs.sp++->setBoolean(b)
-#define PUSH_DOUBLE(d)           regs.sp++->setDouble(d)
-#define PUSH_INT32(i)            regs.sp++->setInt32(i)
-#define PUSH_STRING(s)           do { regs.sp++->setString(s); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
-#define PUSH_OBJECT(obj)         do { regs.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
-#define PUSH_OBJECT_OR_NULL(obj) do { regs.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, regs.sp[-1]); } while (0)
-#define PUSH_HOLE()              regs.sp++->setMagic(JS_ELEMENTS_HOLE)
-#define POP_COPY_TO(v)           (v) = *--regs.sp
-#define POP_RETURN_VALUE()       regs.fp()->setReturnValue(*--regs.sp)
+#define REGS                     (activation.regs())
+#define PUSH_COPY(v)             do { *REGS.sp++ = (v); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
+#define PUSH_COPY_SKIP_CHECK(v)  *REGS.sp++ = (v)
+#define PUSH_NULL()              REGS.sp++->setNull()
+#define PUSH_UNDEFINED()         REGS.sp++->setUndefined()
+#define PUSH_BOOLEAN(b)          REGS.sp++->setBoolean(b)
+#define PUSH_DOUBLE(d)           REGS.sp++->setDouble(d)
+#define PUSH_INT32(i)            REGS.sp++->setInt32(i)
+#define PUSH_STRING(s)           do { REGS.sp++->setString(s); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
+#define PUSH_OBJECT(obj)         do { REGS.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
+#define PUSH_OBJECT_OR_NULL(obj) do { REGS.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)
+#define PUSH_HOLE()              REGS.sp++->setMagic(JS_ELEMENTS_HOLE)
+#define POP_COPY_TO(v)           (v) = *--REGS.sp
+#define POP_RETURN_VALUE()       REGS.fp()->setReturnValue(*--REGS.sp)
 
 #define FETCH_OBJECT(cx, n, obj)                                              \
     JS_BEGIN_MACRO                                                            \
-        HandleValue val = regs.stackHandleAt(n);                              \
+        HandleValue val = REGS.stackHandleAt(n);                              \
         obj = ToObjectFromStack((cx), (val));                                 \
         if (!obj)                                                             \
             goto error;                                                       \
     JS_END_MACRO
 
 /*
  * Ensure that the interpreter switch can close call-bytecode cases in the
  * same way as non-call bytecodes.
@@ -1011,36 +1012,16 @@ js::IteratorNext(JSContext *cx, HandleOb
             rval.setString(*ni->current());
             ni->incCursor();
             return true;
         }
     }
     return js_IteratorNext(cx, iterobj, rval);
 }
 
-FrameGuard::FrameGuard(RunState &state, FrameRegs &regs)
-  : state_(state),
-    regs_(regs),
-    stack_(nullptr),
-    fp_(nullptr)
-{ }
-
-FrameGuard::~FrameGuard()
-{
-    if (state_.isGenerator()) {
-        JSGenerator *gen = state_.asGenerator()->gen();
-        gen->fp->unsetPushedSPSFrame();
-        gen->regs = regs_;
-        return;
-    }
-
-    if (fp_)
-        stack_->releaseFrame(fp_);
-}
-
 /*
  * Compute the implicit |this| parameter for a call expression where the callee
  * funval was resolved from an unqualified name reference to a property on obj
  * (an object on the scope chain).
  *
  * We can avoid computing |this| eagerly and push the implicit callee-coerced
  * |this| value, undefined, if any of these conditions hold:
  *
@@ -1205,107 +1186,145 @@ SetObjectElementOperation(JSContext *cx,
 
     RootedValue tmp(cx, value);
     return JSObject::setGeneric(cx, obj, obj, id, &tmp, strict);
 }
 
 static JS_NEVER_INLINE bool
 Interpret(JSContext *cx, RunState &state)
 {
-    JSAutoResolveFlags rf(cx, RESOLVE_INFER);
-
-    gc::MaybeVerifyBarriers(cx, true);
-
-    JS_ASSERT(!cx->compartment()->activeAnalysis);
-
-#define CHECK_PCCOUNT_INTERRUPTS() \
-    JS_ASSERT_IF(script->hasScriptCounts, switchMask == EnableInterruptsPseudoOpcode)
+/*
+ * Define macros for an interpreter loop. Opcode dispatch may be either by a
+ * switch statement or by indirect goto (aka a threaded interpreter), depending
+ * on compiler support.
+ *
+ * Threaded interpretation appears to be well-supported by GCC 3 and higher.
+ * IBM's C compiler when run with the right options (e.g., -qlanglvl=extended)
+ * also supports threading. Ditto the SunPro C compiler.
+ */
+#if (__GNUC__ >= 3 ||                                                         \
+     (__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) ||                      \
+     __SUNPRO_C >= 0x570)
+// Non-standard but faster indirect-goto-based dispatch.
+# define INTERPRETER_LOOP()
+# define CASE(OP)                 label_##OP:
+# define DEFAULT()                label_default:
+# define DISPATCH_TO(OP)          goto *addresses[(OP)]
+
+# define LABEL(X)                 (&&label_##X)
+
+    // Use addresses instead of offsets to optimize for runtime speed over
+    // load-time relocation overhead.
+    static const void *const addresses[EnableInterruptsPseudoOpcode + 1] = {
+# define OPDEF(op,v,n,t,l,u,d,f)  LABEL(op),
+# define OPPAD(v)                                                             \
+    ((v) == EnableInterruptsPseudoOpcode                                      \
+     ? LABEL(EnableInterruptsPseudoOpcode)                                    \
+     : LABEL(default)),
+# include "jsopcode.tbl"
+# undef OPDEF
+# undef OPPAD
+    };
+#else
+// Portable switch-based dispatch.
+# define INTERPRETER_LOOP()       the_switch: switch (switchOp)
+# define CASE(OP)                 case OP:
+# define DEFAULT()                default:
+# define DISPATCH_TO(OP)                                                      \
+    JS_BEGIN_MACRO                                                            \
+        switchOp = (OP);                                                      \
+        goto the_switch;                                                      \
+    JS_END_MACRO
+
+    // This variable is effectively a parameter to the_switch.
+    jsbytecode switchOp;
+#endif
 
     /*
+     * Increment REGS.pc by N, load the opcode at that position,
+     * and jump to the code to execute it.
+     *
      * When Debugger puts a script in single-step mode, all js::Interpret
      * invocations that might be presently running that script must have
      * interrupts enabled. It's not practical to simply check
      * script->stepModeEnabled() at each point some callee could have changed
      * it, because there are so many places js::Interpret could possibly cause
      * JavaScript to run: each place an object might be coerced to a primitive
      * or a number, for example. So instead, we expose a simple mechanism to
      * let Debugger tweak the affected js::Interpret frames when an onStep
-     * handler is added: setting switchMask to EnableInterruptsPseudoOpcode
-     * will enable interrupts.
+     * handler is added: calling activation.enableInterruptsUnconditionally()
+     * will enable interrupts, and activation.opMask() is or'd with the opcode
+     * to implement a simple alternate dispatch.
      */
-    static_assert(EnableInterruptsPseudoOpcode >= JSOP_LIMIT,
-                  "EnableInterruptsPseudoOpcode must be greater than any opcode");
-    static_assert(EnableInterruptsPseudoOpcode == jsbytecode(-1),
-                  "EnableInterruptsPseudoOpcode must be the maximum jsbytecode value");
-    jsbytecode switchMask = 0;
-    jsbytecode switchOp;
-
-#define DO_OP()            goto do_op
-
-#define BEGIN_CASE(OP)     case OP:
-#define END_CASE(OP)                                                          \
+#define ADVANCE_AND_DISPATCH(N)                                               \
     JS_BEGIN_MACRO                                                            \
-        len = OP##_LENGTH;                                                    \
-        goto advanceAndDoOp;                                                  \
-    JS_END_MACRO;
-
-#define END_VARLEN_CASE    goto advanceAndDoOp;
-
-#define LOAD_DOUBLE(PCOFF, dbl)                                               \
-    ((dbl) = script->getConst(GET_UINT32_INDEX(regs.pc + (PCOFF))).toDouble())
+        REGS.pc += (N);                                                       \
+        SANITY_CHECKS();                                                      \
+        DISPATCH_TO(*REGS.pc | activation.opMask());                          \
+    JS_END_MACRO
+
+   /*
+    * Shorthand for the common sequence at the end of a fixed-size opcode.
+    */
+#define END_CASE(OP)              ADVANCE_AND_DISPATCH(OP##_LENGTH);
 
     /*
      * Prepare to call a user-supplied branch handler, and abort the script
      * if it returns false.
      */
 #define CHECK_BRANCH()                                                        \
     JS_BEGIN_MACRO                                                            \
         if (cx->runtime()->interrupt && !js_HandleExecutionInterrupt(cx))     \
             goto error;                                                       \
     JS_END_MACRO
 
+    /*
+     * This is a simple wrapper around ADVANCE_AND_DISPATCH which also does
+     * a CHECK_BRANCH() if n is not positive, which possibly indicates that it
+     * is the backedge of a loop.
+     */
 #define BRANCH(n)                                                             \
     JS_BEGIN_MACRO                                                            \
         int32_t nlen = (n);                                                   \
-        regs.pc += nlen;                                                      \
-        op = (JSOp) *regs.pc;                                                 \
         if (nlen <= 0)                                                        \
             CHECK_BRANCH();                                                   \
-        DO_OP();                                                              \
+        ADVANCE_AND_DISPATCH(nlen);                                           \
     JS_END_MACRO
 
+#define LOAD_DOUBLE(PCOFF, dbl)                                               \
+    ((dbl) = script->getConst(GET_UINT32_INDEX(REGS.pc + (PCOFF))).toDouble())
+
 #define SET_SCRIPT(s)                                                         \
     JS_BEGIN_MACRO                                                            \
         script = (s);                                                         \
         if (script->hasAnyBreakpointsOrStepMode() || script->hasScriptCounts) \
-            switchMask = EnableInterruptsPseudoOpcode; /* Enable interrupts. */ \
+            activation.enableInterruptsUnconditionally();                     \
     JS_END_MACRO
 
-    FrameRegs regs;
-    FrameGuard fg(state, regs);
-
-    StackFrame *entryFrame = state.pushInterpreterFrame(cx, &fg);
+#define SANITY_CHECKS()                                                       \
+    JS_BEGIN_MACRO                                                            \
+        js::gc::MaybeVerifyBarriers(cx);                                      \
+        JS_ASSERT_IF(script->hasScriptCounts,                                 \
+                     activation.opMask() == EnableInterruptsPseudoOpcode);    \
+    JS_END_MACRO
+
+    JSAutoResolveFlags rf(cx, RESOLVE_INFER);
+
+    gc::MaybeVerifyBarriers(cx, true);
+    JS_ASSERT(!cx->compartment()->activeAnalysis);
+
+    StackFrame *entryFrame = state.pushInterpreterFrame(cx);
     if (!entryFrame)
         return false;
 
-    if (!state.isGenerator()) {
-        regs.prepareToRun(*entryFrame, state.script());
-        JS_ASSERT(regs.pc == state.script()->code);
-    } else {
-        regs = state.asGenerator()->gen()->regs;
-    }
-
-    JS_ASSERT_IF(entryFrame->isEvalFrame(), state.script()->isActiveEval);
-
-    InterpreterActivation activation(cx, entryFrame, regs, &switchMask);
-
-    /* Copy in hot values that change infrequently. */
-    JSRuntime *const rt = cx->runtime();
+    InterpreterActivation activation(state, cx, entryFrame);
+
+    /* The script is used frequently, so keep a local copy. */
     RootedScript script(cx);
-    SET_SCRIPT(regs.fp()->script());
+    SET_SCRIPT(REGS.fp()->script());
 
 #if JS_TRACE_LOGGING
     TraceLogging::defaultLogger()->log(TraceLogging::SCRIPT_START, script);
     TraceLogging::defaultLogger()->log(TraceLogging::INFO_ENGINE_INTERPRETER);
 #endif
 
     /*
      * Pool of rooters for use in this interpreter frame. References to these
@@ -1320,1744 +1339,1755 @@ Interpret(JSContext *cx, RunState &state
     RootedFunction rootFunction0(cx);
     RootedTypeObject rootType0(cx);
     RootedPropertyName rootName0(cx);
     RootedId rootId0(cx);
     RootedShape rootShape0(cx);
     RootedScript rootScript0(cx);
     DebugOnly<uint32_t> blockDepth;
 
-    if (JS_UNLIKELY(regs.fp()->isGeneratorFrame())) {
-        JS_ASSERT(size_t(regs.pc - script->code) <= script->length);
-        JS_ASSERT(regs.stackDepth() <= script->nslots);
+    if (JS_UNLIKELY(REGS.fp()->isGeneratorFrame())) {
+        JS_ASSERT(size_t(REGS.pc - script->code) <= script->length);
+        JS_ASSERT(REGS.stackDepth() <= script->nslots);
 
         /*
          * To support generator_throw and to catch ignored exceptions,
          * fail if cx->isExceptionPending() is true.
          */
         if (cx->isExceptionPending()) {
-            probes::EnterScript(cx, script, script->function(), regs.fp());
+            probes::EnterScript(cx, script, script->function(), REGS.fp());
             goto error;
         }
     }
 
     /* State communicated between non-local jumps: */
     bool interpReturnOK;
 
-    if (!entryFrame->isGeneratorFrame()) {
-        if (!entryFrame->prologue(cx))
+    if (!activation.entryFrame()->isGeneratorFrame()) {
+        if (!activation.entryFrame()->prologue(cx))
             goto error;
     } else {
-        probes::EnterScript(cx, script, script->function(), entryFrame);
+        probes::EnterScript(cx, script, script->function(), activation.entryFrame());
     }
     if (cx->compartment()->debugMode()) {
-        JSTrapStatus status = ScriptDebugPrologue(cx, entryFrame);
+        JSTrapStatus status = ScriptDebugPrologue(cx, activation.entryFrame());
         switch (status) {
           case JSTRAP_CONTINUE:
             break;
           case JSTRAP_RETURN:
             interpReturnOK = true;
             goto forced_return;
           case JSTRAP_THROW:
           case JSTRAP_ERROR:
             goto error;
           default:
             MOZ_ASSUME_UNREACHABLE("bad ScriptDebugPrologue status");
         }
     }
 
-    /*
-     * It is important that "op" be initialized before calling DO_OP because
-     * it is possible for "op" to be specially assigned during the normal
-     * processing of an opcode while looping. We rely on |advanceAndDoOp:| to
-     * manage "op" correctly in all other cases.
-     */
-    JSOp op;
-    int32_t len;
-    len = 0;
-
-    if (rt->profilingScripts || cx->runtime()->debugHooks.interruptHook)
-        switchMask = EnableInterruptsPseudoOpcode; /* Enable interrupts. */
-
-  advanceAndDoOp:
-    js::gc::MaybeVerifyBarriers(cx);
-    regs.pc += len;
-    op = (JSOp) *regs.pc;
-
-  do_op:
-    CHECK_PCCOUNT_INTERRUPTS();
-    switchOp = jsbytecode(op) | switchMask;
-  do_switch:
-    switch (switchOp) {
-
-BEGIN_CASE(EnableInterruptsPseudoOpcode)
+    if (cx->runtime()->profilingScripts || cx->runtime()->debugHooks.interruptHook)
+        activation.enableInterruptsUnconditionally();
+
+  enterInterpreterLoop:
+    // Enter the interpreter loop starting at the current pc.
+    ADVANCE_AND_DISPATCH(0);
+
+INTERPRETER_LOOP() {
+
+CASE(EnableInterruptsPseudoOpcode)
 {
     bool moreInterrupts = false;
+    jsbytecode op = *REGS.pc;
 
     if (cx->runtime()->profilingScripts) {
         if (!script->hasScriptCounts)
             script->initScriptCounts(cx);
         moreInterrupts = true;
     }
 
     if (script->hasScriptCounts) {
-        PCCounts counts = script->getPCCounts(regs.pc);
+        PCCounts counts = script->getPCCounts(REGS.pc);
         counts.get(PCCounts::BASE_INTERP)++;
         moreInterrupts = true;
     }
 
     JSInterruptHook hook = cx->runtime()->debugHooks.interruptHook;
     if (hook || script->stepModeEnabled()) {
         RootedValue rval(cx);
         JSTrapStatus status = JSTRAP_CONTINUE;
         if (hook)
-            status = hook(cx, script, regs.pc, rval.address(), cx->runtime()->debugHooks.interruptHookData);
+            status = hook(cx, script, REGS.pc, rval.address(), cx->runtime()->debugHooks.interruptHookData);
         if (status == JSTRAP_CONTINUE && script->stepModeEnabled())
             status = Debugger::onSingleStep(cx, &rval);
         switch (status) {
           case JSTRAP_ERROR:
             goto error;
           case JSTRAP_CONTINUE:
             break;
           case JSTRAP_RETURN:
-            regs.fp()->setReturnValue(rval);
+            REGS.fp()->setReturnValue(rval);
             interpReturnOK = true;
             goto forced_return;
           case JSTRAP_THROW:
             cx->setPendingException(rval);
             goto error;
           default:;
         }
         moreInterrupts = true;
     }
 
     if (script->hasAnyBreakpointsOrStepMode())
         moreInterrupts = true;
 
-    if (script->hasBreakpointsAt(regs.pc)) {
+    if (script->hasBreakpointsAt(REGS.pc)) {
         RootedValue rval(cx);
         JSTrapStatus status = Debugger::onTrap(cx, &rval);
         switch (status) {
           case JSTRAP_ERROR:
             goto error;
           case JSTRAP_RETURN:
-            regs.fp()->setReturnValue(rval);
+            REGS.fp()->setReturnValue(rval);
             interpReturnOK = true;
             goto forced_return;
           case JSTRAP_THROW:
             cx->setPendingException(rval);
             goto error;
           default:
             break;
         }
         JS_ASSERT(status == JSTRAP_CONTINUE);
         JS_ASSERT(rval.isInt32() && rval.toInt32() == op);
     }
 
-    JS_ASSERT(switchMask == EnableInterruptsPseudoOpcode);
-    switchMask = moreInterrupts ? EnableInterruptsPseudoOpcode : 0;
-
-    switchOp = jsbytecode(op);
-    goto do_switch;
+    JS_ASSERT(activation.opMask() == EnableInterruptsPseudoOpcode);
+    if (!moreInterrupts)
+        activation.clearInterruptsMask();
+
+    /* Commence executing the actual opcode. */
+    SANITY_CHECKS();
+    DISPATCH_TO(op);
 }
 
 /* Various 1-byte no-ops. */
-BEGIN_CASE(JSOP_NOP)
-BEGIN_CASE(JSOP_UNUSED125)
-BEGIN_CASE(JSOP_UNUSED126)
-BEGIN_CASE(JSOP_UNUSED132)
-BEGIN_CASE(JSOP_UNUSED148)
-BEGIN_CASE(JSOP_UNUSED161)
-BEGIN_CASE(JSOP_UNUSED162)
-BEGIN_CASE(JSOP_UNUSED163)
-BEGIN_CASE(JSOP_UNUSED164)
-BEGIN_CASE(JSOP_UNUSED165)
-BEGIN_CASE(JSOP_UNUSED166)
-BEGIN_CASE(JSOP_UNUSED167)
-BEGIN_CASE(JSOP_UNUSED168)
-BEGIN_CASE(JSOP_UNUSED169)
-BEGIN_CASE(JSOP_UNUSED170)
-BEGIN_CASE(JSOP_UNUSED171)
-BEGIN_CASE(JSOP_UNUSED172)
-BEGIN_CASE(JSOP_UNUSED173)
-BEGIN_CASE(JSOP_UNUSED174)
-BEGIN_CASE(JSOP_UNUSED175)
-BEGIN_CASE(JSOP_UNUSED176)
-BEGIN_CASE(JSOP_UNUSED177)
-BEGIN_CASE(JSOP_UNUSED178)
-BEGIN_CASE(JSOP_UNUSED179)
-BEGIN_CASE(JSOP_UNUSED180)
-BEGIN_CASE(JSOP_UNUSED181)
-BEGIN_CASE(JSOP_UNUSED182)
-BEGIN_CASE(JSOP_UNUSED183)
-BEGIN_CASE(JSOP_UNUSED189)
-BEGIN_CASE(JSOP_UNUSED190)
-BEGIN_CASE(JSOP_UNUSED200)
-BEGIN_CASE(JSOP_UNUSED201)
-BEGIN_CASE(JSOP_UNUSED208)
-BEGIN_CASE(JSOP_UNUSED209)
-BEGIN_CASE(JSOP_UNUSED210)
-BEGIN_CASE(JSOP_UNUSED219)
-BEGIN_CASE(JSOP_UNUSED220)
-BEGIN_CASE(JSOP_UNUSED221)
-BEGIN_CASE(JSOP_UNUSED222)
-BEGIN_CASE(JSOP_UNUSED223)
-BEGIN_CASE(JSOP_CONDSWITCH)
-BEGIN_CASE(JSOP_TRY)
+CASE(JSOP_NOP)
+CASE(JSOP_UNUSED44)
+CASE(JSOP_UNUSED45)
+CASE(JSOP_UNUSED46)
+CASE(JSOP_UNUSED47)
+CASE(JSOP_UNUSED48)
+CASE(JSOP_UNUSED49)
+CASE(JSOP_UNUSED50)
+CASE(JSOP_UNUSED51)
+CASE(JSOP_UNUSED52)
+CASE(JSOP_UNUSED101)
+CASE(JSOP_UNUSED102)
+CASE(JSOP_UNUSED103)
+CASE(JSOP_UNUSED104)
+CASE(JSOP_UNUSED107)
+CASE(JSOP_UNUSED125)
+CASE(JSOP_UNUSED126)
+CASE(JSOP_UNUSED132)
+CASE(JSOP_UNUSED139)
+CASE(JSOP_UNUSED140)
+CASE(JSOP_UNUSED141)
+CASE(JSOP_UNUSED142)
+CASE(JSOP_UNUSED147)
+CASE(JSOP_UNUSED148)
+CASE(JSOP_BACKPATCH)
+CASE(JSOP_UNUSED150)
+CASE(JSOP_UNUSED156)
+CASE(JSOP_UNUSED157)
+CASE(JSOP_UNUSED158)
+CASE(JSOP_UNUSED159)
+CASE(JSOP_UNUSED161)
+CASE(JSOP_UNUSED162)
+CASE(JSOP_UNUSED163)
+CASE(JSOP_UNUSED164)
+CASE(JSOP_UNUSED165)
+CASE(JSOP_UNUSED166)
+CASE(JSOP_UNUSED167)
+CASE(JSOP_UNUSED168)
+CASE(JSOP_UNUSED169)
+CASE(JSOP_UNUSED170)
+CASE(JSOP_UNUSED171)
+CASE(JSOP_UNUSED172)
+CASE(JSOP_UNUSED173)
+CASE(JSOP_UNUSED174)
+CASE(JSOP_UNUSED175)
+CASE(JSOP_UNUSED176)
+CASE(JSOP_UNUSED177)
+CASE(JSOP_UNUSED178)
+CASE(JSOP_UNUSED179)
+CASE(JSOP_UNUSED180)
+CASE(JSOP_UNUSED181)
+CASE(JSOP_UNUSED182)
+CASE(JSOP_UNUSED183)
+CASE(JSOP_UNUSED189)
+CASE(JSOP_UNUSED190)
+CASE(JSOP_UNUSED191)
+CASE(JSOP_UNUSED192)
+CASE(JSOP_UNUSED196)
+CASE(JSOP_UNUSED200)
+CASE(JSOP_UNUSED201)
+CASE(JSOP_GETFUNNS)
+CASE(JSOP_UNUSED208)
+CASE(JSOP_UNUSED209)
+CASE(JSOP_UNUSED210)
+CASE(JSOP_UNUSED219)
+CASE(JSOP_UNUSED220)
+CASE(JSOP_UNUSED221)
+CASE(JSOP_UNUSED222)
+CASE(JSOP_UNUSED223)
+CASE(JSOP_CONDSWITCH)
+CASE(JSOP_TRY)
 {
-    JS_ASSERT(js_CodeSpec[op].length == 1);
-    len = 1;
-    goto advanceAndDoOp;
+    JS_ASSERT(js_CodeSpec[*REGS.pc].length == 1);
+    ADVANCE_AND_DISPATCH(1);
 }
 
-BEGIN_CASE(JSOP_LOOPHEAD)
+CASE(JSOP_LOOPHEAD)
 END_CASE(JSOP_LOOPHEAD)
 
-BEGIN_CASE(JSOP_LABEL)
+CASE(JSOP_LABEL)
 END_CASE(JSOP_LABEL)
 
-BEGIN_CASE(JSOP_LOOPENTRY)
+CASE(JSOP_LOOPENTRY)
 
 #ifdef JS_ION
     // Attempt on-stack replacement with Baseline code.
     if (jit::IsBaselineEnabled(cx)) {
-        jit::MethodStatus status = jit::CanEnterBaselineAtBranch(cx, regs.fp(), false);
+        jit::MethodStatus status = jit::CanEnterBaselineAtBranch(cx, REGS.fp(), false);
         if (status == jit::Method_Error)
             goto error;
         if (status == jit::Method_Compiled) {
-            jit::IonExecStatus maybeOsr = jit::EnterBaselineAtBranch(cx, regs.fp(), regs.pc);
+            jit::IonExecStatus maybeOsr = jit::EnterBaselineAtBranch(cx, REGS.fp(), REGS.pc);
 
             // We failed to call into baseline at all, so treat as an error.
             if (maybeOsr == jit::IonExec_Aborted)
                 goto error;
 
             interpReturnOK = (maybeOsr == jit::IonExec_Ok);
 
-            if (entryFrame != regs.fp())
+            if (activation.entryFrame() != REGS.fp())
                 goto jit_return_pop_frame;
             goto leave_on_safe_point;
         }
     }
 #endif /* JS_ION */
 
 END_CASE(JSOP_LOOPENTRY)
 
-BEGIN_CASE(JSOP_NOTEARG)
+CASE(JSOP_NOTEARG)
 END_CASE(JSOP_NOTEARG)
 
-BEGIN_CASE(JSOP_LINENO)
+CASE(JSOP_LINENO)
 END_CASE(JSOP_LINENO)
 
-BEGIN_CASE(JSOP_UNDEFINED)
+CASE(JSOP_UNDEFINED)
     PUSH_UNDEFINED();
 END_CASE(JSOP_UNDEFINED)
 
-BEGIN_CASE(JSOP_POP)
-    regs.sp--;
+CASE(JSOP_POP)
+    REGS.sp--;
 END_CASE(JSOP_POP)
 
-BEGIN_CASE(JSOP_POPN)
-    JS_ASSERT(GET_UINT16(regs.pc) <= regs.stackDepth());
-    regs.sp -= GET_UINT16(regs.pc);
+CASE(JSOP_POPN)
+    JS_ASSERT(GET_UINT16(REGS.pc) <= REGS.stackDepth());
+    REGS.sp -= GET_UINT16(REGS.pc);
 #ifdef DEBUG
-    if (StaticBlockObject *block = regs.fp()->maybeBlockChain())
-        JS_ASSERT(regs.stackDepth() >= block->stackDepth() + block->slotCount());
+    if (StaticBlockObject *block = REGS.fp()->maybeBlockChain())
+        JS_ASSERT(REGS.stackDepth() >= block->stackDepth() + block->slotCount());
 #endif
 END_CASE(JSOP_POPN)
 
-BEGIN_CASE(JSOP_SETRVAL)
-BEGIN_CASE(JSOP_POPV)
+CASE(JSOP_SETRVAL)
+CASE(JSOP_POPV)
     POP_RETURN_VALUE();
 END_CASE(JSOP_POPV)
 
-BEGIN_CASE(JSOP_ENTERWITH)
+CASE(JSOP_ENTERWITH)
 {
     RootedValue &val = rootValue0;
-    val = regs.sp[-1];
-
-    if (!EnterWith(cx, regs.fp(), val, regs.stackDepth() - 1))
+    val = REGS.sp[-1];
+
+    if (!EnterWith(cx, REGS.fp(), val, REGS.stackDepth() - 1))
         goto error;
 
     /*
      * We must ensure that different "with" blocks have different stack depth
      * associated with them. This allows the try handler search to properly
      * recover the scope chain. Thus we must keep the stack at least at the
      * current level.
      *
      * We set sp[-1] to the current "with" object to help asserting the
      * enter/leave balance in [leavewith].
      */
-    regs.sp[-1].setObject(*regs.fp()->scopeChain());
+    REGS.sp[-1].setObject(*REGS.fp()->scopeChain());
 }
 END_CASE(JSOP_ENTERWITH)
 
-BEGIN_CASE(JSOP_LEAVEWITH)
-    JS_ASSERT(regs.sp[-1].toObject() == *regs.fp()->scopeChain());
-    regs.fp()->popWith(cx);
-    regs.sp--;
+CASE(JSOP_LEAVEWITH)
+    JS_ASSERT(REGS.sp[-1].toObject() == *REGS.fp()->scopeChain());
+    REGS.fp()->popWith(cx);
+    REGS.sp--;
 END_CASE(JSOP_LEAVEWITH)
 
-BEGIN_CASE(JSOP_RETURN)
+CASE(JSOP_RETURN)
     POP_RETURN_VALUE();
     /* FALL THROUGH */
 
-BEGIN_CASE(JSOP_RETRVAL)    /* fp return value already set */
-BEGIN_CASE(JSOP_STOP)
+CASE(JSOP_RETRVAL)    /* fp return value already set */
+CASE(JSOP_STOP)
 {
     /*
      * When the inlined frame exits with an exception or an error, ok will be
      * false after the inline_return label.
      */
     CHECK_BRANCH();
 
     interpReturnOK = true;
-    if (entryFrame != regs.fp())
+    if (activation.entryFrame() != REGS.fp())
   inline_return:
     {
 #if JS_TRACE_LOGGING
         TraceLogging::defaultLogger()->log(TraceLogging::SCRIPT_STOP);
 #endif
 
         if (cx->compartment()->debugMode())
-            interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
-
-        if (!regs.fp()->isYielding())
-            regs.fp()->epilogue(cx);
+            interpReturnOK = ScriptDebugEpilogue(cx, REGS.fp(), interpReturnOK);
+
+        if (!REGS.fp()->isYielding())
+            REGS.fp()->epilogue(cx);
         else
-            probes::ExitScript(cx, script, script->function(), regs.fp());
+            probes::ExitScript(cx, script, script->function(), REGS.fp());
 
 #if defined(JS_ION)
   jit_return_pop_frame:
 #endif
 
-        activation.popInlineFrame(regs.fp());
-        SET_SCRIPT(regs.fp()->script());
+        activation.popInlineFrame(REGS.fp());
+        SET_SCRIPT(REGS.fp()->script());
 
 #if defined(JS_ION)
   jit_return:
 #endif
 
-        JS_ASSERT(js_CodeSpec[*regs.pc].format & JOF_INVOKE);
+        JS_ASSERT(js_CodeSpec[*REGS.pc].format & JOF_INVOKE);
 
         /* Resume execution in the calling frame. */
         if (JS_LIKELY(interpReturnOK)) {
-            TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
-
-            len = JSOP_CALL_LENGTH;
-            goto advanceAndDoOp;
+            TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
+
+            ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);
         }
 
         /* Increment pc so that |sp - fp->slots == ReconstructStackDepth(pc)|. */
-        regs.pc += JSOP_CALL_LENGTH;
+        REGS.pc += JSOP_CALL_LENGTH;
         goto error;
     } else {
-        JS_ASSERT(regs.stackDepth() == 0);
+        JS_ASSERT(REGS.stackDepth() == 0);
     }
     interpReturnOK = true;
     goto exit;
 }
 
-BEGIN_CASE(JSOP_DEFAULT)
-    regs.sp--;
+CASE(JSOP_DEFAULT)
+    REGS.sp--;
     /* FALL THROUGH */
-BEGIN_CASE(JSOP_GOTO)
+CASE(JSOP_GOTO)
 {
-    BRANCH(GET_JUMP_OFFSET(regs.pc));
+    BRANCH(GET_JUMP_OFFSET(REGS.pc));
 }
 
-BEGIN_CASE(JSOP_IFEQ)
+CASE(JSOP_IFEQ)
 {
-    bool cond = ToBooleanOp(regs);
-    regs.sp--;
+    bool cond = ToBooleanOp(REGS);
+    REGS.sp--;
     if (!cond)
-        BRANCH(GET_JUMP_OFFSET(regs.pc));
+        BRANCH(GET_JUMP_OFFSET(REGS.pc));
 }
 END_CASE(JSOP_IFEQ)
 
-BEGIN_CASE(JSOP_IFNE)
+CASE(JSOP_IFNE)
 {
-    bool cond = ToBooleanOp(regs);
-    regs.sp--;
+    bool cond = ToBooleanOp(REGS);
+    REGS.sp--;
     if (cond)
-        BRANCH(GET_JUMP_OFFSET(regs.pc));
+        BRANCH(GET_JUMP_OFFSET(REGS.pc));
 }
 END_CASE(JSOP_IFNE)
 
-BEGIN_CASE(JSOP_OR)
+CASE(JSOP_OR)
 {
-    bool cond = ToBooleanOp(regs);
-    if (cond) {
-        len = GET_JUMP_OFFSET(regs.pc);
-        goto advanceAndDoOp;
-    }
+    bool cond = ToBooleanOp(REGS);
+    if (cond)
+        ADVANCE_AND_DISPATCH(GET_JUMP_OFFSET(REGS.pc));
 }
 END_CASE(JSOP_OR)
 
-BEGIN_CASE(JSOP_AND)
+CASE(JSOP_AND)
 {
-    bool cond = ToBooleanOp(regs);
-    if (!cond) {
-        len = GET_JUMP_OFFSET(regs.pc);
-        goto advanceAndDoOp;
-    }
+    bool cond = ToBooleanOp(REGS);
+    if (!cond)
+        ADVANCE_AND_DISPATCH(GET_JUMP_OFFSET(REGS.pc));
 }
 END_CASE(JSOP_AND)
 
 #define FETCH_ELEMENT_ID(n, id)                                               \
     JS_BEGIN_MACRO                                                            \
-        if (!ValueToId<CanGC>(cx, regs.stackHandleAt(n), &(id)))              \
+        if (!ValueToId<CanGC>(cx, REGS.stackHandleAt(n), &(id))) \
             goto error;                                                       \
     JS_END_MACRO
 
 #define TRY_BRANCH_AFTER_COND(cond,spdec)                                     \
     JS_BEGIN_MACRO                                                            \
-        JS_ASSERT(js_CodeSpec[op].length == 1);                               \
-        unsigned diff_ = (unsigned) GET_UINT8(regs.pc) - (unsigned) JSOP_IFEQ;\
+        JS_ASSERT(js_CodeSpec[*REGS.pc].length == 1);                         \
+        unsigned diff_ = (unsigned) GET_UINT8(REGS.pc) - (unsigned) JSOP_IFEQ; \
         if (diff_ <= 1) {                                                     \
-            regs.sp -= (spdec);                                               \
+            REGS.sp -= (spdec);                                               \
             if ((cond) == (diff_ != 0)) {                                     \
-                ++regs.pc;                                                    \
-                BRANCH(GET_JUMP_OFFSET(regs.pc));                             \
+                ++REGS.pc;                                                    \
+                BRANCH(GET_JUMP_OFFSET(REGS.pc));                             \
             }                                                                 \
-            len = 1 + JSOP_IFEQ_LENGTH;                                       \
-            goto advanceAndDoOp;                                              \
+            ADVANCE_AND_DISPATCH(1 + JSOP_IFEQ_LENGTH);                       \
         }                                                                     \
     JS_END_MACRO
 
-BEGIN_CASE(JSOP_IN)
+CASE(JSOP_IN)
 {
-    HandleValue rref = regs.stackHandleAt(-1);
+    HandleValue rref = REGS.stackHandleAt(-1);
     if (!rref.isObject()) {
         js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NullPtr());
         goto error;
     }
     RootedObject &obj = rootObject0;
     obj = &rref.toObject();
     RootedId &id = rootId0;
     FETCH_ELEMENT_ID(-2, id);
     RootedObject &obj2 = rootObject1;
     RootedShape &prop = rootShape0;
     if (!JSObject::lookupGeneric(cx, obj, id, &obj2, &prop))
         goto error;
     bool cond = prop != nullptr;
     prop = nullptr;
     TRY_BRANCH_AFTER_COND(cond, 2);
-    regs.sp--;
-    regs.sp[-1].setBoolean(cond);
+    REGS.sp--;
+    REGS.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_IN)
 
-BEGIN_CASE(JSOP_ITER)
+CASE(JSOP_ITER)
 {
-    JS_ASSERT(regs.stackDepth() >= 1);
-    uint8_t flags = GET_UINT8(regs.pc);
-    MutableHandleValue res = regs.stackHandleAt(-1);
+    JS_ASSERT(REGS.stackDepth() >= 1);
+    uint8_t flags = GET_UINT8(REGS.pc);
+    MutableHandleValue res = REGS.stackHandleAt(-1);
     if (!ValueToIterator(cx, flags, res))
         goto error;
     JS_ASSERT(!res.isPrimitive());
 }
 END_CASE(JSOP_ITER)
 
-BEGIN_CASE(JSOP_MOREITER)
+CASE(JSOP_MOREITER)
 {
-    JS_ASSERT(regs.stackDepth() >= 1);
-    JS_ASSERT(regs.sp[-1].isObject());
+    JS_ASSERT(REGS.stackDepth() >= 1);
+    JS_ASSERT(REGS.sp[-1].isObject());
     PUSH_NULL();
     bool cond;
-    MutableHandleValue res = regs.stackHandleAt(-1);
-    if (!IteratorMore(cx, &regs.sp[-2].toObject(), &cond, res))
+    MutableHandleValue res = REGS.stackHandleAt(-1);
+    if (!IteratorMore(cx, &REGS.sp[-2].toObject(), &cond, res))
         goto error;
-    regs.sp[-1].setBoolean(cond);
+    REGS.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_MOREITER)
 
-BEGIN_CASE(JSOP_ITERNEXT)
+CASE(JSOP_ITERNEXT)
 {
-    JS_ASSERT(regs.sp[-1].isObject());
+    JS_ASSERT(REGS.sp[-1].isObject());
     PUSH_NULL();
-    MutableHandleValue res = regs.stackHandleAt(-1);
+    MutableHandleValue res = REGS.stackHandleAt(-1);
     RootedObject &obj = rootObject0;
-    obj = &regs.sp[-2].toObject();
+    obj = &REGS.sp[-2].toObject();
     if (!IteratorNext(cx, obj, res))
         goto error;
 }
 END_CASE(JSOP_ITERNEXT)
 
-BEGIN_CASE(JSOP_ENDITER)
+CASE(JSOP_ENDITER)
 {
-    JS_ASSERT(regs.stackDepth() >= 1);
+    JS_ASSERT(REGS.stackDepth() >= 1);
     RootedObject &obj = rootObject0;
-    obj = &regs.sp[-1].toObject();
+    obj = &REGS.sp[-1].toObject();
     bool ok = CloseIterator(cx, obj);
-    regs.sp--;
+    REGS.sp--;
     if (!ok)
         goto error;
 }
 END_CASE(JSOP_ENDITER)
 
-BEGIN_CASE(JSOP_DUP)
+CASE(JSOP_DUP)
 {
-    JS_ASSERT(regs.stackDepth() >= 1);
-    const Value &rref = regs.sp[-1];
+    JS_ASSERT(REGS.stackDepth() >= 1);
+    const Value &rref = REGS.sp[-1];
     PUSH_COPY(rref);
 }
 END_CASE(JSOP_DUP)
 
-BEGIN_CASE(JSOP_DUP2)
+CASE(JSOP_DUP2)
 {
-    JS_ASSERT(regs.stackDepth() >= 2);
-    const Value &lref = regs.sp[-2];
-    const Value &rref = regs.sp[-1];
+    JS_ASSERT(REGS.stackDepth() >= 2);
+    const Value &lref = REGS.sp[-2];
+    const Value &rref = REGS.sp[-1];
     PUSH_COPY(lref);
     PUSH_COPY(rref);
 }
 END_CASE(JSOP_DUP2)
 
-BEGIN_CASE(JSOP_SWAP)
+CASE(JSOP_SWAP)
 {
-    JS_ASSERT(regs.stackDepth() >= 2);
-    Value &lref = regs.sp[-2];
-    Value &rref = regs.sp[-1];
+    JS_ASSERT(REGS.stackDepth() >= 2);
+    Value &lref = REGS.sp[-2];
+    Value &rref = REGS.sp[-1];
     lref.swap(rref);
 }
 END_CASE(JSOP_SWAP)
 
-BEGIN_CASE(JSOP_PICK)
+CASE(JSOP_PICK)
 {
-    unsigned i = GET_UINT8(regs.pc);
-    JS_ASSERT(regs.stackDepth() >= i + 1);
-    Value lval = regs.sp[-int(i + 1)];
-    memmove(regs.sp - (i + 1), regs.sp - i, sizeof(Value) * i);
-    regs.sp[-1] = lval;
+    unsigned i = GET_UINT8(REGS.pc);
+    JS_ASSERT(REGS.stackDepth() >= i + 1);
+    Value lval = REGS.sp[-int(i + 1)];
+    memmove(REGS.sp - (i + 1), REGS.sp - i, sizeof(Value) * i);
+    REGS.sp[-1] = lval;
 }
 END_CASE(JSOP_PICK)
 
-BEGIN_CASE(JSOP_SETCONST)
+CASE(JSOP_SETCONST)
 {
     RootedPropertyName &name = rootName0;
-    name = script->getName(regs.pc);
+    name = script->getName(REGS.pc);
 
     RootedValue &rval = rootValue0;
-    rval = regs.sp[-1];
+    rval = REGS.sp[-1];
 
     RootedObject &obj = rootObject0;
-    obj = &regs.fp()->varObj();
+    obj = &REGS.fp()->varObj();
 
     if (!SetConstOperation(cx, obj, name, rval))
         goto error;
 }
 END_CASE(JSOP_SETCONST);
 
 #if JS_HAS_DESTRUCTURING
-BEGIN_CASE(JSOP_ENUMCONSTELEM)
+CASE(JSOP_ENUMCONSTELEM)
 {
     RootedValue &rval = rootValue0;
-    rval = regs.sp[-3];
+    rval = REGS.sp[-3];
 
     RootedObject &obj = rootObject0;
     FETCH_OBJECT(cx, -2, obj);
     RootedId &id = rootId0;
     FETCH_ELEMENT_ID(-1, id);
     if (!JSObject::defineGeneric(cx, obj, id, rval,
                                  JS_PropertyStub, JS_StrictPropertyStub,
                                  JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
         goto error;
     }
-    regs.sp -= 3;
+    REGS.sp -= 3;
 }
 END_CASE(JSOP_ENUMCONSTELEM)
 #endif
 
-BEGIN_CASE(JSOP_BINDGNAME)
-    PUSH_OBJECT(regs.fp()->global());
+CASE(JSOP_BINDGNAME)
+    PUSH_OBJECT(REGS.fp()->global());
 END_CASE(JSOP_BINDGNAME)
 
-BEGIN_CASE(JSOP_BINDINTRINSIC)
+CASE(JSOP_BINDINTRINSIC)
     PUSH_OBJECT(*cx->global()->intrinsicsHolder());
 END_CASE(JSOP_BINDINTRINSIC)
 
-BEGIN_CASE(JSOP_BINDNAME)
+CASE(JSOP_BINDNAME)
 {
     RootedObject &scopeChain = rootObject0;
-    scopeChain = regs.fp()->scopeChain();
+    scopeChain = REGS.fp()->scopeChain();
 
     RootedPropertyName &name = rootName0;
-    name = script->getName(regs.pc);
+    name = script->getName(REGS.pc);
 
     /* Assigning to an undeclared name adds a property to the global object. */
     RootedObject &scope = rootObject1;
     if (!LookupNameWithGlobalDefault(cx, name, scopeChain, &scope))
         goto error;
 
     PUSH_OBJECT(*scope);
 }
 END_CASE(JSOP_BINDNAME)
 
 #define BITWISE_OP(OP)                                                        \
     JS_BEGIN_MACRO                                                            \
         int32_t i, j;                                                         \
-        if (!ToInt32(cx, regs.stackHandleAt(-2), &i))                         \
+        if (!ToInt32(cx, REGS.stackHandleAt(-2), &i))                         \
             goto error;                                                       \
-        if (!ToInt32(cx, regs.stackHandleAt(-1), &j))                         \
+        if (!ToInt32(cx, REGS.stackHandleAt(-1), &j))                         \
             goto error;                                                       \
         i = i OP j;                                                           \
-        regs.sp--;                                                            \
-        regs.sp[-1].setInt32(i);                                              \
+        REGS.sp--;                                                            \
+        REGS.sp[-1].setInt32(i);                                              \
     JS_END_MACRO
 
-BEGIN_CASE(JSOP_BITOR)
+CASE(JSOP_BITOR)
     BITWISE_OP(|);
 END_CASE(JSOP_BITOR)
 
-BEGIN_CASE(JSOP_BITXOR)
+CASE(JSOP_BITXOR)
     BITWISE_OP(^);
 END_CASE(JSOP_BITXOR)
 
-BEGIN_CASE(JSOP_BITAND)
+CASE(JSOP_BITAND)
     BITWISE_OP(&);
 END_CASE(JSOP_BITAND)
 
 #undef BITWISE_OP
 
-BEGIN_CASE(JSOP_EQ)
-    if (!LooseEqualityOp<true>(cx, regs))
+CASE(JSOP_EQ)
+    if (!LooseEqualityOp<true>(cx, REGS))
         goto error;
 END_CASE(JSOP_EQ)
 
-BEGIN_CASE(JSOP_NE)
-    if (!LooseEqualityOp<false>(cx, regs))
+CASE(JSOP_NE)
+    if (!LooseEqualityOp<false>(cx, REGS))
         goto error;
 END_CASE(JSOP_NE)
 
 #define STRICT_EQUALITY_OP(OP, COND)                                          \
     JS_BEGIN_MACRO                                                            \
-        const Value &rref = regs.sp[-1];                                      \
-        const Value &lref = regs.sp[-2];                                      \
+        const Value &rref = REGS.sp[-1];                                      \
+        const Value &lref = REGS.sp[-2];                                      \
         bool equal;                                                           \
         if (!StrictlyEqual(cx, lref, rref, &equal))                           \
             goto error;                                                       \
         (COND) = equal OP true;                                               \
-        regs.sp--;                                                            \
+        REGS.sp--;                                                            \
     JS_END_MACRO
 
-BEGIN_CASE(JSOP_STRICTEQ)
+CASE(JSOP_STRICTEQ)
 {
     bool cond;
     STRICT_EQUALITY_OP(==, cond);
-    regs.sp[-1].setBoolean(cond);
+    REGS.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_STRICTEQ)
 
-BEGIN_CASE(JSOP_STRICTNE)
+CASE(JSOP_STRICTNE)
 {
     bool cond;
     STRICT_EQUALITY_OP(!=, cond);
-    regs.sp[-1].setBoolean(cond);
+    REGS.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_STRICTNE)
 
-BEGIN_CASE(JSOP_CASE)
+CASE(JSOP_CASE)
 {
     bool cond;
     STRICT_EQUALITY_OP(==, cond);
     if (cond) {
-        regs.sp--;
-        BRANCH(GET_JUMP_OFFSET(regs.pc));
+        REGS.sp--;
+        BRANCH(GET_JUMP_OFFSET(REGS.pc));
     }
 }
 END_CASE(JSOP_CASE)
 
 #undef STRICT_EQUALITY_OP
 
-BEGIN_CASE(JSOP_LT)
+CASE(JSOP_LT)
 {
     bool cond;
-    MutableHandleValue lval = regs.stackHandleAt(-2);
-    MutableHandleValue rval = regs.stackHandleAt(-1);
+    MutableHandleValue lval = REGS.stackHandleAt(-2);
+    MutableHandleValue rval = REGS.stackHandleAt(-1);
     if (!LessThanOperation(cx, lval, rval, &cond))
         goto error;
     TRY_BRANCH_AFTER_COND(cond, 2);
-    regs.sp[-2].setBoolean(cond);
-    regs.sp--;
+    REGS.sp[-2].setBoolean(cond);
+    REGS.sp--;
 }
 END_CASE(JSOP_LT)
 
-BEGIN_CASE(JSOP_LE)
+CASE(JSOP_LE)
 {
     bool cond;
-    MutableHandleValue lval = regs.stackHandleAt(-2);
-    MutableHandleValue rval = regs.stackHandleAt(-1);
+    MutableHandleValue lval = REGS.stackHandleAt(-2);
+    MutableHandleValue rval = REGS.stackHandleAt(-1);
     if (!LessThanOrEqualOperation(cx, lval, rval, &cond))
         goto error;
     TRY_BRANCH_AFTER_COND(cond, 2);
-    regs.sp[-2].setBoolean(cond);
-    regs.sp--;
+    REGS.sp[-2].setBoolean(cond);
+    REGS.sp--;
 }
 END_CASE(JSOP_LE)
 
-BEGIN_CASE(JSOP_GT)
+CASE(JSOP_GT)
 {
     bool cond;
-    MutableHandleValue lval = regs.stackHandleAt(-2);
-    MutableHandleValue rval = regs.stackHandleAt(-1);
+    MutableHandleValue lval = REGS.stackHandleAt(-2);
+    MutableHandleValue rval = REGS.stackHandleAt(-1);
     if (!GreaterThanOperation(cx, lval, rval, &cond))
         goto error;
     TRY_BRANCH_AFTER_COND(cond, 2);
-    regs.sp[-2].setBoolean(cond);
-    regs.sp--;
+    REGS.sp[-2].setBoolean(cond);
+    REGS.sp--;
 }
 END_CASE(JSOP_GT)
 
-BEGIN_CASE(JSOP_GE)
+CASE(JSOP_GE)
 {
     bool cond;
-    MutableHandleValue lval = regs.stackHandleAt(-2);
-    MutableHandleValue rval = regs.stackHandleAt(-1);
+    MutableHandleValue lval = REGS.stackHandleAt(-2);
+    MutableHandleValue rval = REGS.stackHandleAt(-1);
     if (!GreaterThanOrEqualOperation(cx, lval, rval, &cond))
         goto error;
     TRY_BRANCH_AFTER_COND(cond, 2);
-    regs.sp[-2].setBoolean(cond);
-    regs.sp--;
+    REGS.sp[-2].setBoolean(cond);
+    REGS.sp--;
 }
 END_CASE(JSOP_GE)
 
 #define SIGNED_SHIFT_OP(OP)                                                   \
     JS_BEGIN_MACRO                                                            \
         int32_t i, j;                                                         \
-        if (!ToInt32(cx, regs.stackHandleAt(-2), &i))                         \
+        if (!ToInt32(cx, REGS.stackHandleAt(-2), &i))                         \
             goto error;                                                       \
-        if (!ToInt32(cx, regs.stackHandleAt(-1), &j))                         \
+        if (!ToInt32(cx, REGS.stackHandleAt(-1), &j))                         \
             goto error;                                                       \
         i = i OP (j & 31);                                                    \
-        regs.sp--;                                                            \
-        regs.sp[-1].setInt32(i);                                              \
+        REGS.sp--;                                                            \
+        REGS.sp[-1].setInt32(i);                                              \
     JS_END_MACRO
 
-BEGIN_CASE(JSOP_LSH)
+CASE(JSOP_LSH)
     SIGNED_SHIFT_OP(<<);
 END_CASE(JSOP_LSH)
 
-BEGIN_CASE(JSOP_RSH)
+CASE(JSOP_RSH)
     SIGNED_SHIFT_OP(>>);
 END_CASE(JSOP_RSH)
 
 #undef SIGNED_SHIFT_OP
 
-BEGIN_CASE(JSOP_URSH)
+CASE(JSOP_URSH)
 {
-    HandleValue lval = regs.stackHandleAt(-2);
-    HandleValue rval = regs.stackHandleAt(-1);
-    if (!UrshOperation(cx, lval, rval, &regs.sp[-2]))
+    HandleValue lval = REGS.stackHandleAt(-2);
+    HandleValue rval = REGS.stackHandleAt(-1);
+    if (!UrshOperation(cx, lval, rval, &REGS.sp[-2]))
         goto error;
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_URSH)
 
-BEGIN_CASE(JSOP_ADD)
+CASE(JSOP_ADD)
 {
-    MutableHandleValue lval = regs.stackHandleAt(-2);
-    MutableHandleValue rval = regs.stackHandleAt(-1);
-    if (!AddOperation(cx, lval, rval, &regs.sp[-2]))
+    MutableHandleValue lval = REGS.stackHandleAt(-2);
+    MutableHandleValue rval = REGS.stackHandleAt(-1);
+    if (!AddOperation(cx, lval, rval, &REGS.sp[-2]))
         goto error;
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_ADD)
 
-BEGIN_CASE(JSOP_SUB)
+CASE(JSOP_SUB)
 {
     RootedValue &lval = rootValue0, &rval = rootValue1;
-    lval = regs.sp[-2];
-    rval = regs.sp[-1];
-    if (!SubOperation(cx, lval, rval, &regs.sp[-2]))
+    lval = REGS.sp[-2];
+    rval = REGS.sp[-1];
+    if (!SubOperation(cx, lval, rval, &REGS.sp[-2]))
         goto error;
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_SUB)
 
-BEGIN_CASE(JSOP_MUL)
+CASE(JSOP_MUL)
 {
     RootedValue &lval = rootValue0, &rval = rootValue1;
-    lval = regs.sp[-2];
-    rval = regs.sp[-1];
-    if (!MulOperation(cx, lval, rval, &regs.sp[-2]))
+    lval = REGS.sp[-2];
+    rval = REGS.sp[-1];
+    if (!MulOperation(cx, lval, rval, &REGS.sp[-2]))
         goto error;
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_MUL)
 
-BEGIN_CASE(JSOP_DIV)
+CASE(JSOP_DIV)
 {
     RootedValue &lval = rootValue0, &rval = rootValue1;
-    lval = regs.sp[-2];
-    rval = regs.sp[-1];
-    if (!DivOperation(cx, lval, rval, &regs.sp[-2]))
+    lval = REGS.sp[-2];
+    rval = REGS.sp[-1];
+    if (!DivOperation(cx, lval, rval, &REGS.sp[-2]))
         goto error;
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_DIV)
 
-BEGIN_CASE(JSOP_MOD)
+CASE(JSOP_MOD)
 {
     RootedValue &lval = rootValue0, &rval = rootValue1;
-    lval = regs.sp[-2];
-    rval = regs.sp[-1];
-    if (!ModOperation(cx, lval, rval, &regs.sp[-2]))
+    lval = REGS.sp[-2];
+    rval = REGS.sp[-1];
+    if (!ModOperation(cx, lval, rval, &REGS.sp[-2]))
         goto error;
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_MOD)
 
-BEGIN_CASE(JSOP_NOT)
+CASE(JSOP_NOT)
 {
-    bool cond = ToBooleanOp(regs);
-    regs.sp--;
+    bool cond = ToBooleanOp(REGS);
+    REGS.sp--;
     PUSH_BOOLEAN(!cond);
 }
 END_CASE(JSOP_NOT)
 
-BEGIN_CASE(JSOP_BITNOT)
+CASE(JSOP_BITNOT)
 {
     int32_t i;
-    HandleValue value = regs.stackHandleAt(-1);
+    HandleValue value = REGS.stackHandleAt(-1);
     if (!BitNot(cx, value, &i))
         goto error;
-    regs.sp[-1].setInt32(i);
+    REGS.sp[-1].setInt32(i);
 }
 END_CASE(JSOP_BITNOT)
 
-BEGIN_CASE(JSOP_NEG)
+CASE(JSOP_NEG)
 {
     RootedValue &val = rootValue0;
-    val = regs.sp[-1];
-    MutableHandleValue res = regs.stackHandleAt(-1);
-    if (!NegOperation(cx, script, regs.pc, val, res))
+    val = REGS.sp[-1];
+    MutableHandleValue res = REGS.stackHandleAt(-1);
+    if (!NegOperation(cx, script, REGS.pc, val, res))
         goto error;
 }
 END_CASE(JSOP_NEG)
 
-BEGIN_CASE(JSOP_POS)
-    if (!ToNumber(cx, regs.stackHandleAt(-1)))
+CASE(JSOP_POS)
+    if (!ToNumber(cx, REGS.stackHandleAt(-1)))
         goto error;
 END_CASE(JSOP_POS)
 
-BEGIN_CASE(JSOP_DELNAME)
+CASE(JSOP_DELNAME)
 {
     /* Strict mode code should never contain JSOP_DELNAME opcodes. */
     JS_ASSERT(!script->strict);
 
     RootedPropertyName &name = rootName0;
-    name = script->getName(regs.pc);
+    name = script->getName(REGS.pc);
 
     RootedObject &scopeObj = rootObject0;
-    scopeObj = regs.fp()->scopeChain();
+    scopeObj = REGS.fp()->scopeChain();
 
     PUSH_BOOLEAN(true);
-    MutableHandleValue res = regs.stackHandleAt(-1);
+    MutableHandleValue res = REGS.stackHandleAt(-1);
     if (!DeleteNameOperation(cx, name, scopeObj, res))
         goto error;
 }
 END_CASE(JSOP_DELNAME)
 
-BEGIN_CASE(JSOP_DELPROP)
+CASE(JSOP_DELPROP)
 {
     RootedPropertyName &name = rootName0;
-    name = script->getName(regs.pc);
+    name = script->getName(REGS.pc);
 
     RootedObject &obj = rootObject0;
     FETCH_OBJECT(cx, -1, obj);
 
     bool succeeded;
     if (!JSObject::deleteProperty(cx, obj, name, &succeeded))
         goto error;
     if (!succeeded && script->strict) {
         obj->reportNotConfigurable(cx, NameToId(name));
         goto error;
     }
-    MutableHandleValue res = regs.stackHandleAt(-1);
+    MutableHandleValue res = REGS.stackHandleAt(-1);
     res.setBoolean(succeeded);
 }
 END_CASE(JSOP_DELPROP)
 
-BEGIN_CASE(JSOP_DELELEM)
+CASE(JSOP_DELELEM)
 {
     /* Fetch the left part and resolve it to a non-null object. */
     RootedObject &obj = rootObject0;
     FETCH_OBJECT(cx, -2, obj);
 
     RootedValue &propval = rootValue0;
-    propval = regs.sp[-1];
+    propval = REGS.sp[-1];
 
     bool succeeded;
     if (!JSObject::deleteByValue(cx, obj, propval, &succeeded))
         goto error;
     if (!succeeded && script->strict) {
         // XXX This observably calls ToString(propval).  We should convert to
         //     PropertyKey and use that to delete, and to report an error if
         //     necessary!
         RootedId id(cx);
         if (!ValueToId<CanGC>(cx, propval, &id))
             goto error;
         obj->reportNotConfigurable(cx, id);
         goto error;
     }
 
-    MutableHandleValue res = regs.stackHandleAt(-2);
+    MutableHandleValue res = REGS.stackHandleAt(-2);
     res.setBoolean(succeeded);
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_DELELEM)
 
-BEGIN_CASE(JSOP_TOID)
+CASE(JSOP_TOID)
 {
     /*
      * Increment or decrement requires use to lookup the same property twice,
      * but we need to avoid the observable stringification the second time.
      * There must be an object value below the id, which will not be popped.
      */
     RootedValue &objval = rootValue0, &idval = rootValue1;
-    objval = regs.sp[-2];
-    idval = regs.sp[-1];
-
-    MutableHandleValue res = regs.stackHandleAt(-1);
-    if (!ToIdOperation(cx, script, regs.pc, objval, idval, res))
+    objval = REGS.sp[-2];
+    idval = REGS.sp[-1];
+
+    MutableHandleValue res = REGS.stackHandleAt(-1);
+    if (!ToIdOperation(cx, script, REGS.pc, objval, idval, res))
         goto error;
 }
 END_CASE(JSOP_TOID)
 
-BEGIN_CASE(JSOP_TYPEOFEXPR)
-BEGIN_CASE(JSOP_TYPEOF)
+CASE(JSOP_TYPEOFEXPR)
+CASE(JSOP_TYPEOF)
 {
-    regs.sp[-1].setString(TypeOfOperation(regs.sp[-1], rt));
+    REGS.sp[-1].setString(TypeOfOperation(REGS.sp[-1], cx->runtime()));
 }
 END_CASE(JSOP_TYPEOF)
 
-BEGIN_CASE(JSOP_VOID)
-    regs.sp[-1].setUndefined();
+CASE(JSOP_VOID)
+    REGS.sp[-1].setUndefined();
 END_CASE(JSOP_VOID)
 
-BEGIN_CASE(JSOP_THIS)
-    if (!ComputeThis(cx, regs.fp()))
+CASE(JSOP_THIS)
+    if (!ComputeThis(cx, REGS.fp()))
         goto error;
-    PUSH_COPY(regs.fp()->thisValue());
+    PUSH_COPY(REGS.fp()->thisValue());
 END_CASE(JSOP_THIS)
 
-BEGIN_CASE(JSOP_GETPROP)
-BEGIN_CASE(JSOP_GETXPROP)
-BEGIN_CASE(JSOP_LENGTH)
-BEGIN_CASE(JSOP_CALLPROP)
+CASE(JSOP_GETPROP)
+CASE(JSOP_GETXPROP)
+CASE(JSOP_LENGTH)
+CASE(JSOP_CALLPROP)
 {
 
-    MutableHandleValue lval = regs.stackHandleAt(-1);
-    if (!GetPropertyOperation(cx, regs.fp(), script, regs.pc, lval, lval))
+    MutableHandleValue lval = REGS.stackHandleAt(-1);
+    if (!GetPropertyOperation(cx, REGS.fp(), script, REGS.pc, lval, lval))
         goto error;
 
-    TypeScript::Monitor(cx, script, regs.pc, lval);
+    TypeScript::Monitor(cx, script, REGS.pc, lval);
     assertSameCompartmentDebugOnly(cx, lval);
 }
 END_CASE(JSOP_GETPROP)
 
-BEGIN_CASE(JSOP_SETINTRINSIC)
+CASE(JSOP_SETINTRINSIC)
 {
-    HandleValue value = regs.stackHandleAt(-1);
-
-    if (!SetIntrinsicOperation(cx, script, regs.pc, value))
+    HandleValue value = REGS.stackHandleAt(-1);
+
+    if (!SetIntrinsicOperation(cx, script, REGS.pc, value))
         goto error;
 
-    regs.sp[-2] = regs.sp[-1];
-    regs.sp--;
+    REGS.sp[-2] = REGS.sp[-1];
+    REGS.sp--;
 }
 END_CASE(JSOP_SETINTRINSIC)
 
-BEGIN_CASE(JSOP_SETGNAME)
-BEGIN_CASE(JSOP_SETNAME)
+CASE(JSOP_SETGNAME)
+CASE(JSOP_SETNAME)
 {
     RootedObject &scope = rootObject0;
-    scope = &regs.sp[-2].toObject();
-
-    HandleValue value = regs.stackHandleAt(-1);
-
-    if (!SetNameOperation(cx, script, regs.pc, scope, value))
+    scope = &REGS.sp[-2].toObject();
+
+    HandleValue value = REGS.stackHandleAt(-1);
+
+    if (!SetNameOperation(cx, script, REGS.pc, scope, value))
         goto error;
 
-    regs.sp[-2] = regs.sp[-1];
-    regs.sp--;
+    REGS.sp[-2] = REGS.sp[-1];
+    REGS.sp--;
 }
 END_CASE(JSOP_SETNAME)
 
-BEGIN_CASE(JSOP_SETPROP)
+CASE(JSOP_SETPROP)
 {
-    HandleValue lval = regs.stackHandleAt(-2);
-    HandleValue rval = regs.stackHandleAt(-1);
-
-    if (!SetPropertyOperation(cx, script, regs.pc, lval, rval))
+    HandleValue lval = REGS.stackHandleAt(-2);
+    HandleValue rval = REGS.stackHandleAt(-1);
+
+    if (!SetPropertyOperation(cx, script, REGS.pc, lval, rval))
         goto error;
 
-    regs.sp[-2] = regs.sp[-1];
-    regs.sp--;
+    REGS.sp[-2] = REGS.sp[-1];
+    REGS.sp--;
 }
 END_CASE(JSOP_SETPROP)
 
-BEGIN_CASE(JSOP_GETELEM)
-BEGIN_CASE(JSOP_CALLELEM)
+CASE(JSOP_GETELEM)
+CASE(JSOP_CALLELEM)
 {
-    MutableHandleValue lval = regs.stackHandleAt(-2);
-    HandleValue rval = regs.stackHandleAt(-1);
-    MutableHandleValue res = regs.stackHandleAt(-2);
+    MutableHandleValue lval = REGS.stackHandleAt(-2);
+    HandleValue rval = REGS.stackHandleAt(-1);
+    MutableHandleValue res = REGS.stackHandleAt(-2);
 
     bool done = false;
-    if (!GetElemOptimizedArguments(cx, regs.fp(), lval, rval, res, &done))
+    if (!GetElemOptimizedArguments(cx, REGS.fp(), lval, rval, res, &done))
         goto error;
 
     if (!done) {
-        if (!GetElementOperation(cx, op, lval, rval, res))
+        if (!GetElementOperation(cx, JSOp(*REGS.pc), lval, rval, res))
             goto error;
     }
 
-    TypeScript::Monitor(cx, script, regs.pc, res);
-    regs.sp--;
+    TypeScript::Monitor(cx, script, REGS.pc, res);
+    REGS.sp--;
 }
 END_CASE(JSOP_GETELEM)
 
-BEGIN_CASE(JSOP_SETELEM)
+CASE(JSOP_SETELEM)
 {
     RootedObject &obj = rootObject0;
     FETCH_OBJECT(cx, -3, obj);
     RootedId &id = rootId0;
     FETCH_ELEMENT_ID(-2, id);
-    Value &value = regs.sp[-1];
+    Value &value = REGS.sp[-1];
     if (!SetObjectElementOperation(cx, obj, id, value, script->strict))
         goto error;
-    regs.sp[-3] = value;
-    regs.sp -= 2;
+    REGS.sp[-3] = value;
+    REGS.sp -= 2;
 }
 END_CASE(JSOP_SETELEM)
 
-BEGIN_CASE(JSOP_ENUMELEM)
+CASE(JSOP_ENUMELEM)
 {
     RootedObject &obj = rootObject0;
     RootedValue &rval = rootValue0;
 
     /* Funky: the value to set is under the [obj, id] pair. */
     FETCH_OBJECT(cx, -2, obj);
     RootedId &id = rootId0;
     FETCH_ELEMENT_ID(-1, id);
-    rval = regs.sp[-3];
+    rval = REGS.sp[-3];
     if (!JSObject::setGeneric(cx, obj, obj, id, &rval, script->strict))
         goto error;
-    regs.sp -= 3;
+    REGS.sp -= 3;
 }
 END_CASE(JSOP_ENUMELEM)
 
-BEGIN_CASE(JSOP_EVAL)
+CASE(JSOP_EVAL)
 {
-    CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
-    if (IsBuiltinEvalForScope(regs.fp()->scopeChain(), args.calleev())) {
+    CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);
+    if (IsBuiltinEvalForScope(REGS.fp()->scopeChain(), args.calleev())) {
         if (!DirectEval(cx, args))
             goto error;
     } else {
         if (!Invoke(cx, args))
             goto error;
     }
-    regs.sp = args.spAfterCall();
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
+    REGS.sp = args.spAfterCall();
+    TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
 }
 END_CASE(JSOP_EVAL)
 
-BEGIN_CASE(JSOP_SPREADNEW)
-BEGIN_CASE(JSOP_SPREADCALL)
-    if (regs.fp()->hasPushedSPSFrame())
-        cx->runtime()->spsProfiler.updatePC(script, regs.pc);
+CASE(JSOP_SPREADNEW)
+CASE(JSOP_SPREADCALL)
+    if (REGS.fp()->hasPushedSPSFrame())
+        cx->runtime()->spsProfiler.updatePC(script, REGS.pc);
     /* FALL THROUGH */
 
-BEGIN_CASE(JSOP_SPREADEVAL)
+CASE(JSOP_SPREADEVAL)
 {
-    JS_ASSERT(regs.stackDepth() >= 3);
+    JS_ASSERT(REGS.stackDepth() >= 3);
     RootedObject &aobj = rootObject0;
-    aobj = &regs.sp[-1].toObject();
+    aobj = &REGS.sp[-1].toObject();
 
     uint32_t length = aobj->as<ArrayObject>().length();
 
     if (length > ARGS_LENGTH_MAX) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
-                             op == JSOP_SPREADNEW ? JSMSG_TOO_MANY_CON_SPREADARGS
-                                                  : JSMSG_TOO_MANY_FUN_SPREADARGS);
+                             *REGS.pc == JSOP_SPREADNEW ? JSMSG_TOO_MANY_CON_SPREADARGS
+                                                        : JSMSG_TOO_MANY_FUN_SPREADARGS);
         goto error;
     }
 
     InvokeArgs args(cx);
 
     if (!args.init(length))
         return false;
 
-    args.setCallee(regs.sp[-3]);
-    args.setThis(regs.sp[-2]);
+    args.setCallee(REGS.sp[-3]);
+    args.setThis(REGS.sp[-2]);
 
     if (!GetElements(cx, aobj, length, args.array()))
         goto error;
 
-    if (op == JSOP_SPREADNEW) {
+    switch (*REGS.pc) {
+      case JSOP_SPREADNEW:
         if (!InvokeConstructor(cx, args))
             goto error;
-    } else if (op == JSOP_SPREADCALL) {
+        break;
+      case JSOP_SPREADCALL:
         if (!Invoke(cx, args))
             goto error;
-    } else {
-        JS_ASSERT(op == JSOP_SPREADEVAL);
-        if (IsBuiltinEvalForScope(regs.fp()->scopeChain(), args.calleev())) {
+        break;
+      case JSOP_SPREADEVAL:
+        if (IsBuiltinEvalForScope(REGS.fp()->scopeChain(), args.calleev())) {
             if (!DirectEval(cx, args))
                 goto error;
         } else {
             if (!Invoke(cx, args))
                 goto error;
         }
+        break;
+      default:
+        MOZ_ASSUME_UNREACHABLE("bad spread opcode");
     }
 
-    regs.sp -= 2;
-    regs.sp[-1] = args.rval();
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
+    REGS.sp -= 2;
+    REGS.sp[-1] = args.rval();
+    TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
 }
 END_CASE(JSOP_SPREADCALL)
 
-BEGIN_CASE(JSOP_FUNAPPLY)
+CASE(JSOP_FUNAPPLY)
 {
-    CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
-    if (!GuardFunApplyArgumentsOptimization(cx, regs.fp(), args.calleev(), args.array(),
+    CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);
+    if (!GuardFunApplyArgumentsOptimization(cx, REGS.fp(), args.calleev(), args.array(),
                                             args.length()))
         goto error;
     /* FALL THROUGH */
 }
 
-BEGIN_CASE(JSOP_NEW)
-BEGIN_CASE(JSOP_CALL)
-BEGIN_CASE(JSOP_FUNCALL)
+CASE(JSOP_NEW)
+CASE(JSOP_CALL)
+CASE(JSOP_FUNCALL)
 {
-    if (regs.fp()->hasPushedSPSFrame())
-        cx->runtime()->spsProfiler.updatePC(script, regs.pc);
-    JS_ASSERT(regs.stackDepth() >= 2 + GET_ARGC(regs.pc));
-    CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
-
-    bool construct = (*regs.pc == JSOP_NEW);
+    if (REGS.fp()->hasPushedSPSFrame())
+        cx->runtime()->spsProfiler.updatePC(script, REGS.pc);
+    JS_ASSERT(REGS.stackDepth() >= 2 + GET_ARGC(REGS.pc));
+    CallArgs args = CallArgsFromSp(GET_ARGC(REGS.pc), REGS.sp);
+
+    bool construct = (*REGS.pc == JSOP_NEW);
 
     RootedFunction &fun = rootFunction0;
     RootedScript &funScript = rootScript0;
     bool isFunction = IsFunctionObject(args.calleev(), fun.address());
 
     /*
      * Some builtins are marked as clone-at-callsite to increase precision of
      * TI and JITs.
      */
     if (isFunction && fun->isInterpreted()) {
         funScript = fun->getOrCreateScript(cx);
         if (!funScript)
             goto error;
         if (cx->typeInferenceEnabled() && funScript->shouldCloneAtCallsite) {
-            fun = CloneFunctionAtCallsite(cx, fun, script, regs.pc);
+            fun = CloneFunctionAtCallsite(cx, fun, script, REGS.pc);
             if (!fun)
                 goto error;
             args.setCallee(ObjectValue(*fun));
         }
     }
 
     /* Don't bother trying to fast-path calls to scripted non-constructors. */
     if (!isFunction || !fun->isInterpretedConstructor()) {
         if (construct) {
             if (!InvokeConstructor(cx, args))
                 goto error;
         } else {
             if (!Invoke(cx, args))
                 goto error;
         }
         Value *newsp = args.spAfterCall();
-        TypeScript::Monitor(cx, script, regs.pc, newsp[-1]);
-        regs.sp = newsp;
-        len = JSOP_CALL_LENGTH;
-        goto advanceAndDoOp;
+        TypeScript::Monitor(cx, script, REGS.pc, newsp[-1]);
+        REGS.sp = newsp;
+        ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);
     }
 
     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
-    bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
+    bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, REGS.pc);
 
     TypeMonitorCall(cx, args, construct);
 
 #ifdef JS_ION
     {
         InvokeState state(cx, args, initial);
         if (newType)
             state.setUseNewType();
 
         if (!newType && jit::IsIonEnabled(cx)) {
             jit::MethodStatus status = jit::CanEnter(cx, state);
             if (status == jit::Method_Error)
                 goto error;
             if (status == jit::Method_Compiled) {
                 jit::IonExecStatus exec = jit::IonCannon(cx, state);
                 CHECK_BRANCH();
-                regs.sp = args.spAfterCall();
+                REGS.sp = args.spAfterCall();
                 interpReturnOK = !IsErrorStatus(exec);
                 goto jit_return;
             }
         }
 
         if (jit::IsBaselineEnabled(cx)) {
             jit::MethodStatus status = jit::CanEnterBaselineMethod(cx, state);
             if (status == jit::Method_Error)
                 goto error;
             if (status == jit::Method_Compiled) {
                 jit::IonExecStatus exec = jit::EnterBaselineMethod(cx, state);
                 CHECK_BRANCH();
-                regs.sp = args.spAfterCall();
+                REGS.sp = args.spAfterCall();
                 interpReturnOK = !IsErrorStatus(exec);
                 goto jit_return;
             }
         }
     }
 #endif
 
     funScript = fun->nonLazyScript();
     if (!activation.pushInlineFrame(args, funScript, initial))
         goto error;
 
     if (newType)
-        regs.fp()->setUseNewType();
-
-    SET_SCRIPT(regs.fp()->script());
+        REGS.fp()->setUseNewType();
+
+    SET_SCRIPT(REGS.fp()->script());
 
 #if JS_TRACE_LOGGING
     TraceLogging::defaultLogger()->log(TraceLogging::SCRIPT_START, script);
     TraceLogging::defaultLogger()->log(TraceLogging::INFO_ENGINE_INTERPRETER);
 #endif
 
-    if (!regs.fp()->prologue(cx))
+    if (!REGS.fp()->prologue(cx))
         goto error;
     if (cx->compartment()->debugMode()) {
-        switch (ScriptDebugPrologue(cx, regs.fp())) {
+        switch (ScriptDebugPrologue(cx, REGS.fp())) {
           case JSTRAP_CONTINUE:
             break;
           case JSTRAP_RETURN:
             interpReturnOK = true;
             goto forced_return;
           case JSTRAP_THROW:
           case JSTRAP_ERROR:
             goto error;
           default:
             MOZ_ASSUME_UNREACHABLE("bad ScriptDebugPrologue status");
         }
     }
 
     /* Load first op and dispatch it (safe since JSOP_STOP). */
-    op = (JSOp) *regs.pc;
-    DO_OP();
+    ADVANCE_AND_DISPATCH(0);
 }
 
-BEGIN_CASE(JSOP_SETCALL)
+CASE(JSOP_SETCALL)
 {
     JS_ALWAYS_FALSE(SetCallOperation(cx));
     goto error;
 }
 END_CASE(JSOP_SETCALL)
 
-BEGIN_CASE(JSOP_IMPLICITTHIS)
+CASE(JSOP_IMPLICITTHIS)
 {
     RootedPropertyName &name = rootName0;
-    name = script->getName(regs.pc);
+    name = script->getName(REGS.pc);
 
     RootedObject &scopeObj = rootObject0;
-    scopeObj = regs.fp()->scopeChain();
+    scopeObj = REGS.fp()->scopeChain();
 
     RootedObject &scope = rootObject1;
     if (!LookupNameWithGlobalDefault(cx, name, scopeObj, &scope))
         goto error;
 
     RootedValue &v = rootValue0;
     if (!ComputeImplicitThis(cx, scope, &v))
         goto error;
     PUSH_COPY(v);
 }
 END_CASE(JSOP_IMPLICITTHIS)
 
-BEGIN_CASE(JSOP_GETGNAME)
-BEGIN_CASE(JSOP_CALLGNAME)
-BEGIN_CASE(JSOP_NAME)
-BEGIN_CASE(JSOP_CALLNAME)
+CASE(JSOP_GETGNAME)
+CASE(JSOP_CALLGNAME)
+CASE(JSOP_NAME)
+CASE(JSOP_CALLNAME)
 {
     RootedValue &rval = rootValue0;
 
-    if (!NameOperation(cx, regs.fp(), regs.pc, &rval))
+    if (!NameOperation(cx, REGS.fp(), REGS.pc, &rval))
         goto error;
 
     PUSH_COPY(rval);
-    TypeScript::Monitor(cx, script, regs.pc, rval);
+    TypeScript::Monitor(cx, script, REGS.pc, rval);
 }
 END_CASE(JSOP_NAME)
 
-BEGIN_CASE(JSOP_GETINTRINSIC)
-BEGIN_CASE(JSOP_CALLINTRINSIC)
+CASE(JSOP_GETINTRINSIC)
+CASE(JSOP_CALLINTRINSIC)
 {
     RootedValue &rval = rootValue0;
 
-    if (!GetIntrinsicOperation(cx, regs.pc, &rval))
+    if (!GetIntrinsicOperation(cx, REGS.pc, &rval))
         goto error;
 
     PUSH_COPY(rval);
-    TypeScript::Monitor(cx, script, regs.pc, rval);
+    TypeScript::Monitor(cx, script, REGS.pc, rval);
 }
 END_CASE(JSOP_GETINTRINSIC)
 
-BEGIN_CASE(JSOP_UINT16)
-    PUSH_INT32((int32_t) GET_UINT16(regs.pc));
+CASE(JSOP_UINT16)
+    PUSH_INT32((int32_t) GET_UINT16(REGS.pc));
 END_CASE(JSOP_UINT16)
 
-BEGIN_CASE(JSOP_UINT24)
-    PUSH_INT32((int32_t) GET_UINT24(regs.pc));
+CASE(JSOP_UINT24)
+    PUSH_INT32((int32_t) GET_UINT24(REGS.pc));
 END_CASE(JSOP_UINT24)
 
-BEGIN_CASE(JSOP_INT8)
-    PUSH_INT32(GET_INT8(regs.pc));
+CASE(JSOP_INT8)
+    PUSH_INT32(GET_INT8(REGS.pc));
 END_CASE(JSOP_INT8)
 
-BEGIN_CASE(JSOP_INT32)
-    PUSH_INT32(GET_INT32(regs.pc));
+CASE(JSOP_INT32)
+    PUSH_INT32(GET_INT32(REGS.pc));
 END_CASE(JSOP_INT32)
 
-BEGIN_CASE(JSOP_DOUBLE)
+CASE(JSOP_DOUBLE)
 {
     double dbl;
     LOAD_DOUBLE(0, dbl);
     PUSH_DOUBLE(dbl);
 }
 END_CASE(JSOP_DOUBLE)
 
-BEGIN_CASE(JSOP_STRING)
-    PUSH_STRING(script->getAtom(regs.pc));
+CASE(JSOP_STRING)
+    PUSH_STRING(script->getAtom(REGS.pc));
 END_CASE(JSOP_STRING)
 
-BEGIN_CASE(JSOP_OBJECT)
-    PUSH_OBJECT(*script->getObject(regs.pc));
+CASE(JSOP_OBJECT)
+    PUSH_OBJECT(*script->getObject(REGS.pc));
 END_CASE(JSOP_OBJECT)
 
-BEGIN_CASE(JSOP_REGEXP)
+CASE(JSOP_REGEXP)
 {
     /*
      * Push a regexp object cloned from the regexp literal object mapped by the
      * bytecode at pc.
      */
-    uint32_t index = GET_UINT32_INDEX(regs.pc);
-    JSObject *proto = regs.fp()->global().getOrCreateRegExpPrototype(cx);
+    uint32_t index = GET_UINT32_INDEX(REGS.pc);
+    JSObject *proto = REGS.fp()->global().getOrCreateRegExpPrototype(cx);
     if (!proto)
         goto error;
     JSObject *obj = CloneRegExpObject(cx, script->getRegExp(index), proto);
     if (!obj)
         goto error;
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_REGEXP)
 
-BEGIN_CASE(JSOP_ZERO)
+CASE(JSOP_ZERO)
     PUSH_INT32(0);
 END_CASE(JSOP_ZERO)
 
-BEGIN_CASE(JSOP_ONE)
+CASE(JSOP_ONE)
     PUSH_INT32(1);
 END_CASE(JSOP_ONE)
 
-BEGIN_CASE(JSOP_NULL)
+CASE(JSOP_NULL)
     PUSH_NULL();
 END_CASE(JSOP_NULL)
 
-BEGIN_CASE(JSOP_FALSE)
+CASE(JSOP_FALSE)
     PUSH_BOOLEAN(false);
 END_CASE(JSOP_FALSE)
 
-BEGIN_CASE(JSOP_TRUE)
+CASE(JSOP_TRUE)
     PUSH_BOOLEAN(true);
 END_CASE(JSOP_TRUE)
 
-{
-BEGIN_CASE(JSOP_TABLESWITCH)
+CASE(JSOP_TABLESWITCH)
 {
-    jsbytecode *pc2 = regs.pc;
-    len = GET_JUMP_OFFSET(pc2);
+    jsbytecode *pc2 = REGS.pc;
+    int32_t len = GET_JUMP_OFFSET(pc2);
 
     /*
      * ECMAv2+ forbids conversion of discriminant, so we will skip to the
      * default case if the discriminant isn't already an int jsval.  (This
      * opcode is emitted only for dense int-domain switches.)
      */
-    const Value &rref = *--regs.sp;
+    const Value &rref = *--REGS.sp;
     int32_t i;
     if (rref.isInt32()) {
         i = rref.toInt32();
     } else {
         double d;
         /* Don't use mozilla::DoubleIsInt32; treat -0 (double) as 0. */
         if (!rref.isDouble() || (d = rref.toDouble()) != (i = int32_t(rref.toDouble())))
-            goto advanceAndDoOp;
+            ADVANCE_AND_DISPATCH(len);
     }
 
     pc2 += JUMP_OFFSET_LEN;
     int32_t low = GET_JUMP_OFFSET(pc2);
     pc2 += JUMP_OFFSET_LEN;
     int32_t high = GET_JUMP_OFFSET(pc2);
 
     i -= low;
     if ((uint32_t)i < (uint32_t)(high - low + 1)) {
         pc2 += JUMP_OFFSET_LEN + JUMP_OFFSET_LEN * i;
         int32_t off = (int32_t) GET_JUMP_OFFSET(pc2);
         if (off)
             len = off;
     }
-}
-END_VARLEN_CASE
+    ADVANCE_AND_DISPATCH(len);
 }
 
-BEGIN_CASE(JSOP_ARGUMENTS)
-    JS_ASSERT(!regs.fp()->fun()->hasRest());
+CASE(JSOP_ARGUMENTS)
+    JS_ASSERT(!REGS.fp()->fun()->hasRest());
     if (!script->analyzedArgsUsage() && !script->ensureRanAnalysis(cx))
         goto error;
     if (script->needsArgsObj()) {
-        ArgumentsObject *obj = ArgumentsObject::createExpected(cx, regs.fp());
+        ArgumentsObject *obj = ArgumentsObject::createExpected(cx, REGS.fp());
         if (!obj)
             goto error;
         PUSH_COPY(ObjectValue(*obj));
     } else {
         PUSH_COPY(MagicValue(JS_OPTIMIZED_ARGUMENTS));
     }
 END_CASE(JSOP_ARGUMENTS)
 
-BEGIN_CASE(JSOP_RUNONCE)
+CASE(JSOP_RUNONCE)
 {
     if (!RunOnceScriptPrologue(cx, script))
         goto error;
 }
 END_CASE(JSOP_RUNONCE)
 
-BEGIN_CASE(JSOP_REST)
+CASE(JSOP_REST)
 {
     RootedObject &rest = rootObject0;
-    rest = regs.fp()->createRestParameter(cx);
+    rest = REGS.fp()->createRestParameter(cx);
     if (!rest)
         goto error;
     PUSH_COPY(ObjectValue(*rest));
 }
 END_CASE(JSOP_REST)
 
-BEGIN_CASE(JSOP_CALLALIASEDVAR)
-BEGIN_CASE(JSOP_GETALIASEDVAR)
+CASE(JSOP_CALLALIASEDVAR)
+CASE(JSOP_GETALIASEDVAR)
 {
-    ScopeCoordinate sc = ScopeCoordinate(regs.pc);
-    PUSH_COPY(regs.fp()->aliasedVarScope(sc).aliasedVar(sc));
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
+    ScopeCoordinate sc = ScopeCoordinate(REGS.pc);
+    PUSH_COPY(REGS.fp()->aliasedVarScope(sc).aliasedVar(sc));
+    TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
 }
 END_CASE(JSOP_GETALIASEDVAR)
 
-BEGIN_CASE(JSOP_SETALIASEDVAR)
+CASE(JSOP_SETALIASEDVAR)
 {
-    ScopeCoordinate sc = ScopeCoordinate(regs.pc);
-    ScopeObject &obj = regs.fp()->aliasedVarScope(sc);
+    ScopeCoordinate sc = ScopeCoordinate(REGS.pc);
+    ScopeObject &obj = REGS.fp()->aliasedVarScope(sc);
 
     // Avoid computing the name if no type updates are needed, as this may be
     // expensive on scopes with large numbers of variables.
-    PropertyName *name = obj.hasSingletonType() ? ScopeCoordinateName(cx, script, regs.pc)
+    PropertyName *name = obj.hasSingletonType() ? ScopeCoordinateName(cx, script, REGS.pc)
                                                 : nullptr;
 
-    obj.setAliasedVar(cx, sc, name, regs.sp[-1]);
+    obj.setAliasedVar(cx, sc, name, REGS.sp[-1]);
 }
 END_CASE(JSOP_SETALIASEDVAR)
 
-BEGIN_CASE(JSOP_GETARG)
-BEGIN_CASE(JSOP_CALLARG)
+CASE(JSOP_GETARG)
+CASE(JSOP_CALLARG)
 {
-    unsigned i = GET_ARGNO(regs.pc);
+    unsigned i = GET_ARGNO(REGS.pc);
     if (script->argsObjAliasesFormals())
-        PUSH_COPY(regs.fp()->argsObj().arg(i));
+        PUSH_COPY(REGS.fp()->argsObj().arg(i));
     else
-        PUSH_COPY(regs.fp()->unaliasedFormal(i));
+        PUSH_COPY(REGS.fp()->unaliasedFormal(i));
 }
 END_CASE(JSOP_GETARG)
 
-BEGIN_CASE(JSOP_SETARG)
+CASE(JSOP_SETARG)
 {
-    unsigned i = GET_ARGNO(regs.pc);
+    unsigned i = GET_ARGNO(REGS.pc);
     if (script->argsObjAliasesFormals())
-        regs.fp()->argsObj().setArg(i, regs.sp[-1]);
+        REGS.fp()->argsObj().setArg(i, REGS.sp[-1]);
     else
-        regs.fp()->unaliasedFormal(i) = regs.sp[-1];
+        REGS.fp()->unaliasedFormal(i) = REGS.sp[-1];
 }
 END_CASE(JSOP_SETARG)
 
-BEGIN_CASE(JSOP_GETLOCAL)
-BEGIN_CASE(JSOP_CALLLOCAL)
+CASE(JSOP_GETLOCAL)
+CASE(JSOP_CALLLOCAL)
 {
-    unsigned i = GET_SLOTNO(regs.pc);
-    PUSH_COPY_SKIP_CHECK(regs.fp()->unaliasedLocal(i));
+    unsigned i = GET_SLOTNO(REGS.pc);
+    PUSH_COPY_SKIP_CHECK(REGS.fp()->unaliasedLocal(i));
 
     /*
      * Skip the same-compartment assertion if the local will be immediately
      * popped. We do not guarantee sync for dead locals when coming in from the
      * method JIT, and a GETLOCAL followed by POP is not considered to be
      * a use of the variable.
      */
-    if (regs.pc[JSOP_GETLOCAL_LENGTH] != JSOP_POP)
-        assertSameCompartmentDebugOnly(cx, regs.sp[-1]);
+    if (REGS.pc[JSOP_GETLOCAL_LENGTH] != JSOP_POP)
+        assertSameCompartmentDebugOnly(cx, REGS.sp[-1]);
 }
 END_CASE(JSOP_GETLOCAL)
 
-BEGIN_CASE(JSOP_SETLOCAL)
+CASE(JSOP_SETLOCAL)
 {
-    unsigned i = GET_SLOTNO(regs.pc);
-    regs.fp()->unaliasedLocal(i) = regs.sp[-1];
+    unsigned i = GET_SLOTNO(REGS.pc);
+    REGS.fp()->unaliasedLocal(i) = REGS.sp[-1];
 }
 END_CASE(JSOP_SETLOCAL)
 
-BEGIN_CASE(JSOP_DEFCONST)
-BEGIN_CASE(JSOP_DEFVAR)
+CASE(JSOP_DEFCONST)
+CASE(JSOP_DEFVAR)
 {
     /* ES5 10.5 step 8 (with subsequent errata). */
     unsigned attrs = JSPROP_ENUMERATE;
-    if (!regs.fp()->isEvalFrame())
+    if (!REGS.fp()->isEvalFrame())
         attrs |= JSPROP_PERMANENT;
-    if (op == JSOP_DEFCONST)
+    if (*REGS.pc == JSOP_DEFCONST)
         attrs |= JSPROP_READONLY;
 
     /* Step 8b. */
     RootedObject &obj = rootObject0;
-    obj = &regs.fp()->varObj();
+    obj = &REGS.fp()->varObj();
 
     RootedPropertyName &name = rootName0;
-    name = script->getName(regs.pc);
+    name = script->getName(REGS.pc);
 
     if (!DefVarOrConstOperation(cx, obj, name, attrs))
         goto error;
 }
 END_CASE(JSOP_DEFVAR)
 
-BEGIN_CASE(JSOP_DEFFUN)
+CASE(JSOP_DEFFUN)
 {
     /*
      * A top-level function defined in Global or Eval code (see ECMA-262
      * Ed. 3), or else a SpiderMonkey extension: a named function statement in
      * a compound statement (not at the top statement level of global code, or
      * at the top level of a function body).
      */
     RootedFunction &fun = rootFunction0;
-    fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
-
-    if (!DefFunOperation(cx, script, regs.fp()->scopeChain(), fun))
+    fun = script->getFunction(GET_UINT32_INDEX(REGS.pc));
+
+    if (!DefFunOperation(cx, script, REGS.fp()->scopeChain(), fun))
         goto error;
 }
 END_CASE(JSOP_DEFFUN)
 
-BEGIN_CASE(JSOP_LAMBDA)
+CASE(JSOP_LAMBDA)
 {
     /* Load the specified function object literal. */
     RootedFunction &fun = rootFunction0;
-    fun = script->getFunction(GET_UINT32_INDEX(regs.pc));
-
-    JSObject *obj = Lambda(cx, fun, regs.fp()->scopeChain());
+    fun = script->getFunction(GET_UINT32_INDEX(REGS.pc));
+
+    JSObject *obj = Lambda(cx, fun, REGS.fp()->scopeChain());
     if (!obj)
         goto error;
     JS_ASSERT(obj->getProto());
     PUSH_OBJECT(*obj);
 }
 END_CASE(JSOP_LAMBDA)
 
-BEGIN_CASE(JSOP_CALLEE)
-    JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
-    PUSH_COPY(regs.fp()->calleev());
+CASE(JSOP_CALLEE)
+    JS_ASSERT(REGS.fp()->isNonEvalFunctionFrame());
+    PUSH_COPY(REGS.fp()->calleev());
 END_CASE(JSOP_CALLEE)
 
-BEGIN_CASE(JSOP_INITPROP_GETTER)
-BEGIN_CASE(JSOP_INITPROP_SETTER)
+CASE(JSOP_INITPROP_GETTER)
+CASE(JSOP_INITPROP_SETTER)
 {
     RootedObject &obj = rootObject0;
     RootedPropertyName &name = rootName0;
     RootedObject &val = rootObject1;
 
-    JS_ASSERT(regs.stackDepth() >= 2);
-    obj = &regs.sp[-2].toObject();
-    name = script->getName(regs.pc);
-    val = &regs.sp[-1].toObject();
-
-    if (!InitGetterSetterOperation(cx, regs.pc, obj, name, val))
+    JS_ASSERT(REGS.stackDepth() >= 2);
+    obj = &REGS.sp[-2].toObject();
+    name = script->getName(REGS.pc);
+    val = &REGS.sp[-1].toObject();
+
+    if (!InitGetterSetterOperation(cx, REGS.pc, obj, name, val))
         goto error;
 
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_INITPROP_GETTER)
 
-BEGIN_CASE(JSOP_INITELEM_GETTER)
-BEGIN_CASE(JSOP_INITELEM_SETTER)
+CASE(JSOP_INITELEM_GETTER)
+CASE(JSOP_INITELEM_SETTER)
 {
     RootedObject &obj = rootObject0;
     RootedValue &idval = rootValue0;
     RootedObject &val = rootObject1;
 
-    JS_ASSERT(regs.stackDepth() >= 3);
-    obj = &regs.sp[-3].toObject();
-    idval = regs.sp[-2];
-    val = &regs.sp[-1].toObject();
-
-    if (!InitGetterSetterOperation(cx, regs.pc, obj, idval, val))
+    JS_ASSERT(REGS.stackDepth() >= 3);
+    obj = &REGS.sp[-3].toObject();
+    idval = REGS.sp[-2];
+    val = &REGS.sp[-1].toObject();
+
+    if (!InitGetterSetterOperation(cx, REGS.pc, obj, idval, val))
         goto error;
 
-    regs.sp -= 2;
+    REGS.sp -= 2;
 }
 END_CASE(JSOP_INITELEM_GETTER)
 
-BEGIN_CASE(JSOP_HOLE)
+CASE(JSOP_HOLE)
     PUSH_HOLE();
 END_CASE(JSOP_HOLE)
 
-BEGIN_CASE(JSOP_NEWINIT)
+CASE(JSOP_NEWINIT)
 {
-    uint8_t i = GET_UINT8(regs.pc);
+    uint8_t i = GET_UINT8(REGS.pc);
     JS_ASSERT(i == JSProto_Array || i == JSProto_Object);
 
     RootedObject &obj = rootObject0;
     NewObjectKind newKind;
     if (i == JSProto_Array) {
-        newKind = UseNewTypeForInitializer(script, regs.pc, &ArrayObject::class_);
+        newKind = UseNewTypeForInitializer(script, REGS.pc, &ArrayObject::class_);
         obj = NewDenseEmptyArray(cx, nullptr, newKind);
     } else {
         gc::AllocKind allocKind = GuessObjectGCKind(0);
-        newKind = UseNewTypeForInitializer(script, regs.pc, &JSObject::class_);
+        newKind = UseNewTypeForInitializer(script, REGS.pc, &JSObject::class_);
         obj = NewBuiltinClassInstance(cx, &JSObject::class_, allocKind, newKind);
     }
-    if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj, newKind))
+    if (!obj || !SetInitializerObjectType(cx, script, REGS.pc, obj, newKind))
         goto error;
 
     PUSH_OBJECT(*obj);
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
+    TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
 }
 END_CASE(JSOP_NEWINIT)
 
-BEGIN_CASE(JSOP_NEWARRAY)
+CASE(JSOP_NEWARRAY)
 {
-    unsigned count = GET_UINT24(regs.pc);
+    unsigned count = GET_UINT24(REGS.pc);
     RootedObject &obj = rootObject0;
-    NewObjectKind newKind = UseNewTypeForInitializer(script, regs.pc, &ArrayObject::class_);
+    NewObjectKind newKind = UseNewTypeForInitializer(script, REGS.pc, &ArrayObject::class_);
     obj = NewDenseAllocatedArray(cx, count, nullptr, newKind);
-    if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj, newKind))
+    if (!obj || !SetInitializerObjectType(cx, script, REGS.pc, obj, newKind))
         goto error;
 
     PUSH_OBJECT(*obj);
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
+    TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
 }
 END_CASE(JSOP_NEWARRAY)
 
-BEGIN_CASE(JSOP_NEWOBJECT)
+CASE(JSOP_NEWOBJECT)
 {
     RootedObject &baseobj = rootObject0;
-    baseobj = script->getObject(regs.pc);
+    baseobj = script->getObject(REGS.pc);
 
     RootedObject &obj = rootObject1;
-    NewObjectKind newKind = UseNewTypeForInitializer(script, regs.pc, baseobj->getClass());
+    NewObjectKind newKind = UseNewTypeForInitializer(script, REGS.pc, baseobj->getClass());
     obj = CopyInitializerObject(cx, baseobj, newKind);
-    if (!obj || !SetInitializerObjectType(cx, script, regs.pc, obj, newKind))
+    if (!obj || !SetInitializerObjectType(cx, script, REGS.pc, obj, newKind))
         goto error;
 
     PUSH_OBJECT(*obj);
-    TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
+    TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
 }
 END_CASE(JSOP_NEWOBJECT)
 
-BEGIN_CASE(JSOP_ENDINIT)
+CASE(JSOP_ENDINIT)
 {
     /* FIXME remove JSOP_ENDINIT bug 588522 */
-    JS_ASSERT(regs.stackDepth() >= 1);
-    JS_ASSERT(regs.sp[-1].isObject() || regs.sp[-1].isUndefined());
+    JS_ASSERT(REGS.stackDepth() >= 1);
+    JS_ASSERT(REGS.sp[-1].isObject() || REGS.sp[-1].isUndefined());
 }
 END_CASE(JSOP_ENDINIT)
 
-BEGIN_CASE(JSOP_INITPROP)
+CASE(JSOP_INITPROP)
 {
     /* Load the property's initial value into rval. */
-    JS_ASSERT(regs.stackDepth() >= 2);
+    JS_ASSERT(REGS.stackDepth() >= 2);
     RootedValue &rval = rootValue0;
-    rval = regs.sp[-1];
+    rval = REGS.sp[-1];
 
     /* Load the object being initialized into lval/obj. */
     RootedObject &obj = rootObject0;
-    obj = &regs.sp[-2].toObject();
+    obj = &REGS.sp[-2].toObject();
     JS_ASSERT(obj->is<JSObject>());
 
-    PropertyName *name = script->getName(regs.pc);
+    PropertyName *name = script->getName(REGS.pc);
 
     RootedId &id = rootId0;
     id = NameToId(name);
 
     if (JS_UNLIKELY(name == cx->names().proto)
         ? !baseops::SetPropertyHelper<SequentialExecution>(cx, obj, obj, id, 0, &rval,
                                                            script->strict)
         : !DefineNativeProperty(cx, obj, id, rval, nullptr, nullptr,
                                 JSPROP_ENUMERATE, 0, 0, 0)) {
         goto error;
     }
 
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_INITPROP);
 
-BEGIN_CASE(JSOP_INITELEM)
+CASE(JSOP_INITELEM)
 {
-    JS_ASSERT(regs.stackDepth() >= 3);
-    HandleValue val = regs.stackHandleAt(-1);
-    HandleValue id = regs.stackHandleAt(-2);
+    JS_ASSERT(REGS.stackDepth() >= 3);
+    HandleValue val = REGS.stackHandleAt(-1);
+    HandleValue id = REGS.stackHandleAt(-2);
 
     RootedObject &obj = rootObject0;
-    obj = &regs.sp[-3].toObject();
+    obj = &REGS.sp[-3].toObject();
 
     if (!InitElemOperation(cx, obj, id, val))
         goto error;
 
-    regs.sp -= 2;
+    REGS.sp -= 2;
 }
 END_CASE(JSOP_INITELEM)
 
-BEGIN_CASE(JSOP_INITELEM_ARRAY)
+CASE(JSOP_INITELEM_ARRAY)
 {
-    JS_ASSERT(regs.stackDepth() >= 2);
-    HandleValue val = regs.stackHandleAt(-1);
+    JS_ASSERT(REGS.stackDepth() >= 2);
+    HandleValue val = REGS.stackHandleAt(-1);
 
     RootedObject &obj = rootObject0;
-    obj = &regs.sp[-2].toObject();
+    obj = &REGS.sp[-2].toObject();
 
     JS_ASSERT(obj->is<ArrayObject>());
 
-    uint32_t index = GET_UINT24(regs.pc);
-    if (!InitArrayElemOperation(cx, regs.pc, obj, index, val))
+    uint32_t index = GET_UINT24(REGS.pc);
+    if (!InitArrayElemOperation(cx, REGS.pc, obj, index, val))
         goto error;
 
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_INITELEM_ARRAY)
 
-BEGIN_CASE(JSOP_INITELEM_INC)
+CASE(JSOP_INITELEM_INC)
 {
-    JS_ASSERT(regs.stackDepth() >= 3);
-    HandleValue val = regs.stackHandleAt(-1);
+    JS_ASSERT(REGS.stackDepth() >= 3);
+    HandleValue val = REGS.stackHandleAt(-1);
 
     RootedObject &obj = rootObject0;
-    obj = &regs.sp[-3].toObject();
-
-    uint32_t index = regs.sp[-2].toInt32();
-    if (!InitArrayElemOperation(cx, regs.pc, obj, index, val))
+    obj = &REGS.sp[-3].toObject();
+
+    uint32_t index = REGS.sp[-2].toInt32();
+    if (!InitArrayElemOperation(cx, REGS.pc, obj, index, val))
         goto error;
 
-    regs.sp[-2].setInt32(index + 1);
-    regs.sp--;
+    REGS.sp[-2].setInt32(index + 1);
+    REGS.sp--;
 }
 END_CASE(JSOP_INITELEM_INC)
 
-BEGIN_CASE(JSOP_SPREAD)
+CASE(JSOP_SPREAD)
 {
-    int32_t count = regs.sp[-2].toInt32();
+    int32_t count = REGS.sp[-2].toInt32();
     RootedObject &arr = rootObject0;
-    arr = &regs.sp[-3].toObject();
-    const Value iterable = regs.sp[-1];
+    arr = &REGS.sp[-3].toObject();
+    const Value iterable = REGS.sp[-1];
     ForOfIterator iter(cx);
     RootedValue &iterVal = rootValue0;
     iterVal.set(iterable);
     if (!iter.init(iterVal))
         goto error;
     while (true) {
         bool done;
         if (!iter.next(&iterVal, &done))
@@ -3068,32 +3098,32 @@ BEGIN_CASE(JSOP_SPREAD)
             JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                                  JSMSG_SPREAD_TOO_LARGE);
             goto error;
         }
         if (!JSObject::defineElement(cx, arr, count++, iterVal, nullptr, nullptr,
                                      JSPROP_ENUMERATE))
             goto error;
     }
-    regs.sp[-2].setInt32(count);
-    regs.sp--;
+    REGS.sp[-2].setInt32(count);
+    REGS.sp--;
 }
 END_CASE(JSOP_SPREAD)
 
+CASE(JSOP_GOSUB)
 {
-BEGIN_CASE(JSOP_GOSUB)
     PUSH_BOOLEAN(false);
-    int32_t i = (regs.pc - script->code) + JSOP_GOSUB_LENGTH;
-    len = GET_JUMP_OFFSET(regs.pc);
+    int32_t i = (REGS.pc - script->code) + JSOP_GOSUB_LENGTH;
+    int32_t len = GET_JUMP_OFFSET(REGS.pc);
     PUSH_INT32(i);
-END_VARLEN_CASE
+    ADVANCE_AND_DISPATCH(len);
 }
 
+CASE(JSOP_RETSUB)
 {
-BEGIN_CASE(JSOP_RETSUB)
     /* Pop [exception or hole, retsub pc-index]. */
     Value rval, lval;
     POP_COPY_TO(rval);
     POP_COPY_TO(lval);
     JS_ASSERT(lval.isBoolean());
     if (lval.toBoolean()) {
         /*
          * Exception was pending during finally, throw it *before* we adjust
@@ -3102,206 +3132,205 @@ BEGIN_CASE(JSOP_RETSUB)
          * 350509, due to Igor Bukanov.
          */
         cx->setPendingException(rval);
         goto error;
     }
     JS_ASSERT(rval.isInt32());
 
     /* Increment the PC by this much. */
-    len = rval.toInt32() - int32_t(regs.pc - script->code);
-END_VARLEN_CASE
+    int32_t len = rval.toInt32() - int32_t(REGS.pc - script->code);
+    ADVANCE_AND_DISPATCH(len);
 }
 
-BEGIN_CASE(JSOP_EXCEPTION)
+CASE(JSOP_EXCEPTION)
 {
     PUSH_NULL();
-    MutableHandleValue res = regs.stackHandleAt(-1);
+    MutableHandleValue res = REGS.stackHandleAt(-1);
     if (!GetAndClearException(cx, res))
         goto error;
 }
 END_CASE(JSOP_EXCEPTION)
 
-BEGIN_CASE(JSOP_FINALLY)
+CASE(JSOP_FINALLY)
     CHECK_BRANCH();
 END_CASE(JSOP_FINALLY)
 
-BEGIN_CASE(JSOP_THROWING)
+CASE(JSOP_THROWING)
 {
     JS_ASSERT(!cx->isExceptionPending());
     Value v;
     POP_COPY_TO(v);
     cx->setPendingException(v);
 }
 END_CASE(JSOP_THROWING)
 
-BEGIN_CASE(JSOP_THROW)
+CASE(JSOP_THROW)
 {
     CHECK_BRANCH();
     RootedValue &v = rootValue0;
     POP_COPY_TO(v);
     JS_ALWAYS_FALSE(Throw(cx, v));
     /* let the code at error try to catch the exception. */
     goto error;
 }
 
-BEGIN_CASE(JSOP_INSTANCEOF)
+CASE(JSOP_INSTANCEOF)
 {
     RootedValue &rref = rootValue0;
-    rref = regs.sp[-1];
+    rref = REGS.sp[-1];
     if (rref.isPrimitive()) {
         js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, -1, rref, NullPtr());
         goto error;
     }
     RootedObject &obj = rootObject0;
     obj = &rref.toObject();
     bool cond = false;
-    if (!HasInstance(cx, obj, regs.stackHandleAt(-2), &cond))
+    if (!HasInstance(cx, obj, REGS.stackHandleAt(-2), &cond))
         goto error;
-    regs.sp--;
-    regs.sp[-1].setBoolean(cond);
+    REGS.sp--;
+    REGS.sp[-1].setBoolean(cond);
 }
 END_CASE(JSOP_INSTANCEOF)
 
-BEGIN_CASE(JSOP_DEBUGGER)
+CASE(JSOP_DEBUGGER)
 {
     JSTrapStatus st = JSTRAP_CONTINUE;
     RootedValue rval(cx);
     if (JSDebuggerHandler handler = cx->runtime()->debugHooks.debuggerHandler)
-        st = handler(cx, script, regs.pc, rval.address(), cx->runtime()->debugHooks.debuggerHandlerData);
+        st = handler(cx, script, REGS.pc, rval.address(), cx->runtime()->debugHooks.debuggerHandlerData);
     if (st == JSTRAP_CONTINUE)
         st = Debugger::onDebuggerStatement(cx, &rval);
     switch (st) {
       case JSTRAP_ERROR:
         goto error;
       case JSTRAP_CONTINUE:
         break;
       case JSTRAP_RETURN:
-        regs.fp()->setReturnValue(rval);
+        REGS.fp()->setReturnValue(rval);
         interpReturnOK = true;
         goto forced_return;
       case JSTRAP_THROW:
         cx->setPendingException(rval);
         goto error;
       default:;
     }
 }
 END_CASE(JSOP_DEBUGGER)
 
-BEGIN_CASE(JSOP_ENTERBLOCK)
-BEGIN_CASE(JSOP_ENTERLET0)
-BEGIN_CASE(JSOP_ENTERLET1)
-BEGIN_CASE(JSOP_ENTERLET2)
+CASE(JSOP_ENTERBLOCK)
+CASE(JSOP_ENTERLET0)
+CASE(JSOP_ENTERLET1)
+CASE(JSOP_ENTERLET2)
 {
-    StaticBlockObject &blockObj = script->getObject(regs.pc)->as<StaticBlockObject>();
-
-    if (op == JSOP_ENTERBLOCK) {
-        JS_ASSERT(regs.stackDepth() == blockObj.stackDepth());
-        JS_ASSERT(regs.stackDepth() + blockObj.slotCount() <= script->nslots);
-        Value *vp = regs.sp + blockObj.slotCount();
-        SetValueRangeToUndefined(regs.sp, vp);
-        regs.sp = vp;
+    StaticBlockObject &blockObj = script->getObject(REGS.pc)->as<StaticBlockObject>();
+
+    if (*REGS.pc == JSOP_ENTERBLOCK) {
+        JS_ASSERT(REGS.stackDepth() == blockObj.stackDepth());
+        JS_ASSERT(REGS.stackDepth() + blockObj.slotCount() <= script->nslots);
+        Value *vp = REGS.sp + blockObj.slotCount();
+        SetValueRangeToUndefined(REGS.sp, vp);
+        REGS.sp = vp;
     }
 
     /* Clone block iff there are any closed-over variables. */
-    if (!regs.fp()->pushBlock(cx, blockObj))
+    if (!REGS.fp()->pushBlock(cx, blockObj))
         goto error;
 }
 END_CASE(JSOP_ENTERBLOCK)
 
-BEGIN_CASE(JSOP_LEAVEBLOCK)
-BEGIN_CASE(JSOP_LEAVEFORLETIN)
-BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
+CASE(JSOP_LEAVEBLOCK)
+CASE(JSOP_LEAVEFORLETIN)
+CASE(JSOP_LEAVEBLOCKEXPR)
 {
-    blockDepth = regs.fp()->blockChain().stackDepth();
-
-    regs.fp()->popBlock(cx);
-
-    if (op == JSOP_LEAVEBLOCK) {
+    blockDepth = REGS.fp()->blockChain().stackDepth();
+
+    REGS.fp()->popBlock(cx);
+
+    if (*REGS.pc == JSOP_LEAVEBLOCK) {
         /* Pop the block's slots. */
-        regs.sp -= GET_UINT16(regs.pc);
-        JS_ASSERT(regs.stackDepth() == blockDepth);
-    } else if (op == JSOP_LEAVEBLOCKEXPR) {
+        REGS.sp -= GET_UINT16(REGS.pc);
+        JS_ASSERT(REGS.stackDepth() == blockDepth);
+    } else if (*REGS.pc == JSOP_LEAVEBLOCKEXPR) {
         /* Pop the block's slots maintaining the topmost expr. */
-        Value *vp = &regs.sp[-1];
-        regs.sp -= GET_UINT16(regs.pc);
-        JS_ASSERT(regs.stackDepth() == blockDepth + 1);
-        regs.sp[-1] = *vp;
+        Value *vp = &REGS.sp[-1];
+        REGS.sp -= GET_UINT16(REGS.pc);
+        JS_ASSERT(REGS.stackDepth() == blockDepth + 1);
+        REGS.sp[-1] = *vp;
     } else {
         /* Another op will pop; nothing to do here. */
-        len = JSOP_LEAVEFORLETIN_LENGTH;
-        goto advanceAndDoOp;
+        ADVANCE_AND_DISPATCH(JSOP_LEAVEFORLETIN_LENGTH);
     }
 }
 END_CASE(JSOP_LEAVEBLOCK)
 
-BEGIN_CASE(JSOP_GENERATOR)
+CASE(JSOP_GENERATOR)
 {
     JS_ASSERT(!cx->isExceptionPending());
-    regs.fp()->initGeneratorFrame();
-    regs.pc += JSOP_GENERATOR_LENGTH;
-    JSObject *obj = js_NewGenerator(cx, regs);
+    REGS.fp()->initGeneratorFrame();
+    REGS.pc += JSOP_GENERATOR_LENGTH;
+    JSObject *obj = js_NewGenerator(cx, REGS);
     if (!obj)
         goto error;
-    regs.fp()->setReturnValue(ObjectValue(*obj));
-    regs.fp()->setYielding();
+    REGS.fp()->setReturnValue(ObjectValue(*obj));
+    REGS.fp()->setYielding();
     interpReturnOK = true;
-    if (entryFrame != regs.fp())
+    if (activation.entryFrame() != REGS.fp())
         goto inline_return;
     goto exit;
 }
 
-BEGIN_CASE(JSOP_YIELD)
+CASE(JSOP_YIELD)
     JS_ASSERT(!cx->isExceptionPending());
-    JS_ASSERT(regs.fp()->isNonEvalFunctionFrame());
+    JS_ASSERT(REGS.fp()->isNonEvalFunctionFrame());
     if (cx->innermostGenerator()->state == JSGEN_CLOSING) {
         RootedValue &val = rootValue0;
-        val.setObject(regs.fp()->callee());
+        val.setObject(REGS.fp()->callee());
         js_ReportValueError(cx, JSMSG_BAD_GENERATOR_YIELD, JSDVG_SEARCH_STACK, val, NullPtr());
         goto error;
     }
-    regs.fp()->setReturnValue(regs.sp[-1]);
-    regs.fp()->setYielding();
-    regs.pc += JSOP_YIELD_LENGTH;
+    REGS.fp()->setReturnValue(REGS.sp[-1]);
+    REGS.fp()->setYielding();
+    REGS.pc += JSOP_YIELD_LENGTH;
     interpReturnOK = true;
     goto exit;
 
-BEGIN_CASE(JSOP_ARRAYPUSH)
+CASE(JSOP_ARRAYPUSH)
 {
-    uint32_t slot = GET_UINT16(regs.pc);
+    uint32_t slot = GET_UINT16(REGS.pc);
     JS_ASSERT(script->nfixed <= slot);
     JS_ASSERT(slot < script->nslots);
     RootedObject &obj = rootObject0;
-    obj = &regs.fp()->unaliasedLocal(slot).toObject();
-    if (!js_NewbornArrayPush(cx, obj, regs.sp[-1]))
+    obj = &REGS.fp()->unaliasedLocal(slot).toObject();
+    if (!js_NewbornArrayPush(cx, obj, REGS.sp[-1]))
         goto error;
-    regs.sp--;
+    REGS.sp--;
 }
 END_CASE(JSOP_ARRAYPUSH)
 
-default:
+DEFAULT()
 {
     char numBuf[12];
-    JS_snprintf(numBuf, sizeof numBuf, "%d", op);
+    JS_snprintf(numBuf, sizeof numBuf, "%d", *REGS.pc);
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                          JSMSG_BAD_BYTECODE, numBuf);
     goto error;
 }
 
-    } /* switch (op) */
+} /* interpreter loop */
 
     MOZ_ASSUME_UNREACHABLE("Interpreter loop exited via fallthrough");
 
   error:
-    JS_ASSERT(uint32_t(regs.pc - script->code) < script->length);
+    JS_ASSERT(uint32_t(REGS.pc - script->code) < script->length);
 
     if (cx->isExceptionPending()) {
         /* Call debugger throw hooks. */
         if (cx->compartment()->debugMode()) {
-            JSTrapStatus status = DebugExceptionUnwind(cx, regs.fp(), regs.pc);
+            JSTrapStatus status = DebugExceptionUnwind(cx, REGS.fp(), REGS.pc);
             switch (status) {
               case JSTRAP_ERROR:
                 goto error;
 
               case JSTRAP_CONTINUE:
               case JSTRAP_THROW:
                 break;
 
@@ -3309,63 +3338,69 @@ default:
                 interpReturnOK = true;
                 goto forced_return;
 
               default:
                 MOZ_ASSUME_UNREACHABLE("Invalid trap status");
             }
         }
 
-        for (TryNoteIter tni(cx, regs); !tni.done(); ++tni) {
+        for (TryNoteIter tni(cx, REGS); !tni.done(); ++tni) {
             JSTryNote *tn = *tni;
 
-            UnwindScope(cx, regs.fp(), tn->stackDepth);
+            UnwindScope(cx, REGS.fp(), tn->stackDepth);
 
             /*
              * Set pc to the first bytecode after the the try note to point
              * to the beginning of catch or finally or to [enditer] closing
              * the for-in loop.
              */
-            regs.pc = (script)->main() + tn->start + tn->length;
-            regs.sp = regs.spForStackDepth(tn->stackDepth);
+            REGS.pc = (script)->main() + tn->start + tn->length;
+            REGS.sp = REGS.spForStackDepth(tn->stackDepth);
 
             switch (tn->kind) {
               case JSTRY_CATCH:
-                JS_ASSERT(*regs.pc == JSOP_ENTERBLOCK || *regs.pc == JSOP_EXCEPTION);
+                JS_ASSERT(*REGS.pc == JSOP_ENTERBLOCK || *REGS.pc == JSOP_EXCEPTION);
 
                 /* Catch cannot intercept the closing of a generator. */
                   if (JS_UNLIKELY(cx->getPendingException().isMagic(JS_GENERATOR_CLOSING)))
                     break;
 
                 /*
                  * Don't clear exceptions to save cx->exception from GC
                  * until it is pushed to the stack via [exception] in the
                  * catch block.
+                 *
+                 * Also, see the comment below about the use of goto here.
                  */
-                len = 0;
-                goto advanceAndDoOp;
+                goto enterInterpreterLoop;
 
               case JSTRY_FINALLY:
                 /*
                  * Push (true, exception) pair for finally to indicate that
                  * [retsub] should rethrow the exception.
                  */
                 PUSH_BOOLEAN(true);
                 PUSH_COPY(cx->getPendingException());
                 cx->clearPendingException();
-                len = 0;
-                goto advanceAndDoOp;
+
+                /*
+                 * Leave the scope via a plain goto (and not via
+                 * ADVANCE_AND_DISPATCH, which may be implemented with indirect
+                 * goto) so that the TryNoteIter goes out of scope properly.
+                 */
+                goto enterInterpreterLoop;
 
               case JSTRY_ITER: {
                 /* This is similar to JSOP_ENDITER in the interpreter loop. */
-                JS_ASSERT(JSOp(*regs.pc) == JSOP_ENDITER);
+                JS_ASSERT(JSOp(*REGS.pc) == JSOP_ENDITER);
                 RootedObject &obj = rootObject0;
-                obj = &regs.sp[-1].toObject();
+                obj = &REGS.sp[-1].toObject();
                 bool ok = UnwindIteratorForException(cx, obj);
-                regs.sp -= 1;
+                REGS.sp -= 1;
                 if (!ok)
                     goto error;
                 break;
               }
 
               case JSTRY_LOOP:
                 break;
            }
@@ -3375,54 +3410,54 @@ default:
          * Propagate the exception or error to the caller unless the exception
          * is an asynchronous return from a generator.
          */
         interpReturnOK = false;
         if (JS_UNLIKELY(cx->isExceptionPending() &&
                         cx->getPendingException().isMagic(JS_GENERATOR_CLOSING))) {
             cx->clearPendingException();
             interpReturnOK = true;
-            regs.fp()->clearReturnValue();
+            REGS.fp()->clearReturnValue();
         }
     } else {
-        UnwindForUncatchableException(cx, regs);
+        UnwindForUncatchableException(cx, REGS);
         interpReturnOK = false;
     }
 
   forced_return:
-    UnwindScope(cx, regs.fp(), 0);
-    regs.setToEndOfScript();
-
-    if (entryFrame != regs.fp())
+    UnwindScope(cx, REGS.fp(), 0);
+    REGS.setToEndOfScript();
+
+    if (activation.entryFrame() != REGS.fp())
         goto inline_return;
 
   exit:
     if (cx->compartment()->debugMode())
-        interpReturnOK = ScriptDebugEpilogue(cx, regs.fp(), interpReturnOK);
-    if (!regs.fp()->isYielding())
-        regs.fp()->epilogue(cx);
+        interpReturnOK = ScriptDebugEpilogue(cx, REGS.fp(), interpReturnOK);
+    if (!REGS.fp()->isYielding())
+        REGS.fp()->epilogue(cx);
     else
-        probes::ExitScript(cx, script, script->function(), regs.fp());
+        probes::ExitScript(cx, script, script->function(), REGS.fp());
 
     gc::MaybeVerifyBarriers(cx, true);
 
 #if JS_TRACE_LOGGING
         TraceLogging::defaultLogger()->log(TraceLogging::SCRIPT_STOP);
 #endif
 
 #ifdef JS_ION
     /*
      * This path is used when it's guaranteed the method can be finished
      * inside the JIT.
      */
   leave_on_safe_point:
 #endif
 
     if (interpReturnOK)
-        state.setReturnValue(entryFrame->returnValue());
+        state.setReturnValue(activation.entryFrame()->returnValue());
 
     return interpReturnOK;
 }
 
 bool
 js::Throw(JSContext *cx, HandleValue v)
 {
     JS_ASSERT(!cx->isExceptionPending());
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -198,17 +198,17 @@ class RunState
     }
     GeneratorState *asGenerator() const {
         JS_ASSERT(isGenerator());
         return (GeneratorState *)this;
     }
 
     JSScript *script() const { return script_; }
 
-    virtual StackFrame *pushInterpreterFrame(JSContext *cx, FrameGuard *fg) = 0;
+    virtual StackFrame *pushInterpreterFrame(JSContext *cx) = 0;
     virtual void setReturnValue(Value v) = 0;
 
   private:
     RunState(const RunState &other) MOZ_DELETE;
     RunState(const ExecuteState &other) MOZ_DELETE;
     RunState(const InvokeState &other) MOZ_DELETE;
     RunState(const GeneratorState &other) MOZ_DELETE;
     void operator=(const RunState &other) MOZ_DELETE;
@@ -235,17 +235,17 @@ class ExecuteState : public RunState
         evalInFrame_(evalInFrame),
         result_(result)
     { }
 
     Value *addressOfThisv() { return thisv_.address(); }
     JSObject *scopeChain() const { return scopeChain_; }
     ExecuteType type() const { return type_; }
 
-    virtual StackFrame *pushInterpreterFrame(JSContext *cx, FrameGuard *fg);
+    virtual StackFrame *pushInterpreterFrame(JSContext *cx);
 
     virtual void setReturnValue(Value v) {
         if (result_)
             *result_ = v;
     }
 };
 
 // Data to invoke a function.
@@ -264,17 +264,17 @@ class InvokeState : public RunState
     { }
 
     bool useNewType() const { return useNewType_; }
     void setUseNewType() { useNewType_ = true; }
 
     bool constructing() const { return InitialFrameFlagsAreConstructing(initial_); }
     CallArgs &args() const { return args_; }
 
-    virtual StackFrame *pushInterpreterFrame(JSContext *cx, FrameGuard *fg);
+    virtual StackFrame *pushInterpreterFrame(JSContext *cx);
 
     virtual void setReturnValue(Value v) {
         args_.rval().set(v);
     }
 };
 
 // Generator script.
 class GeneratorState : public RunState
@@ -283,17 +283,17 @@ class GeneratorState : public RunState
     JSGenerator *gen_;
     JSGeneratorState futureState_;
     bool entered_;
 
   public:
     GeneratorState(JSContext *cx, JSGenerator *gen, JSGeneratorState futureState);
     ~GeneratorState();
 
-    virtual StackFrame *pushInterpreterFrame(JSContext *cx, FrameGuard *fg);
+    virtual StackFrame *pushInterpreterFrame(JSContext *cx);
     virtual void setReturnValue(Value) { }
 
     JSGenerator *gen() const { return gen_; }
 };
 
 extern bool
 RunScript(JSContext *cx, RunState &state);
 
--- a/js/src/vm/MemoryMetrics.cpp
+++ b/js/src/vm/MemoryMetrics.cpp
@@ -580,17 +580,17 @@ AddSizeOfTab(JSRuntime *rt, JSObject *ob
     rtStats.zTotals.add(rtStats.zoneStatsVector[0]);
 
     for (size_t i = 0; i < rtStats.compartmentStatsVector.length(); i++) {
         CompartmentStats &cStats = rtStats.compartmentStatsVector[i];
         rtStats.cTotals.add(cStats);
     }
 
     for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
-        comp->compartmentStats = NULL;
+        comp->compartmentStats = nullptr;
 
     rtStats.zTotals.addToTabSizes(sizes);
     rtStats.cTotals.addToTabSizes(sizes);
 
     return true;
 }
 
 } // namespace JS
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -78,17 +78,17 @@ bool
 js::intrinsic_ThrowError(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     JS_ASSERT(args.length() >= 1);
     uint32_t errorNumber = args[0].toInt32();
 
 #ifdef DEBUG
     const JSErrorFormatString *efs =
-        js_GetLocalizedErrorMessage(cx, NULL, NULL, errorNumber);
+        js_GetLocalizedErrorMessage(cx, nullptr, nullptr, errorNumber);
     JS_ASSERT(efs->argCount == args.length() - 1);
 #endif
 
     char *errorArgs[3] = {nullptr, nullptr, nullptr};
     for (unsigned i = 1; i < 4 && i < args.length(); i++) {
         RootedValue val(cx, args[i]);
         if (val.isInt32()) {
             JSString *str = ToString<CanGC>(cx, val);
@@ -992,14 +992,14 @@ JSRuntime::maybeWrappedSelfHostedFunctio
     return cx->compartment()->wrap(cx, funVal);
 }
 
 JSFunction *
 js::SelfHostedFunction(JSContext *cx, HandlePropertyName propName)
 {
     RootedValue func(cx);
     if (!cx->global()->getIntrinsicValue(cx, propName, &func))
-        return NULL;
+        return nullptr;
 
     JS_ASSERT(func.isObject());
     JS_ASSERT(func.toObject().is<JSFunction>());
     return &func.toObject().as<JSFunction>();
 }
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -835,35 +835,53 @@ Activation::Activation(JSContext *cx, Ki
 }
 
 Activation::~Activation()
 {
     JS_ASSERT(cx_->mainThread().activation_ == this);
     cx_->mainThread().activation_ = prev_;
 }
 
-InterpreterActivation::InterpreterActivation(JSContext *cx, StackFrame *entry, FrameRegs &regs,
-                                             jsbytecode *const switchMask)
+InterpreterActivation::InterpreterActivation(RunState &state, JSContext *cx, StackFrame *entryFrame)
   : Activation(cx, Interpreter),
-    entry_(entry),
-    regs_(regs),
-    switchMask_(switchMask)
+    state_(state),
+    entryFrame_(entryFrame),
+    opMask_(0)
 #ifdef DEBUG
   , oldFrameCount_(cx_->runtime()->interpreterStack().frameCount_)
 #endif
-{}
+{
+    if (!state.isGenerator()) {
+        regs_.prepareToRun(*entryFrame, state.script());
+        JS_ASSERT(regs_.pc == state.script()->code);
+    } else {
+        regs_ = state.asGenerator()->gen()->regs;
+    }
+
+    JS_ASSERT_IF(entryFrame_->isEvalFrame(), state_.script()->isActiveEval);
+}
 
 InterpreterActivation::~InterpreterActivation()
 {
     // Pop all inline frames.
-    while (regs_.fp() != entry_)
+    while (regs_.fp() != entryFrame_)
         popInlineFrame(regs_.fp());
 
     JS_ASSERT(oldFrameCount_ == cx_->runtime()->interpreterStack().frameCount_);
     JS_ASSERT_IF(oldFrameCount_ == 0, cx_->runtime()->interpreterStack().allocator_.used() == 0);
+
+    if (state_.isGenerator()) {
+        JSGenerator *gen = state_.asGenerator()->gen();
+        gen->fp->unsetPushedSPSFrame();
+        gen->regs = regs_;
+        return;
+    }
+
+    if (entryFrame_)
+        cx_->runtime()->interpreterStack().releaseFrame(entryFrame_);
 }
 
 inline bool
 InterpreterActivation::pushInlineFrame(const CallArgs &args, HandleScript script,
                                        InitialFrameFlags initial)
 {
     if (!cx_->runtime()->interpreterStack().pushInlineFrame(cx_, regs_, args, script, initial))
         return false;
@@ -871,16 +889,16 @@ InterpreterActivation::pushInlineFrame(c
     return true;
 }
 
 inline void
 InterpreterActivation::popInlineFrame(StackFrame *frame)
 {
     (void)frame; // Quell compiler warning.
     JS_ASSERT(regs_.fp() == frame);
-    JS_ASSERT(regs_.fp() != entry_);
+    JS_ASSERT(regs_.fp() != entryFrame_);
 
     cx_->runtime()->interpreterStack().popInlineFrame(regs_);
 }
 
 } /* namespace js */
 
 #endif /* vm_Stack_inl_h */
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -466,54 +466,51 @@ FrameRegs::setToEndOfScript()
     sp = fp()->base();
     pc = script->code + script->length - JSOP_STOP_LENGTH;
     JS_ASSERT(*pc == JSOP_STOP);
 }
 
 /*****************************************************************************/
 
 StackFrame *
-InterpreterStack::pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial,
-                                  FrameGuard *fg)
+InterpreterStack::pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial)
 {
     LifoAlloc::Mark mark = allocator_.mark();
 
     RootedFunction fun(cx, &args.callee().as<JSFunction>());
     RootedScript script(cx, fun->nonLazyScript());
 
     StackFrame::Flags flags = ToFrameFlags(initial);
     Value *argv;
     StackFrame *fp = getCallFrame(cx, args, script, &flags, &argv);
     if (!fp)
         return nullptr;
 
     fp->mark_ = mark;
     fp->initCallFrame(cx, nullptr, nullptr, nullptr, *fun, script, argv, args.length(), flags);
-    fg->setPushed(*this, fp);
     return fp;
 }
 
 StackFrame *
 InterpreterStack::pushExecuteFrame(JSContext *cx, HandleScript script, const Value &thisv,
                                    HandleObject scopeChain, ExecuteType type,
-                                   AbstractFramePtr evalInFrame, FrameGuard *fg)
+                                   AbstractFramePtr evalInFrame)
 {
     LifoAlloc::Mark mark = allocator_.mark();
 
     unsigned nvars = 2 /* callee, this */ + script->nslots;
     uint8_t *buffer = allocateFrame(cx, sizeof(StackFrame) + nvars * sizeof(Value));
     if (!buffer)
         return nullptr;
 
     StackFrame *fp = reinterpret_cast<StackFrame *>(buffer + 2 * sizeof(Value));
     fp->mark_ = mark;
     fp->initExecuteFrame(cx, script, evalInFrame, thisv, *scopeChain, type);
     fp->initVarsToUndefined();
 
-    fg->setPushed(*this, fp);
     return fp;
 }
 
 /*****************************************************************************/
 
 /* MSVC PGO causes xpcshell startup crashes. */
 #if defined(_MSC_VER)
 # pragma optimize("g", off)
@@ -1339,17 +1336,17 @@ jit::JitActivation::setActive(JSContext 
         cx->mainThread().ionJSContext = prevIonJSContext_;
     }
 }
 
 InterpreterFrameIterator &
 InterpreterFrameIterator::operator++()
 {
     JS_ASSERT(!done());
-    if (fp_ != activation_->entry_) {
+    if (fp_ != activation_->entryFrame_) {
         pc_ = fp_->prevpc();
         sp_ = fp_->prevsp();
         fp_ = fp_->prev();
     } else {
         pc_ = nullptr;
         sp_ = nullptr;
         fp_ = nullptr;
     }
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -22,17 +22,16 @@ struct JSCompartment;
 struct JSGenerator;
 
 namespace js {
 
 class StackFrame;
 class FrameRegs;
 
 class InvokeFrameGuard;
-class FrameGuard;
 class ExecuteFrameGuard;
 class GeneratorFrameGuard;
 
 class ScriptFrameIter;
 class AllFramesIter;
 
 class ArgumentsObject;
 class ScopeObject;
@@ -1019,17 +1018,16 @@ class FrameRegs
         return HandleValue::fromMarkedLocation(&sp[i]);
     }
 };
 
 /*****************************************************************************/
 
 class InterpreterStack
 {
-    friend class FrameGuard;
     friend class InterpreterActivation;
 
     static const size_t DEFAULT_CHUNK_SIZE = 4 * 1024;
     LifoAlloc allocator_;
 
     // Number of interpreter frames on the stack, for over-recursion checks.
     static const size_t MAX_FRAMES = 50 * 1000;
     static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
@@ -1054,21 +1052,20 @@ class InterpreterStack
 
     ~InterpreterStack() {
         JS_ASSERT(frameCount_ == 0);
     }
 
     // For execution of eval or global code.
     StackFrame *pushExecuteFrame(JSContext *cx, HandleScript script, const Value &thisv,
                                  HandleObject scopeChain, ExecuteType type,
-                                 AbstractFramePtr evalInFrame, FrameGuard *fg);
+                                 AbstractFramePtr evalInFrame);
 
     // Called to invoke a function.
-    StackFrame *pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial,
-                                FrameGuard *fg);
+    StackFrame *pushInvokeFrame(JSContext *cx, const CallArgs &args, InitialFrameFlags initial);
 
     // The interpreter can push light-weight, "inline" frames without entering a
     // new InterpreterActivation or recursively calling Interpret.
     bool pushInlineFrame(JSContext *cx, FrameRegs &regs, const CallArgs &args,
                          HandleScript script, InitialFrameFlags initial);
 
     void popInlineFrame(FrameRegs &regs);
 
@@ -1093,41 +1090,16 @@ class InvokeArgs : public JS::CallArgs
     bool init(unsigned argc) {
         if (!v_.resize(2 + argc))
             return false;
         ImplicitCast<CallArgs>(*this) = CallArgsFromVp(argc, v_.begin());
         return true;
     }
 };
 
-class RunState;
-
-class FrameGuard
-{
-    friend class InterpreterStack;
-    RunState &state_;
-    FrameRegs &regs_;
-    InterpreterStack *stack_;
-    StackFrame *fp_;
-
-    void setPushed(InterpreterStack &stack, StackFrame *fp) {
-        stack_ = &stack;
-        fp_ = fp;
-    }
-
-  public:
-    FrameGuard(RunState &state, FrameRegs &regs);
-    ~FrameGuard();
-
-    StackFrame *fp() const {
-        JS_ASSERT(fp_);
-        return fp_;
-    }
-};
-
 template <>
 struct DefaultHasher<AbstractFramePtr> {
     typedef AbstractFramePtr Lookup;
 
     static js::HashNumber hash(const Lookup &key) {
         return size_t(key.raw());
     }
 
@@ -1209,58 +1181,73 @@ class Activation
         return savedFrameChain_ > 0;
     }
 
   private:
     Activation(const Activation &other) MOZ_DELETE;
     void operator=(const Activation &other) MOZ_DELETE;
 };
 
-// The value to assign to InterpreterActivation's *switchMask_ to enable
-// interrupts. This value is greater than the greatest opcode, and is chosen
-// such that the bitwise or of this value with any opcode is this value.
+// This variable holds a special opcode value which is greater than all normal
+// opcodes, and is chosen such that the bitwise or of this value with any
+// opcode is this value.
 static const jsbytecode EnableInterruptsPseudoOpcode = -1;
 
+static_assert(EnableInterruptsPseudoOpcode >= JSOP_LIMIT,
+              "EnableInterruptsPseudoOpcode must be greater than any opcode");
+static_assert(EnableInterruptsPseudoOpcode == jsbytecode(-1),
+              "EnableInterruptsPseudoOpcode must be the maximum jsbytecode value");
+
 class InterpreterFrameIterator;
+class RunState;
 
 class InterpreterActivation : public Activation
 {
     friend class js::InterpreterFrameIterator;
 
-    StackFrame *const entry_; // Entry frame for this activation.
-    FrameRegs &regs_;
-    jsbytecode *const switchMask_; // For debugger interrupts, see js::Interpret.
+    RunState &state_;
+    FrameRegs regs_;
+    StackFrame *entryFrame_;
+    size_t opMask_; // For debugger interrupts, see js::Interpret.
 
 #ifdef DEBUG
     size_t oldFrameCount_;
 #endif
 
   public:
-    inline InterpreterActivation(JSContext *cx, StackFrame *entry, FrameRegs &regs,
-                                 jsbytecode *const switchMask);
+    inline InterpreterActivation(RunState &state, JSContext *cx, StackFrame *entryFrame);
     inline ~InterpreterActivation();
 
     inline bool pushInlineFrame(const CallArgs &args, HandleScript script,
                                 InitialFrameFlags initial);
     inline void popInlineFrame(StackFrame *frame);
 
     StackFrame *current() const {
         return regs_.fp();
     }
-    FrameRegs &regs() const {
+    FrameRegs &regs() {
         return regs_;
     }
+    StackFrame *entryFrame() const {
+        return entryFrame_;
+    }
+    size_t opMask() const {
+        return opMask_;
+    }
 
     // If this js::Interpret frame is running |script|, enable interrupts.
     void enableInterruptsIfRunning(JSScript *script) {
         if (regs_.fp()->script() == script)
             enableInterruptsUnconditionally();
     }
     void enableInterruptsUnconditionally() {
-        *switchMask_ = EnableInterruptsPseudoOpcode;
+        opMask_ = EnableInterruptsPseudoOpcode;
+    }
+    void clearInterruptsMask() {
+        opMask_ = 0;
     }
 };
 
 // Iterates over a runtime's activation list.
 class ActivationIterator
 {
     uint8_t *jitTop_;
 
@@ -1376,18 +1363,18 @@ class InterpreterFrameIterator
     explicit InterpreterFrameIterator(InterpreterActivation *activation)
       : activation_(activation),
         fp_(nullptr),
         pc_(nullptr),
         sp_(nullptr)
     {
         if (activation) {
             fp_ = activation->current();
-            pc_ = activation->regs_.pc;
-            sp_ = activation->regs_.sp;
+            pc_ = activation->regs().pc;
+            sp_ = activation->regs().sp;
         }
     }
 
     StackFrame *frame() const {
         JS_ASSERT(!done());
         return fp_;
     }
     jsbytecode *pc() const {
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -708,44 +708,44 @@ JSStructuredCloneWriter::parseTransferab
 
         if (!v.isObject()) {
             reportErrorTransferable();
             return false;
         }
 
         JSObject* tObj = CheckedUnwrap(&v.toObject());
         if (!tObj) {
-            JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_UNWRAP_DENIED);
+            JS_ReportErrorNumber(context(), js_GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED);
             return false;
         }
         if (!tObj->is<ArrayBufferObject>()) {
             reportErrorTransferable();
             return false;
         }
 
         // No duplicates allowed
         if (std::find(transferableObjects.begin(), transferableObjects.end(), tObj) != transferableObjects.end()) {
-            JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_DUP_TRANSFERABLE);
+            JS_ReportErrorNumber(context(), js_GetErrorMessage, nullptr, JSMSG_SC_DUP_TRANSFERABLE);
             return false;
         }
 
         if (!transferableObjects.append(tObj))
             return false;
     }
 
     return true;
 }
 
 void
 JSStructuredCloneWriter::reportErrorTransferable()
 {
     if (callbacks && callbacks->reportError)
         return callbacks->reportError(context(), JS_SCERR_TRANSFERABLE);
     else
-        JS_ReportErrorNumber(context(), js_GetErrorMessage, NULL, JSMSG_SC_NOT_TRANSFERABLE);
+        JS_ReportErrorNumber(context(), js_GetErrorMessage, nullptr, JSMSG_SC_NOT_TRANSFERABLE);
 }
 
 bool
 JSStructuredCloneWriter::writeString(uint32_t tag, JSString *str)
 {
     size_t length = str->length();
     const jschar *chars = str->getChars(context());
     if (!chars)
@@ -957,17 +957,17 @@ JSStructuredCloneWriter::writeTransferMa
         JSObject *obj = tr.front();
 
         if (!memory.put(obj, memory.count()))
             return false;
 
         // Emit a placeholder pointer. We will steal the data and neuter the
         // transferable later.
         if (!out.writePair(SCTAG_TRANSFER_MAP_ENTRY, SCTAG_TM_UNFILLED) ||
-            !out.writePtr(NULL) ||
+            !out.writePtr(nullptr) ||
             !out.write(0))
         {
             return false;
         }
     }
 
     return true;
 }
@@ -986,19 +986,20 @@ JSStructuredCloneWriter::transferOwnersh
     point++;
     JS_ASSERT(LittleEndian::readUint64(point) == transferableObjects.length());
     point++;
 
     for (JS::AutoObjectVector::Range tr = transferableObjects.all();
          !tr.empty();
          tr.popFront())
     {
+        RootedObject obj(context(), tr.front());
         void *content;
         uint8_t *data;
-        if (!JS_StealArrayBufferContents(context(), tr.front(), &content, &data))
+        if (!JS_StealArrayBufferContents(context(), obj, &content, &data))
             return false; // Destructor will clean up the already-transferred data
 
         MOZ_ASSERT(uint32_t(LittleEndian::readUint64(point) >> 32) == SCTAG_TRANSFER_MAP_ENTRY);
         LittleEndian::writeUint64(point++, PairToUInt64(SCTAG_TRANSFER_MAP_ENTRY, SCTAG_TM_ALLOC_DATA));
         LittleEndian::writeUint64(point++, reinterpret_cast<uint64_t>(content));
         LittleEndian::writeUint64(point++, 0);
     }
 
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -369,18 +369,18 @@ ArrayBufferObject::changeContents(JSCont
         view->setPrivate(reinterpret_cast<uint8_t*>(newDataPtr));
 
         // Notify compiled jit code that the base pointer has moved.
         if (maybecx)
             MarkObjectStateChange(maybecx, view);
     }
 
     // The list of views in the old header is reachable if the contents are
-    // being transferred, so NULL it out
-    SetViewList(this, NULL);
+    // being transferred, so null it out
+    SetViewList(this, nullptr);
 
     elements = newHeader->elements();
 
     initElementsHeader(newHeader, byteLengthCopy);
     InitViewList(this, viewListHead);
 }
 
 void
@@ -430,17 +430,17 @@ ArrayBufferObject::getTransferableConten
     if (hasDynamicElements() && !isAsmJSArrayBuffer()) {
         *callerOwns = false;
         return getElementsHeader();
     }
 
     uint32_t byteLen = byteLength();
     ObjectElements *newheader = AllocateArrayBufferContents(maybecx, byteLen, dataPointer());
     if (!newheader)
-        return NULL;
+        return nullptr;
 
     initElementsHeader(newheader, byteLen);
     *callerOwns = true;
     return newheader;
 }
 
 #if defined(JS_ION) && defined(JS_CPU_X64)
 // To avoid dynamically checking bounds on each load/store, asm.js code relies
@@ -665,39 +665,39 @@ ArrayBufferObject::createDataViewForThis
 bool
 ArrayBufferObject::createDataViewForThis(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsArrayBuffer, createDataViewForThisImpl>(cx, args);
 }
 
 bool
-ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents, uint8_t **data)
+ArrayBufferObject::stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer, void **contents,
+                                 uint8_t **data)
 {
-    ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
-
     // Make the data stealable
     bool own;
-    ObjectElements *header = reinterpret_cast<ObjectElements*>(buffer.getTransferableContents(cx, &own));
+    ObjectElements *header = reinterpret_cast<ObjectElements*>(buffer->getTransferableContents(cx, &own));
     if (!header)
         return false;
+    JS_ASSERT(!IsInsideNursery(cx->runtime(), header));
     *contents = header;
     *data = reinterpret_cast<uint8_t *>(header + 1);
 
     // Neuter the views, which may also mprotect(PROT_NONE) the buffer. So do
     // it after copying out the data.
-    if (!buffer.neuterViews(cx))
+    if (!buffer->neuterViews(cx))
         return false;
 
     if (!own) {
         // If header has dynamically allocated elements, revert it back to
         // fixed-element storage before neutering it.
-        buffer.changeContents(cx, ObjectElements::fromElements(buffer.fixedElements()));
+        buffer->changeContents(cx, ObjectElements::fromElements(buffer->fixedElements()));
     }
-    buffer.neuter(cx);
+    buffer->neuter(cx);
 
     return true;
 }
 
 void
 ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj)
 {
     /*
@@ -4020,17 +4020,17 @@ JS_GetArrayBufferByteLength(JSObject *ob
 
 JS_FRIEND_API(uint8_t *)
 JS_GetArrayBufferData(JSObject *obj)
 {
     obj = CheckedUnwrap(obj);
     if (!obj)
         return nullptr;
     ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
-    if (!buffer.ensureNonInline(NULL))
+    if (!buffer.ensureNonInline(nullptr))
         return nullptr;
     return buffer.dataPointer();
 }
 
 JS_FRIEND_API(bool)
 JS_NeuterArrayBuffer(JSContext *cx, JSObject *obj)
 {
     ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
@@ -4083,28 +4083,29 @@ JS_ReallocateArrayBufferContents(JSConte
     ArrayBufferObject::initElementsHeader(header, nbytes);
 
     *contents = header;
     *data = reinterpret_cast<uint8_t*>(header->elements());
     return true;
 }
 
 JS_PUBLIC_API(bool)
-JS_StealArrayBufferContents(JSContext *cx, JSObject *obj, void **contents,
-                            uint8_t **data)
+JS_StealArrayBufferContents(JSContext *cx, HandleObject objArg, void **contents, uint8_t **data)
 {
-    if (!(obj = CheckedUnwrap(obj)))
+    JSObject *obj = CheckedUnwrap(objArg);
+    if (!obj)
         return false;
 
     if (!obj->is<ArrayBufferObject>()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_BAD_ARGS);
         return false;
     }
 
-    if (!ArrayBufferObject::stealContents(cx, obj, contents, data))
+    Rooted<ArrayBufferObject*> buffer(cx, &obj->as<ArrayBufferObject>());
+    if (!ArrayBufferObject::stealContents(cx, buffer, contents, data))
         return false;
 
     return true;
 }
 
 JS_FRIEND_API(uint32_t)
 JS_GetTypedArrayLength(JSObject *obj)
 {
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -138,17 +138,17 @@ class ArrayBufferObject : public JSObjec
                               MutableHandleValue statep, MutableHandleId idp);
 
     static void sweep(JSCompartment *rt);
 
     static void resetArrayBufferList(JSCompartment *rt);
     static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
     static void restoreArrayBufferLists(ArrayBufferVector &vector);
 
-    static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
+    static bool stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer, void **contents,
                               uint8_t **data);
 
     static void updateElementsHeader(js::ObjectElements *header, uint32_t bytes) {
         header->initializedLength = bytes;
 
         // NB: one or both of these fields is clobbered by GetViewList to store
         // the 'views' link. Set them to 0 to effectively initialize 'views'
         // to nullptr.
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -988,16 +988,19 @@ XPCConvert::JSObject2NativeInterface(voi
         // we aren't, throw an exception eagerly.
         JSObject* inner = js::CheckedUnwrap(src, /* stopAtOuter = */ false);
 
         // Hack - For historical reasons, wrapped chrome JS objects have been
         // passable as native interfaces. We'd like to fix this, but it
         // involves fixing the contacts API and PeerConnection to stop using
         // COWs. This needs to happen, but for now just preserve the old
         // behavior.
+        //
+        // Note that there is an identical hack in getWrapper which should be
+        // removed if this one is.
         if (!inner && MOZ_UNLIKELY(xpc::WrapperFactory::IsCOW(src)))
             inner = js::UncheckedUnwrap(src);
         if (!inner) {
             if (pErr)
                 *pErr = NS_ERROR_XPC_SECURITY_MANAGER_VETO;
             return false;
         }
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2361,18 +2361,21 @@ ReportJSRuntimeExplicitTreeStats(const J
 }
 
 nsresult
 ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
                                  const nsACString &rtPath,
                                  nsIMemoryReporterCallback *cb,
                                  nsISupports *closure, size_t *rtTotalOut)
 {
-    nsCOMPtr<amIAddonManager> am =
-      do_GetService("@mozilla.org/addons/integration;1");
+    nsCOMPtr<amIAddonManager> am;
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+        // Only try to access the service from the main process.
+        am = do_GetService("@mozilla.org/addons/integration;1");
+    }
     return ReportJSRuntimeExplicitTreeStats(rtStats, rtPath, am.get(), cb,
                                             closure, rtTotalOut);
 }
 
 
 } // namespace xpc
 
 class JSMainRuntimeCompartmentsReporter MOZ_FINAL : public nsIMemoryReporter
@@ -2599,18 +2602,21 @@ JSReporter::CollectReports(WindowPaths *
     XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance();
 
     // In the first step we get all the stats and stash them in a local
     // data structure.  In the second step we pass all the stashed stats to
     // the callback.  Separating these steps is important because the
     // callback may be a JS function, and executing JS while getting these
     // stats seems like a bad idea.
 
-    nsCOMPtr<amIAddonManager> addonManager =
-      do_GetService("@mozilla.org/addons/integration;1");
+    nsCOMPtr<amIAddonManager> addonManager;
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+        // Only try to access the service from the main process.
+        addonManager = do_GetService("@mozilla.org/addons/integration;1");
+    }
     bool getLocations = !!addonManager;
     XPCJSRuntimeStats rtStats(windowPaths, topWindowPaths, getLocations);
     OrphanReporter orphanReporter(XPCConvert::GetISupportsFromJSObject);
     if (!JS::CollectRuntimeStats(xpcrt->Runtime(), &rtStats, &orphanReporter))
         return NS_ERROR_FAILURE;
 
     size_t xpconnect =
         xpcrt->SizeOfIncludingThis(JSMallocSizeOf) +
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "jsprf.h"
 #include "nsCOMPtr.h"
+#include "WrapperFactory.h"
 #include "xpcprivate.h"
 #include "XPCInlines.h"
 #include "XPCQuickStubs.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Exceptions.h"
 
 using namespace mozilla;
 using namespace JS;
@@ -526,24 +527,38 @@ getWrapper(JSContext *cx,
     // We can have at most three layers in need of unwrapping here:
     // * A (possible) security wrapper
     // * A (possible) Xray waiver
     // * A (possible) outer window
     //
     // If we pass stopAtOuter == false, we can handle all three with one call
     // to js::CheckedUnwrap.
     if (js::IsWrapper(obj)) {
-        obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
+        JSObject* inner = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
+
+        // Hack - For historical reasons, wrapped chrome JS objects have been
+        // passable as native interfaces. We'd like to fix this, but it
+        // involves fixing the contacts API and PeerConnection to stop using
+        // COWs. This needs to happen, but for now just preserve the old
+        // behavior.
+        //
+        // Note that there is an identical hack in
+        // XPCConvert::JSObject2NativeInterface which should be removed if this
+        // one is.
+        if (!inner && MOZ_UNLIKELY(xpc::WrapperFactory::IsCOW(obj)))
+            inner = js::UncheckedUnwrap(obj);
 
         // The safe unwrap might have failed if we encountered an object that
         // we're not allowed to unwrap. If it didn't fail though, we should be
         // done with wrappers.
-        if (!obj)
+        if (!inner)
             return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
-        MOZ_ASSERT(!js::IsWrapper(obj));
+        MOZ_ASSERT(!js::IsWrapper(inner));
+
+        obj = inner;
     }
 
     // Start with sane values.
     *wrapper = nullptr;
     *cur = nullptr;
     *tearoff = nullptr;
 
     if (dom::IsDOMObject(obj)) {
deleted file mode 100644
--- a/media/kiss_fft/Makefile.in
+++ /dev/null
@@ -1,7 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
--- a/media/kiss_fft/moz.build
+++ b/media/kiss_fft/moz.build
@@ -13,8 +13,10 @@ EXPORTS.kiss_fft += [
 
 SOURCES += [
     'kiss_fft.c',
     'kiss_fftr.c',
 ]
 
 LIBRARY_NAME = 'kiss_fft'
 
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/libcubeb/src/Makefile.in
+++ b/media/libcubeb/src/Makefile.in
@@ -1,15 +1,12 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq ($(OS_TARGET),WINNT)
-VISIBILITY_FLAGS =
-endif
 
 ifeq ($(OS_TARGET),WINNT)
 DEFINES         += -DUSE_WINMM -DUSE_WASAPI
 endif
 
 ifeq ($(OS_TARGET),Android)
 ifneq ($(MOZ_WIDGET_TOOLKIT),gonk)
 DEFINES         += -DUSE_AUDIOTRACK
--- a/media/libcubeb/src/moz.build
+++ b/media/libcubeb/src/moz.build
@@ -47,8 +47,11 @@ if CONFIG['OS_TARGET'] == 'Android':
             'cubeb_audiotrack.c',
         ]
 
 LIBRARY_NAME = 'cubeb'
 
 MSVC_ENABLE_PGO = True
 
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/libjpeg/Makefile.in
+++ b/media/libjpeg/Makefile.in
@@ -1,17 +1,13 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq ($(OS_ARCH),WINNT)
-VISIBILITY_FLAGS	=
-endif
-
 AS=$(LIBJPEG_TURBO_AS)
 ASM_SUFFIX=asm
 ASFLAGS=$(LIBJPEG_TURBO_ASFLAGS) -I$(topsrcdir)/media/libjpeg/simd/
 
 ifeq ($(AS),yasm)
   # yasm doesn't like -c
   AS_DASH_C_FLAG=
 endif
--- a/media/libjpeg/moz.build
+++ b/media/libjpeg/moz.build
@@ -147,8 +147,11 @@ else: # No SIMD support?
     ]
 
 LIBRARY_NAME = 'mozjpeg'
 
 MSVC_ENABLE_PGO = True
 
 # need static lib for some of the libimg componentry to link properly
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/libnestegg/src/Makefile.in
+++ b/media/libnestegg/src/Makefile.in
@@ -1,7 +1,4 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
--- a/media/libnestegg/src/moz.build
+++ b/media/libnestegg/src/moz.build
@@ -11,8 +11,11 @@ SOURCES += [
     'nestegg.c',
 ]
 
 LIBRARY_NAME = 'nestegg'
 
 MSVC_ENABLE_PGO = True
 
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/libogg/src/Makefile.in
+++ b/media/libogg/src/Makefile.in
@@ -1,7 +1,4 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
--- a/media/libogg/src/moz.build
+++ b/media/libogg/src/moz.build
@@ -11,8 +11,11 @@ SOURCES += [
     'ogg_framing.c',
 ]
 
 LIBRARY_NAME = 'ogg'
 
 MSVC_ENABLE_PGO = True
 
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/libpng/Makefile.in
+++ b/media/libpng/Makefile.in
@@ -1,8 +1,5 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq ($(OS_ARCH),WINNT)
-VISIBILITY_FLAGS=
-endif
--- a/media/libpng/moz.build
+++ b/media/libpng/moz.build
@@ -45,8 +45,11 @@ if CONFIG['MOZ_PNG_ARM_NEON']:
         'arm/filter_neon.S'
     ]
 
 LIBRARY_NAME = 'mozpng'
 
 MSVC_ENABLE_PGO = True
 
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/libsoundtouch/src/Makefile.in
+++ b/media/libsoundtouch/src/Makefile.in
@@ -1,14 +1,13 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SHORT_LIBNAME = soundt
-VISIBILITY_FLAGS =
 EXTRA_DSO_LDOPTS += $(MOZALLOC_LIB)
 
 # Use abort() instead of exception in SoundTouch.
 DEFINES += -DST_NO_EXCEPTION_HANDLING=1
 
 include $(topsrcdir)/config/rules.mk
 
 ifneq (,$(INTEL_ARCHITECTURE))
--- a/media/libsoundtouch/src/moz.build
+++ b/media/libsoundtouch/src/moz.build
@@ -31,9 +31,9 @@ if CONFIG['INTEL_ARCHITECTURE']:
     else:
         SOURCES += [
             'mmx_optimized.cpp',
         ]
 
 LIBRARY_NAME = 'soundtouch'
 
 MSVC_ENABLE_PGO = True
-
+NO_VISIBILITY_FLAGS = True
--- a/media/libtheora/lib/Makefile.in
+++ b/media/libtheora/lib/Makefile.in
@@ -1,15 +1,12 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
 
 # The encoder is currently not included.
 DEFINES += -DTHEORA_DISABLE_ENCODE
 
 ifeq ($(findstring 86,$(OS_TEST)), 86)
 ifneq ($(OS_ARCH),SunOS)
 ifneq ($(OS_ARCH)$(OS_TEST),WINNTx86_64)
 DEFINES += -DOC_X86_ASM
--- a/media/libtheora/lib/moz.build
+++ b/media/libtheora/lib/moz.build
@@ -22,8 +22,11 @@ SOURCES += [
     'internal.c',
     'quant.c',
     'state.c',
 ]
 
 MSVC_ENABLE_PGO = True
 
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/libvorbis/lib/Makefile.in
+++ b/media/libvorbis/lib/Makefile.in
@@ -1,11 +1,8 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
 
 ifeq ($(OS_ARCH),AIX)
 DEFINES += -Dalloca=__alloca
 endif
--- a/media/libvorbis/lib/moz.build
+++ b/media/libvorbis/lib/moz.build
@@ -29,8 +29,11 @@ SOURCES += [
     'vorbis_smallft.c',
     'vorbis_synthesis.c',
     'vorbis_window.c',
 ]
 
 MSVC_ENABLE_PGO = True
 
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/libvpx/Makefile.in
+++ b/media/libvpx/Makefile.in
@@ -1,18 +1,15 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 DEFINES += -DHAVE_CONFIG_H=vpx_config.h
 
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
 
 LOCAL_INCLUDES += \
   -I. \
   -I$(topsrcdir)/media/libvpx \
   -I$(topsrcdir)/media/libvpx/vp8/ \
   -I$(topsrcdir)/media/libvpx/vp8/common/ \
   -I$(topsrcdir)/media/libvpx/vp8/common/arm \
   -I$(topsrcdir)/media/libvpx/vp8/common/x86 \
--- a/media/libvpx/moz.build
+++ b/media/libvpx/moz.build
@@ -88,8 +88,11 @@ SOURCES += [
     'vpx_scale/generic/vpxscale.c',
     'vpx_scale/generic/yv12config.c',
     'vpx_scale/generic/yv12extend.c',
 ]
 
 MSVC_ENABLE_PGO = True
 
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/mtransport/build/Makefile.in
+++ b/media/mtransport/build/Makefile.in
@@ -1,17 +1,13 @@
 # -*- Mode: makefile; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
-
 DEFINES += -DHAVE_STRDUP -DNR_SOCKET_IS_VOID_PTR
 
 ifneq (,$(filter Darwin DragonFly FreeBSD NetBSD OpenBSD,$(OS_TARGET)))
 ifeq ($(OS_TARGET), Darwin)
 DEFINES += -DDARWIN
 else
 DEFINES += -DBSD
 endif
--- a/media/mtransport/build/moz.build
+++ b/media/mtransport/build/moz.build
@@ -66,8 +66,11 @@ elif CONFIG['OS_TARGET'] == 'Linux':
 elif CONFIG['OS_TARGET'] == 'Android':
     LOCAL_INCLUDES += [
         '/media/mtransport/third_party/nrappkit/src/port/android/include',
     ]
 elif CONFIG['OS_TARGET'] == 'WINNT':
     LOCAL_INCLUDES += [
         '/media/mtransport/third_party/nrappkit/src/port/win32/include',
     ]
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/media/mtransport/standalone/Makefile.in
+++ b/media/mtransport/standalone/Makefile.in
@@ -1,16 +1,13 @@
 # -*- Mode: makefile; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-ifeq (WINNT,$(OS_TARGET))
-VISIBILITY_FLAGS =
-endif
 
 DEFINES += -DHAVE_STRDUP -DNR_SOCKET_IS_VOID_PTR
 
 ifneq (,$(filter Darwin DragonFly FreeBSD NetBSD OpenBSD,$(OS_TARGET)))
 ifeq ($(OS_TARGET), Darwin)
 DEFINES += -DDARWIN
 else
 DEFINES += -DBSD
--- a/media/mtransport/standalone/moz.build
+++ b/media/mtransport/standalone/moz.build
@@ -46,8 +46,11 @@ elif CONFIG['OS_TARGET'] == 'Android':
         '/media/mtransport/third_party/nrappkit/src/port/android/include',
     ]
 elif CONFIG['OS_TARGET'] == 'WINNT':
     LOCAL_INCLUDES += [
         '/media/mtransport/third_party/nrappkit/src/port/win32/include',
     ]
 
 FORCE_STATIC_LIB = True
+
+if CONFIG['OS_TARGET'] == 'WINNT':
+    NO_VISIBILITY_FLAGS = True
--- a/memory/mozalloc/Makefile.in
+++ b/memory/mozalloc/Makefile.in
@@ -1,14 +1,13 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-VISIBILITY_FLAGS=
 STL_FLAGS	=
 ifdef _MSC_VER
 STL_FLAGS	= -D_HAS_EXCEPTIONS=0
 endif
 
 DIST_INSTALL 	= 1
 
 ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
--- a/memory/mozalloc/moz.build
+++ b/memory/mozalloc/moz.build
@@ -1,15 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MODULE = 'mozalloc'
+NO_VISIBILITY_FLAGS = True
 
 EXPORTS.mozilla += [
     'fallible.h',
     'mozalloc.h',
     'mozalloc_abort.h',
     'mozalloc_macro_wrappers.h',
     'mozalloc_oom.h',
     'mozalloc_undef_macro_wrappers.h',
--- a/mozglue/build/Makefile.in
+++ b/mozglue/build/Makefile.in
@@ -10,18 +10,16 @@ DIST_INSTALL = 1
 ifneq (,$(filter WINNT Darwin Android,$(OS_TARGET)))
 FORCE_SHARED_LIB = 1
 endif
 
 # Keep jemalloc separated when mozglue is statically linked
 ifeq (1_1,$(MOZ_MEMORY)_$(or $(MOZ_NATIVE_JEMALLOC),$(FORCE_SHARED_LIB)))
 SHARED_LIBRARY_LIBS = $(call EXPAND_LIBNAME_PATH,memory,$(DEPTH)/memory/build)
 else
-# Temporary, until bug 662814 lands
-VISIBILITY_FLAGS =
 
 ifneq (,$(filter OS2 WINNT,$(OS_ARCH)))
 SDK_LIBRARY = $(IMPORT_LIBRARY)
 else
 ifdef FORCE_SHARED_LIB
 SDK_LIBRARY = $(SHARED_LIBRARY)
 else
 SDK_LIBRARY = $(REAL_LIBRARY)
--- a/mozglue/build/moz.build
+++ b/mozglue/build/moz.build
@@ -15,16 +15,18 @@ if CONFIG['OS_TARGET'] in ('WINNT', 'Dar
 else:
     force_shared_lib = 0
     FORCE_STATIC_LIB = True
 
 if CONFIG['MOZ_MEMORY'] and (CONFIG['MOZ_NATIVE_JEMALLOC'] or force_shared_lib):
     pass
     # TODO: SHARED_LIBRARY_LIBS go here
 else:
+    # Temporary, until bug 662814 lands
+    NO_VISIBILITY_FLAGS = True
     SOURCES += [
         'dummy.cpp',
     ]
 
 if CONFIG['OS_TARGET'] == 'Android':
     SOURCES += [
         'BionicGlue.cpp',
     ]
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -166,16 +166,20 @@ class TreeMetadataEmitter(LoggingMixin):
             SDK_LIBRARY='SDK_LIBRARY',
             SHARED_LIBRARY_LIBS='SHARED_LIBRARY_LIBS',
             SIMPLE_PROGRAMS='SIMPLE_PROGRAMS',
         )
         for mak, moz in varmap.items():
             if sandbox[moz]:
                 passthru.variables[mak] = sandbox[moz]
 
+        # NO_VISIBILITY_FLAGS is slightly different
+        if sandbox['NO_VISIBILITY_FLAGS']:
+            passthru.variables['VISIBILITY_FLAGS'] = ''
+
         varmap = dict(
             ASFILES=('SOURCES', ('.s', '.asm')),
             CSRCS=('SOURCES', '.c'),
             CMMSRCS=('SOURCES', '.mm'),
             CPPSRCS=('SOURCES', ('.cc', '.cpp')),
             SSRCS=('SOURCES', '.S'),
             HOST_CPPSRCS=('HOST_SOURCES', ('.cc', '.cpp')),
             HOST_CSRCS=('HOST_SOURCES', '.c'),
--- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
+++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py
@@ -252,16 +252,20 @@ VARIABLES = {
     'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list, [],
         """Additional directories to be searched for include files by the compiler.
         """, None),
 
     'MSVC_ENABLE_PGO': (bool, bool, False,
         """Whether profile-guided optimization is enabled in this directory.
         """, None),
 
+    'NO_VISIBILITY_FLAGS': (bool, bool, False,
+        """Build sources listed in this file without VISIBILITY_FLAGS.
+        """, None),
+
     'OS_LIBS': (list, list, [],
         """System link libraries.
 
         This variable contains a list of system libaries to link against.
         """, None),
 
     'SDK_LIBRARY': (StrictOrderingOnAppendList, list, [],
         """Elements of the distributed SDK.
--- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
@@ -38,8 +38,9 @@ SOURCES += ['bar.c', 'foo.c']
 
 SOURCES += ['bar.mm', 'foo.mm']
 
 SOURCES += ['baz.S', 'foo.S']
 
 FAIL_ON_WARNINGS = True
 LIBXUL_LIBRARY = True
 MSVC_ENABLE_PGO = True
+NO_VISIBILITY_FLAGS = True
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -353,16 +353,19 @@ class TestRecursiveMakeBackend(BackendTe
             'SIMPLE_PROGRAMS': [
                 'SIMPLE_PROGRAMS += bar.x',
                 'SIMPLE_PROGRAMS += foo.x',
             ],
             'SSRCS': [
                 'SSRCS += baz.S',
                 'SSRCS += foo.S',
             ],
+            'VISIBILITY_FLAGS': [
+                'VISIBILITY_FLAGS :=',
+            ],
         }
 
         for var, val in expected.items():
             # print("test_variable_passthru[%s]" % (var))
             found = [str for str in lines if str.startswith(var)]
             self.assertEqual(found, val)
 
     def test_exports(self):
--- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
@@ -45,8 +45,9 @@ LIBXUL_LIBRARY = True
 MSVC_ENABLE_PGO = True
 
 NO_DIST_INSTALL = True
 
 FORCE_SHARED_LIB = True
 FORCE_STATIC_LIB = True
 EXPORT_LIBRARY = True
 IS_COMPONENT = True
+NO_VISIBILITY_FLAGS = True
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -158,16 +158,17 @@ class TestEmitterBasic(unittest.TestCase
             MSVC_ENABLE_PGO=True,
             NO_DIST_INSTALL=True,
             MODULE='module_name',
             OS_LIBS=['foo.so', '-l123', 'aaa.a'],
             SDK_LIBRARY=['fans.sdk', 'tans.sdk'],
             SHARED_LIBRARY_LIBS=['fans.sll', 'tans.sll'],
             SIMPLE_PROGRAMS=['fans.x', 'tans.x'],
             SSRCS=['bans.S', 'fans.S'],
+            VISIBILITY_FLAGS='',
         )
 
         variables = objs[1].variables
         maxDiff = self.maxDiff
         self.maxDiff = None
         self.assertEqual(wanted, variables)
         self.maxDiff = maxDiff
 
--- a/security/manager/ssl/src/ScopedNSSTypes.h
+++ b/security/manager/ssl/src/ScopedNSSTypes.h
@@ -231,17 +231,17 @@ SECITEM_AllocItem(SECItem & item, uint32
   }
 }
 
 class ScopedAutoSECItem MOZ_FINAL : public SECItem
 {
 public:
   ScopedAutoSECItem(uint32_t initialAllocatedLen = 0)
   {
-    data = NULL;
+    data = nullptr;
     len = 0;
     if (initialAllocatedLen > 0) {
       SECITEM_AllocItem(*this, initialAllocatedLen);
     }
   }
 
   void reset()
   {
--- a/security/manager/ssl/src/nsCrypto.cpp
+++ b/security/manager/ssl/src/nsCrypto.cpp
@@ -2302,18 +2302,18 @@ nsCrypto::ImportUserCertificates(const n
 
   numResponses = CMMF_CertRepContentGetNumResponses(certRepContent);
 
   if (aDoForcedBackup) {
     //We've been asked to force the user to back up these
     //certificates.  Let's keep an array of them around which
     //we pass along to the nsP12Runnable to use.
     certArr = new nsIX509Cert*[numResponses];
-    // If this is NULL, chances are we're gonna fail really soon,
-    // but let's try to keep going just in case.
+    // If this is nullptr, chances are we're gonna fail really
+    // soon, but let's try to keep going just in case.
     if (!certArr)
       aDoForcedBackup = false;
 
     memset(certArr, 0, sizeof(nsIX509Cert*)*numResponses);
   }
   for (i=0; i<numResponses; i++) {
     currResponse = CMMF_CertRepContentGetResponseAtIndex(certRepContent,i);
     if (!currResponse) {
--- a/security/manager/ssl/src/nsIdentityChecking.cpp
+++ b/security/manager/ssl/src/nsIdentityChecking.cpp
@@ -83,17 +83,17 @@ struct nsMyTrustedEVInfo
  * - the constant SEC_OID_UNKNOWN
  *   (it will be replaced at runtime with another identifier)
  * - the UPPERCASE version of the SHA1 fingerprint, hexadecimal,
  *   bytes separated by colons (as printed by pp)
  * - the "Issuer DER Base64" as printed by the pp tool.
  *   Remove all whitespaces. If you use multiple lines, make sure that
  *   only the final line will be followed by a comma.
  * - the "Serial DER Base64" (as printed by pp)
- * - a NULL pointer value
+ * - a nullptr value
  *
  * After adding an entry, test it locally against the test site that
  * has been provided by the CA. Note that you must use a version of NSS
  * where the root certificate has already been added and marked as trusted
  * for issueing SSL server certificates (at least).
  *
  * If you are able to connect to the site without certificate errors,
  * but you don't see the EV status indicator, then most likely the CA
--- a/security/manager/ssl/src/nsNSSCertHelper.cpp
+++ b/security/manager/ssl/src/nsNSSCertHelper.cpp
@@ -937,18 +937,18 @@ ProcessName(CERTName *name, nsINSSCompon
   CERTRDN **lastRdn;
   lastRdn = rdns;
 
 
   /* find last RDN */
   lastRdn = rdns;
   while (*lastRdn) lastRdn++;
   // The above whille loop will put us at the last member
-  // of the array which is a NULL pointer.  So let's back
-  // up one spot so that we have the last non-NULL entry in 
+  // of the array which is a nullptr pointer.  So let's back
+  // up one spot so that we have the last non-nullptr entry in 
   // the array in preparation for traversing the 
   // RDN's (Relative Distinguished Name) in reverse oder.
   lastRdn--;
    
   /*
    * Loop over name contents in _reverse_ RDN order appending to string
    * When building the Ascii string, NSS loops over these entries in 
    * reverse order, so I will as well.  The difference is that NSS
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -2019,19 +2019,19 @@ private:
  * Purpose: this callback function is used to pull client certificate
  *			information upon server request
  *
  * Arguments and return values
  * - arg: SSL data connection
  * - socket: SSL socket we're dealing with
  * - caNames: list of CA names
  * - pRetCert: returns a pointer to a pointer to a valid certificate if
- *			   successful; otherwise NULL
+ *			   successful; otherwise nullptr
  * - pRetKey: returns a pointer to a pointer to the corresponding key if
- *			  successful; otherwise NULL
+ *			  successful; otherwise nullptr
  * - returns: SECSuccess if successful; error code otherwise
  */
 SECStatus nsNSS_SSLGetClientAuthData(void* arg, PRFileDesc* socket,
 								   CERTDistNames* caNames,
 								   CERTCertificate** pRetCert,
 								   SECKEYPrivateKey** pRetKey)
 {
   nsNSSShutDownPreventionLock locker;
--- a/security/manager/ssl/src/nsPKCS12Blob.h
+++ b/security/manager/ssl/src/nsPKCS12Blob.h
@@ -59,17 +59,17 @@ private:
 
   // RetryReason and ImportMode are used when importing a PKCS12 file.
   // There are two reasons that cause us to retry:
   // - When the password entered by the user is incorrect.
   //   The user will be prompted to try again.
   // - When the user entered a zero length password.
   //   An empty password should be represented as an empty
   //   string (a SECItem that contains a single terminating
-  //   NULL UTF16 character), but some applications use a
+  //   null UTF16 character), but some applications use a
   //   zero length SECItem.
   //   We try both variations, zero length item and empty string,
   //   without giving a user prompt when trying the different empty password flavors.
   
   enum RetryReason { rr_do_not_retry, rr_bad_password, rr_auto_retry_empty_password_flavors };
   enum ImportMode { im_standard_prompt, im_try_zero_length_secitem };
   
   nsresult ImportFromFileHelper(nsIFile *file, ImportMode aImportMode, RetryReason &aWantRetry);
--- a/security/manager/ssl/src/nsRandomGenerator.cpp
+++ b/security/manager/ssl/src/nsRandomGenerator.cpp
@@ -25,17 +25,17 @@ nsRandomGenerator::GenerateRandomBytes(u
   NS_ENSURE_ARG_POINTER(aBuffer);
   *aBuffer = nullptr;
 
   uint8_t *buf = reinterpret_cast<uint8_t *>(NS_Alloc(aLength));
   if (!buf)
     return NS_ERROR_OUT_OF_MEMORY;
 
   mozilla::ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
-  if (slot == NULL) {
+  if (slot == nullptr) {
     return NS_ERROR_FAILURE;
   }
   SECStatus srv = PK11_GenerateRandomOnSlot(slot, buf, aLength);
 
   if (SECSuccess != srv) {
     NS_Free(buf);
     return NS_ERROR_FAILURE;
   }
--- a/security/sandbox/Makefile.in
+++ b/security/sandbox/Makefile.in
@@ -1,6 +1,26 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+ifeq ($(OS_ARCH),WINNT)
+LOCAL_INCLUDES += \
+    -I$(topsrcdir)/security/sandbox/base/shim \
+    -I$(topsrcdir)/security \
+    -I$(topsrcdir)/nsprpub \
+    $(NULL)
+
+DEFINES += -DUNICODE -D_UNICODE -DNS_NO_XPCOM -DSANDBOX_EXPORTS -DNOMINMAX -D_CRT_RAND_S
+
+EXTRA_SDK_DECLS = $(topsrcdir)/security/sandbox/base/shim/sdkdecls.h
+
+ifdef _MSC_VER
+OS_CXXFLAGS += -FI $(EXTRA_SDK_DECLS)
+else
+OS_CXXFLAGS += -include $(EXTRA_SDK_DECLS)
+endif
+
+STL_FLAGS =
+MOZ_GLUE_LDFLAGS =
+endif
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/security/sandbox/base/at_exit.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/at_exit.h"
+
+#include <stddef.h>
+#include <ostream>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+
+namespace base {
+
+// Keep a stack of registered AtExitManagers.  We always operate on the most
+// recent, and we should never have more than one outside of testing (for a
+// statically linked version of this library).  Testing may use the shadow
+// version of the constructor, and if we are building a dynamic library we may
+// end up with multiple AtExitManagers on the same process.  We don't protect
+// this for thread-safe access, since it will only be modified in testing.
+static AtExitManager* g_top_manager = NULL;
+
+AtExitManager::AtExitManager() : next_manager_(g_top_manager) {
+// If multiple modules instantiate AtExitManagers they'll end up living in this
+// module... they have to coexist.
+#if !defined(COMPONENT_BUILD)
+  DCHECK(!g_top_manager);
+#endif
+  g_top_manager = this;
+}
+
+AtExitManager::~AtExitManager() {
+  if (!g_top_manager) {
+    NOTREACHED() << "Tried to ~AtExitManager without an AtExitManager";
+    return;
+  }
+  DCHECK_EQ(this, g_top_manager);
+
+  ProcessCallbacksNow();
+  g_top_manager = next_manager_;
+}
+
+// static
+void AtExitManager::RegisterCallback(AtExitCallbackType func, void* param) {
+  DCHECK(func);
+  RegisterTask(base::Bind(func, param));
+}
+
+// static
+void AtExitManager::RegisterTask(base::Closure task) {
+  if (!g_top_manager) {
+    NOTREACHED() << "Tried to RegisterCallback without an AtExitManager";
+    return;
+  }
+
+  AutoLock lock(g_top_manager->lock_);
+  g_top_manager->stack_.push(task);
+}
+
+// static
+void AtExitManager::ProcessCallbacksNow() {
+  if (!g_top_manager) {
+    NOTREACHED() << "Tried to ProcessCallbacksNow without an AtExitManager";
+    return;
+  }
+
+  AutoLock lock(g_top_manager->lock_);
+
+  while (!g_top_manager->stack_.empty()) {
+    base::Closure task = g_top_manager->stack_.top();
+    task.Run();
+    g_top_manager->stack_.pop();
+  }
+}
+
+AtExitManager::AtExitManager(bool shadow) : next_manager_(g_top_manager) {
+  DCHECK(shadow || !g_top_manager);
+  g_top_manager = this;
+}
+
+}  // namespace base
new file mode 100644
--- /dev/null
+++ b/security/sandbox/base/at_exit.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_AT_EXIT_H_
+#define BASE_AT_EXIT_H_
+
+#include <stack>
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/synchronization/lock.h"
+
+namespace base {
+
+// This class provides a facility similar to the CRT atexit(), except that
+// we control when the callbacks are executed. Under Windows for a DLL they
+// happen at a really bad time and under the loader lock. This facility is
+// mostly used by base::Singleton.
+//
+// The usage is simple. Early in the main() or WinMain() scope create an
+// AtExitManager object on the stack:
+// int main(...) {
+//    base::AtExitManager exit_manager;
+//
+// }
+// When the exit_manager object goes out of scope, all the registered
+// callbacks and singleton destructors will be called.
+
+class BASE_EXPORT AtExitManager {
+ public:
+  typedef void (*AtExitCallbackType)(void*);
+
+  AtExitManager();
+
+  // The dtor calls all the registered callbacks. Do not try to register more
+  // callbacks after this point.
+  ~AtExitManager();
+
+  // Registers the specified function to be called at exit. The prototype of
+  // the callback function is void func(void*).
+  static void RegisterCallback(AtExitCallbackType func, void* param);
+
+  // Registers the specified task to be called at exit.
+  static void RegisterTask(base::Closure task);
+
+  // Calls the functions registered with RegisterCallback in LIFO order. It
+  // is possible to register new callbacks after calling this function.
+  static void ProcessCallbacksNow();
+
+ protected:
+  // This constructor will allow this instance of AtExitManager to be created
+  // even if one already exists.  This should only be used for testing!
+  // AtExitManagers are kept on a global stack, and it will be removed during
+  // destruction.  This allows you to shadow another AtExitManager.
+  explicit AtExitManager(bool shadow);
+
+ private:
+  base::Lock lock_;
+  std::stack<base::Closure> stack_;
+  AtExitManager* next_manager_;  // Stack of managers to allow shadowing.
+
+  DISALLOW_COPY_AND_ASSIGN(AtExitManager);
+};
+
+#if defined(UNIT_TEST)
+class ShadowingAtExitManager : public AtExitManager {
+ public:
+  ShadowingAtExitManager() : AtExitManager(true) {}
+};
+#endif  // defined(UNIT_TEST)
+
+}  // namespace base
+
+#endif  // BASE_AT_EXIT_H_
new file mode 100644
--- /dev/null
+++ b/security/sandbox/base/atomic_ref_count.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is a low level implementation of atomic semantics for reference
+// counting.  Please use base/memory/ref_counted.h directly instead.
+//
+// The implementation includes annotations to avoid some false positives
+// when using data race detection tools.
+
+#ifndef BASE_ATOMIC_REF_COUNT_H_
+#define BASE_ATOMIC_REF_COUNT_H_
+
+#include "base/atomicops.h"
+#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
+
+namespace base {
+
+typedef subtle::Atomic32 AtomicRefCount;
+
+// Increment a reference count by "increment", which must exceed 0.
+inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr,
+                               AtomicRefCount increment) {
+  subtle::NoBarrier_AtomicIncrement(ptr, increment);
+}
+
+// Decrement a reference count by "decrement", which must exceed 0,
+// and return whether the result is non-zero.
+// Insert barriers to ensure that state written before the reference count
+// became zero will be visible to a thread that has just made the count zero.
+inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr,
+                               AtomicRefCount decrement) {
+  ANNOTATE_HAPPENS_BEFORE(ptr);
+  bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0);
+  if (!res) {
+    ANNOTATE_HAPPENS_AFTER(ptr);
+  }
+  return res;
+}
+
+// Increment a reference count by 1.
+inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) {
+  base::AtomicRefCountIncN(ptr, 1);
+}
+
+// Decrement a reference count by 1 and return whether the result is non-zero.
+// Insert barriers to ensure that state written before the reference count
+// became zero will be visible to a thread that has just made the count zero.
+inline bool AtomicRefCountDec(volatile AtomicRefCount *ptr) {
+  return base::AtomicRefCountDecN(ptr, 1);
+}
+
+// Return whether the reference count is one.  If the reference count is used
+// in the conventional way, a refrerence count of 1 implies that the current
+// thread owns the reference and no other thread shares it.  This call performs
+// the test for a reference count of one, and performs the memory barrier
+// needed for the owning thread to act on the object, knowing that it has
+// exclusive access to the object.
+inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) {
+  bool res = (subtle::Acquire_Load(ptr) == 1);
+  if (res) {
+    ANNOTATE_HAPPENS_AFTER(ptr);
+  }
+  return res;
+}
+
+// Return whether the reference count is zero.  With conventional object
+// referencing counting, the object will be destroyed, so the reference count
+// should never be zero.  Hence this is generally used for a debug check.
+inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) {
+  bool res = (subtle::Acquire_Load(ptr) == 0);
+  if (res) {
+    ANNOTATE_HAPPENS_AFTER(ptr);
+  }
+  return res;
+}
+
+}  // namespace base
+
+#endif  // BASE_ATOMIC_REF_COUNT_H_
new file mode 100644
--- /dev/null
+++ b/security/sandbox/base/atomic_sequence_num.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_ATOMIC_SEQUENCE_NUM_H_
+#define BASE_ATOMIC_SEQUENCE_NUM_H_
+
+#include "base/atomicops.h"
+#include "base/basictypes.h"
+
+namespace base {
+
+class AtomicSequenceNumber;
+
+// Static (POD) AtomicSequenceNumber that MUST be used in global scope (or
+// non-function scope) ONLY. This implementation does not generate any static
+// initializer.  Note that it does not implement any constructor which means
+// that its fields are not initialized except when it is stored in the global
+// data section (.data in ELF). If you want to allocate an atomic sequence
+// number on the stack (or heap), please use the AtomicSequenceNumber class
+// declared below.
+class StaticAtomicSequenceNumber {
+ public:
+  inline int GetNext() {
+    return static_cast<int>(
+        base::subtle::NoBarrier_AtomicIncrement(&seq_, 1) - 1);
+  }
+
+ private:
+  friend class AtomicSequenceNumber;
+
+  inline void Reset() {
+    base::subtle::Release_Store(&seq_, 0);
+  }
+
+  base::subtle::Atomic32 seq_;
+};
+
+// AtomicSequenceNumber that can be stored and used safely (i.e. its fields are
+// always initialized as opposed to StaticAtomicSequenceNumber declared above).
+// Please use StaticAtomicSequenceNumber if you want to declare an atomic
+// sequence number in the global scope.
+class AtomicSequenceNumber {
+ public:
+  AtomicSequenceNumber() {
+    seq_.Reset();
+  }
+
+  inline int GetNext() {
+    return seq_.GetNext();
+  }
+
+ private:
+  StaticAtomicSequenceNumber seq_;
+  DISALLOW_COPY_AND_ASSIGN(AtomicSequenceNumber);
+};
+
+}  // namespace base
+
+#endif  // BASE_ATOMIC_SEQUENCE_NUM_H_
new file mode 100644
--- /dev/null
+++ b/security/sandbox/base/atomicops.h
@@ -0,0 +1,164 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// For atomic operations on reference counts, see atomic_refcount.h.
+// For atomic operations on sequence numbers, see atomic_sequence_num.h.
+
+// The routines exported by this module are subtle.  If you use them, even if
+// you get the code right, it will depend on careful reasoning about atomicity
+// and memory ordering; it will be less readable, and harder to maintain.  If
+// you plan to use these routines, you should have a good reason, such as solid
+// evidence that performance would otherwise suffer, or there being no
+// alternative.  You should assume only properties explicitly guaranteed by the
+// specifications in this file.  You are almost certainly _not_ writing code
+// just for the x86; if you assume x86 semantics, x86 hardware bugs and
+// implementations on other archtectures will cause your code to break.  If you
+// do not know what you are doing, avoid these routines, and use a Mutex.
+//
+// It is incorrect to make direct assignments to/from an atomic variable.
+// You should use one of the Load or Store routines.  The NoBarrier
+// versions are provided when no barriers are needed:
+//   NoBarrier_Store()
+//   NoBarrier_Load()
+// Although there are currently no compiler enforcement, you are encouraged
+// to use these.
+//
+
+#ifndef BASE_ATOMICOPS_H_
+#define BASE_ATOMICOPS_H_
+
+#include "base/basictypes.h"
+#include "build/build_config.h"
+
+#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
+// windows.h #defines this (only on x64). This causes problems because the
+// public API also uses MemoryBarrier at the public name for this fence. So, on
+// X64, undef it, and call its documented
+// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
+// implementation directly.
+#undef MemoryBarrier
+#endif
+
+namespace base {
+namespace subtle {
+
+typedef int32 Atomic32;
+#ifdef ARCH_CPU_64_BITS
+// We need to be able to go between Atomic64 and AtomicWord implicitly.  This
+// means Atomic64 and AtomicWord should be the same type on 64-bit.
+#if defined(__ILP32__) || defined(OS_NACL)
+// NaCl's intptr_t is not actually 64-bits on 64-bit!
+// http://code.google.com/p/nativeclient/issues/detail?id=1162
+typedef int64_t Atomic64;
+#else
+typedef intptr_t Atomic64;
+#endif
+#endif
+
+// Use AtomicWord for a machine-sized pointer.  It will use the Atomic32 or
+// Atomic64 routines below, depending on your architecture.
+typedef intptr_t AtomicWord;
+
+// Atomically execute:
+//      result = *ptr;
+//      if (*ptr == old_value)
+//        *ptr = new_value;
+//      return result;
+//
+// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value".
+// Always return the old value of "*ptr"
+//
+// This routine implies no memory barriers.
+Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                  Atomic32 old_value,
+                                  Atomic32 new_value);
+
+// Atomically store new_value into *ptr, returning the previous value held in
+// *ptr.  This routine implies no memory barriers.
+Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value);
+
+// Atomically increment *ptr by "increment".  Returns the new value of
+// *ptr with the increment applied.  This routine implies no memory barriers.
+Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment);
+
+Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                 Atomic32 increment);
+
+// These following lower-level operations are typically useful only to people
+// implementing higher-level synchronization operations like spinlocks,
+// mutexes, and condition-variables.  They combine CompareAndSwap(), a load, or
+// a store with appropriate memory-ordering instructions.  "Acquire" operations
+// ensure that no later memory access can be reordered ahead of the operation.
+// "Release" operations ensure that no previous memory access can be reordered
+// after the operation.  "Barrier" operations have both "Acquire" and "Release"
+// semantics.   A MemoryBarrier() has "Barrier" semantics, but does no memory
+// access.
+Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                Atomic32 old_value,
+                                Atomic32 new_value);
+Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                Atomic32 old_value,
+                                Atomic32 new_value);
+
+void MemoryBarrier();
+void NoBarrier_Store(volatile Atomic32* ptr, Atomi