Merge m-c to fx-team
authorWes Kocher <wkocher@mozilla.com>
Mon, 06 Jan 2014 17:59:58 -0800
changeset 179269 b1732c430f6485a6d69739e8c2cbe35f79527550
parent 179268 7d4182792214622a7e2c8b3b333433cd016df5ca (current diff)
parent 179246 ce917d3dd7c8a100f43a645241d8feb711cd1dc6 (diff)
child 179270 641671b50e97ef438aa05f8edb4806f5f6dfbb20
push id462
push userraliiev@mozilla.com
push dateTue, 22 Apr 2014 00:22:30 +0000
treeherdermozilla-release@ac5db8c74ac0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "61b250647043dcbc616ee1514575ec55f8b8b223", 
+    "revision": "ac80bbe24c39a813ab65b98bb56dce2e42207b22", 
     "repo_path": "/integration/gaia-central"
 }
--- a/content/base/src/nsScriptLoader.cpp
+++ b/content/base/src/nsScriptLoader.cpp
@@ -719,17 +719,17 @@ class NotifyOffThreadScriptLoadCompleted
 {
   nsRefPtr<nsScriptLoadRequest> mRequest;
   nsRefPtr<nsScriptLoader> mLoader;
   void *mToken;
 
 public:
   NotifyOffThreadScriptLoadCompletedRunnable(nsScriptLoadRequest* aRequest,
                                              nsScriptLoader* aLoader)
-    : mRequest(aRequest), mLoader(aLoader), mToken(NULL)
+    : mRequest(aRequest), mLoader(aLoader), mToken(nullptr)
   {}
 
   void SetToken(void* aToken) {
     MOZ_ASSERT(aToken && !mToken);
     mToken = aToken;
   }
 
   NS_DECL_NSIRUNNABLE
--- a/content/html/content/public/HTMLMediaElement.h
+++ b/content/html/content/public/HTMLMediaElement.h
@@ -530,16 +530,22 @@ public:
   }
 
   void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly = false) {
     if (mTextTrackManager) {
       mTextTrackManager->RemoveTextTrack(aTextTrack, aPendingListOnly);
     }
   }
 
+  void AddCue(TextTrackCue& aCue) {
+    if (mTextTrackManager) {
+      mTextTrackManager->AddCue(aCue);
+    }
+  }
+
   /**
    * A public wrapper for FinishDecoderSetup()
    */
   nsresult FinishDecoderSetup(MediaDecoder* aDecoder, MediaResource* aStream) {
     return FinishDecoderSetup(aDecoder, aStream, nullptr, nullptr);
   }
 
 protected:
--- a/content/html/content/src/TextTrackManager.cpp
+++ b/content/html/content/src/TextTrackManager.cpp
@@ -7,24 +7,26 @@
 
 #include "mozilla/dom/TextTrackManager.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/dom/HTMLTrackElement.h"
 
 namespace mozilla {
 namespace dom {
 
-NS_IMPL_CYCLE_COLLECTION_2(TextTrackManager, mTextTracks, mPendingTextTracks)
+NS_IMPL_CYCLE_COLLECTION_3(TextTrackManager, mTextTracks,
+                           mPendingTextTracks, mNewCues)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(TextTrackManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(TextTrackManager, Release)
 
 TextTrackManager::TextTrackManager(HTMLMediaElement *aMediaElement)
   : mMediaElement(aMediaElement)
 {
   MOZ_COUNT_CTOR(TextTrackManager);
+  mNewCues = new TextTrackCueList(mMediaElement->OwnerDoc()->GetParentObject());
   mTextTracks = new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
   mPendingTextTracks =
     new TextTrackList(mMediaElement->OwnerDoc()->GetParentObject());
 }
 
 TextTrackManager::~TextTrackManager()
 {
   MOZ_COUNT_DTOR(TextTrackManager);
@@ -38,23 +40,37 @@ TextTrackManager::TextTracks() const
 
 already_AddRefed<TextTrack>
 TextTrackManager::AddTextTrack(TextTrackKind aKind, const nsAString& aLabel,
                                const nsAString& aLanguage)
 {
   nsRefPtr<TextTrack> ttrack =
     mTextTracks->AddTextTrack(mMediaElement, aKind, aLabel, aLanguage);
   ttrack->SetReadyState(HTMLTrackElement::LOADED);
+  AddCues(ttrack);
   return ttrack.forget();
 }
 
 void
 TextTrackManager::AddTextTrack(TextTrack* aTextTrack)
 {
   mTextTracks->AddTextTrack(aTextTrack);
+  AddCues(aTextTrack);
+}
+
+void
+TextTrackManager::AddCues(TextTrack* aTextTrack)
+{
+  TextTrackCueList* cueList = aTextTrack->GetCues();
+  if (cueList) {
+    bool dummy;
+    for (uint32_t i = 0; i < cueList->Length(); ++i) {
+      mNewCues->AddCue(*cueList->IndexedGetter(i, dummy));
+    }
+  }
 }
 
 void
 TextTrackManager::RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly)
 {
   mPendingTextTracks->RemoveTextTrack(aTextTrack);
   if (aPendingListOnly) {
     return;
@@ -71,16 +87,22 @@ TextTrackManager::DidSeek()
 
 void
 TextTrackManager::Update(double aTime)
 {
   mTextTracks->Update(aTime);
 }
 
 void
+TextTrackManager::AddCue(TextTrackCue& aCue)
+{
+  mNewCues->AddCue(aCue);
+}
+
+void
 TextTrackManager::PopulatePendingList()
 {
   uint32_t len = mTextTracks->Length();
   bool dummy;
   for (uint32_t index = 0; index < len; ++index) {
     TextTrack* ttrack = mTextTracks->IndexedGetter(index, dummy);
     if (ttrack && ttrack->Mode() != TextTrackMode::Disabled &&
         ttrack->ReadyState() == HTMLTrackElement::LOADING) {
--- a/content/html/content/src/TextTrackManager.h
+++ b/content/html/content/src/TextTrackManager.h
@@ -5,16 +5,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_TextTrackManager_h
 #define mozilla_dom_TextTrackManager_h
 
 #include "mozilla/dom/TextTrack.h"
 #include "mozilla/dom/TextTrackList.h"
+#include "mozilla/dom/TextTrackCueList.h"
 
 namespace mozilla {
 namespace dom {
 
 class HTMLMediaElement;
 
 class TextTrackManager
 {
@@ -28,30 +29,35 @@ public:
   TextTrackList* TextTracks() const;
   already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind,
                                            const nsAString& aLabel,
                                            const nsAString& aLanguage);
   void AddTextTrack(TextTrack* aTextTrack);
   void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly);
   void DidSeek();
 
+  void AddCue(TextTrackCue& aCue);
+  void AddCues(TextTrack* aTextTrack);
+
   // Update the display of cues on the video as per the current play back time
   // of aTime.
   void Update(double aTime);
 
   void PopulatePendingList();
 
 private:
   // The HTMLMediaElement that this TextTrackManager manages the TextTracks of.
   // This is a weak reference as the life time of TextTrackManager is dependent
   // on the HTMLMediaElement, so it should not be trying to hold the
   // HTMLMediaElement alive.
   HTMLMediaElement* mMediaElement;
   // List of the TextTrackManager's owning HTMLMediaElement's TextTracks.
   nsRefPtr<TextTrackList> mTextTracks;
   // List of text track objects awaiting loading.
   nsRefPtr<TextTrackList> mPendingTextTracks;
+  // List of newly introduced Text Track cues.
+  nsRefPtr<TextTrackCueList> mNewCues;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TextTrackManager_h
--- a/content/media/MediaRecorder.cpp
+++ b/content/media/MediaRecorder.cpp
@@ -105,16 +105,24 @@ class MediaRecorder::Session: public nsI
     ExtractRunnable(Session *aSession)
       : mSession(aSession) {}
 
     NS_IMETHODIMP Run()
     {
       MOZ_ASSERT(NS_GetCurrentThread() == mSession->mReadThread);
 
       mSession->Extract();
+      if (!mSession->mEncoder->IsShutdown()) {
+        NS_DispatchToCurrentThread(new ExtractRunnable(mSession));
+      } else {
+        // Flush out remainding encoded data.
+        NS_DispatchToMainThread(new PushBlobRunnable(mSession));
+        // Destroy this Session object in main thread.
+        NS_DispatchToMainThread(new DestroyRunnable(already_AddRefed<Session>(mSession)));
+      }
       return NS_OK;
     }
 
   private:
     Session* mSession;
   };
 
   // For Ensure recorder has tracks to record.
@@ -193,16 +201,17 @@ public:
   Session(MediaRecorder* aRecorder, int32_t aTimeSlice)
     : mRecorder(aRecorder),
       mTimeSlice(aTimeSlice)
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     AddRef();
     mEncodedBufferCache = new EncodedBufferCache(MAX_ALLOW_MEMORY_BUFFER);
+    mLastBlobTimeStamp = TimeStamp::Now();
   }
 
   // Only DestroyRunnable is allowed to delete Session object.
   virtual ~Session()
   {
     CleanupStreams();
   }
 
@@ -253,46 +262,37 @@ public:
 private:
 
   // Pull encoded meida data from MediaEncoder and put into EncodedBufferCache.
   // Destroy this session object in the end of this function.
   void Extract()
   {
     MOZ_ASSERT(NS_GetCurrentThread() == mReadThread);
 
-    TimeStamp lastBlobTimeStamp = TimeStamp::Now();
     // Whether push encoded data back to onDataAvailable automatically.
     const bool pushBlob = (mTimeSlice > 0) ? true : false;
 
-    do {
-      // Pull encoded media data from MediaEncoder
-      nsTArray<nsTArray<uint8_t> > encodedBuf;
-      nsString mimeType;
-      mEncoder->GetEncodedData(&encodedBuf, mimeType);
+    // Pull encoded media data from MediaEncoder
+    nsTArray<nsTArray<uint8_t> > encodedBuf;
+    nsString mimeType;
+    mEncoder->GetEncodedData(&encodedBuf, mimeType);
 
-      mRecorder->SetMimeType(mimeType);
-
-      // Append pulled data into cache buffer.
-      for (uint32_t i = 0; i < encodedBuf.Length(); i++) {
-        mEncodedBufferCache->AppendBuffer(encodedBuf[i]);
-      }
+    mRecorder->SetMimeType(mimeType);
 
-      if (pushBlob) {
-        if ((TimeStamp::Now() - lastBlobTimeStamp).ToMilliseconds() > mTimeSlice) {
-          NS_DispatchToMainThread(new PushBlobRunnable(this));
-          lastBlobTimeStamp = TimeStamp::Now();
-        }
+    // Append pulled data into cache buffer.
+    for (uint32_t i = 0; i < encodedBuf.Length(); i++) {
+      mEncodedBufferCache->AppendBuffer(encodedBuf[i]);
+    }
+
+    if (pushBlob) {
+      if ((TimeStamp::Now() - mLastBlobTimeStamp).ToMilliseconds() > mTimeSlice) {
+        NS_DispatchToMainThread(new PushBlobRunnable(this));
+        mLastBlobTimeStamp = TimeStamp::Now();
       }
-    } while (!mEncoder->IsShutdown());
-
-    // Flush out remainding encoded data.
-    NS_DispatchToMainThread(new PushBlobRunnable(this));
-
-    // Destroy this session object in main thread.
-    NS_DispatchToMainThread(new DestroyRunnable(already_AddRefed<Session>(this)));
+    }
   }
 
   // Bind media source with MediaEncoder to receive raw media data.
   void SetupStreams()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     // Create a Track Union Stream
@@ -393,16 +393,18 @@ private:
   nsRefPtr<MediaInputPort> mInputPort;
 
   // Runnable thread for read data from MediaEncode.
   nsCOMPtr<nsIThread> mReadThread;
   // MediaEncoder pipeline.
   nsRefPtr<MediaEncoder> mEncoder;
   // A buffer to cache encoded meda data.
   nsAutoPtr<EncodedBufferCache> mEncodedBufferCache;
+  // Timestamp of the last fired dataavailable event.
+  TimeStamp mLastBlobTimeStamp;
   // The interval of passing encoded data from EncodedBufferCache to onDataAvailable
   // handler. "mTimeSlice < 0" means Session object does not push encoded data to
   // onDataAvailable, instead, it passive wait the client side pull encoded data
   // by calling requestData API.
   const int32_t mTimeSlice;
 };
 
 NS_IMPL_ISUPPORTS1(MediaRecorder::Session, nsIObserver)
--- a/content/media/RtspMediaResource.cpp
+++ b/content/media/RtspMediaResource.cpp
@@ -472,16 +472,20 @@ RtspMediaResource::OnConnected(uint8_t a
     trackMeta->GetHeight(&h);
     slotSize = clamped((int32_t)(w * h), BUFFER_SLOT_DEFAULT_SIZE,
                        BUFFER_SLOT_MAX_SIZE);
     mTrackBuffer.AppendElement(new RtspTrackBuffer(rtspTrackId.get(),
                                                    i, slotSize));
     mTrackBuffer[i]->Start();
   }
 
+  if (!mDecoder) {
+    return NS_ERROR_FAILURE;
+  }
+
   // If the duration is 0, imply the stream is live stream.
   if (duration) {
     // Not live stream.
     mRealTime = false;
     bool seekable = true;
     mDecoder->SetInfinite(false);
     mDecoder->SetTransportSeekable(seekable);
     mDecoder->SetDuration(duration);
@@ -522,16 +526,23 @@ RtspMediaResource::OnDisconnected(uint8_
 {
   NS_ASSERTION(NS_IsMainThread(), "Don't call on non-main thread");
 
   for (uint32_t i = 0 ; i < mTrackBuffer.Length(); ++i) {
     mTrackBuffer[i]->Stop();
     mTrackBuffer[i]->Reset();
   }
 
+  // If mDecoder is null pointer, it means this OnDisconnected event is
+  // triggered when media element was destroyed and mDecoder was already
+  // shutdown.
+  if (!mDecoder) {
+    return NS_OK;
+  }
+
   if (aReason == NS_ERROR_NOT_INITIALIZED ||
       aReason == NS_ERROR_CONNECTION_REFUSED ||
       aReason == NS_ERROR_NOT_CONNECTED) {
 
     RTSPMLOG("Error in OnDisconnected 0x%x", aReason);
 
     mDecoder->NetworkError();
     return NS_OK;
@@ -575,16 +586,22 @@ nsresult RtspMediaResource::Open(nsIStre
 {
   return NS_OK;
 }
 
 nsresult RtspMediaResource::Close()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   mMediaStreamController->Stop();
+  // Since mDecoder is not an nsCOMPtr in BaseMediaResource, we have to
+  // explicitly set it as null pointer in order to prevent misuse from this
+  // object (RtspMediaResource).
+  if (mDecoder) {
+    mDecoder = nullptr;
+  }
   return NS_OK;
 }
 
 already_AddRefed<nsIPrincipal> RtspMediaResource::GetCurrentPrincipal()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   nsCOMPtr<nsIPrincipal> principal;
--- a/content/media/TextTrack.cpp
+++ b/content/media/TextTrack.cpp
@@ -96,16 +96,17 @@ TextTrack::SetMode(TextTrackMode aValue)
     }
   }
 }
 
 void
 TextTrack::AddCue(TextTrackCue& aCue)
 {
   mCueList->AddCue(aCue);
+  mMediaElement->AddCue(aCue);
   SetDirty();
 }
 
 void
 TextTrack::RemoveCue(TextTrackCue& aCue, ErrorResult& aRv)
 {
   mCueList->RemoveCue(aCue, aRv);
   SetDirty();
--- a/content/media/fmp4/wmf/MFTDecoder.cpp
+++ b/content/media/fmp4/wmf/MFTDecoder.cpp
@@ -31,17 +31,17 @@ MFTDecoder::~MFTDecoder()
 }
 
 HRESULT
 MFTDecoder::Create(const GUID& aMFTClsID)
 {
   // Create the IMFTransform to do the decoding.
   HRESULT hr;
   hr = CoCreateInstance(aMFTClsID,
-                        NULL,
+                        nullptr,
                         CLSCTX_INPROC_SERVER,
                         IID_IMFTransform,
                         reinterpret_cast<void**>(static_cast<IMFTransform**>(byRef(mDecoder))));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   return S_OK;
 }
 
--- a/content/media/fmp4/wmf/WMFVideoDecoder.cpp
+++ b/content/media/fmp4/wmf/WMFVideoDecoder.cpp
@@ -240,17 +240,17 @@ WMFVideoDecoder::CreateBasicVideoFrame(I
   BYTE* data = nullptr;
   LONG stride = 0;
   RefPtr<IMF2DBuffer> twoDBuffer;
   hr = buffer->QueryInterface(static_cast<IMF2DBuffer**>(byRef(twoDBuffer)));
   if (SUCCEEDED(hr)) {
     hr = twoDBuffer->Lock2D(&data, &stride);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   } else {
-    hr = buffer->Lock(&data, NULL, NULL);
+    hr = buffer->Lock(&data, nullptr, nullptr);
     NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
     stride = mVideoStride;
   }
 
   // YV12, planar format: [YYYY....][VVVV....][UUUU....]
   // i.e., Y, then V, then U.
   VideoData::YCbCrBuffer b;
 
--- a/dom/apps/src/Webapps.js
+++ b/dom/apps/src/Webapps.js
@@ -290,16 +290,25 @@ let manifestCache = {
       if (aInnerWindowID in winObjs) {
         delete winObjs[aInnerWindowID];
       }
 
       if (Object.keys(winObjs).length == 0) {
         delete this._cache[aManifestURL];
       }
     }
+  },
+
+  observe: function(aSubject, aTopic, aData) {
+    // Clear the cache on memory pressure.
+    this._cache = { };
+  },
+
+  init: function() {
+    Services.obs.addObserver(this, "memory-pressure", false);
   }
 };
 
 function createApplicationObject(aWindow, aApp) {
   let app = Cc["@mozilla.org/webapps/application;1"].createInstance(Ci.mozIDOMApplication);
   app.wrappedJSObject.init(aWindow, aApp);
   return app;
 }
@@ -796,10 +805,12 @@ WebappsApplicationMgmt.prototype = {
 
   classInfo: XPCOMUtils.generateCI({classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
                                     contractID: "@mozilla.org/webapps/application-mgmt;1",
                                     interfaces: [Ci.mozIDOMApplicationMgmt],
                                     flags: Ci.nsIClassInfo.DOM_OBJECT,
                                     classDescription: "Webapps Application Mgmt"})
 }
 
+manifestCache.init();
+
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsRegistry,
                                                      WebappsApplication]);
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -150,16 +150,17 @@ this.DOMApplicationRegistry = {
 
     this.messages.forEach((function(msgName) {
       ppmm.addMessageListener(msgName, this);
     }).bind(this));
 
     cpmm.addMessageListener("Activities:Register:OK", this);
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
+    Services.obs.addObserver(this, "memory-pressure", false);
 
     AppDownloadManager.registerCancelFunction(this.cancelDownload.bind(this));
 
     this.appsFile = FileUtils.getFile(DIRECTORY_NAME,
                                       ["webapps", "webapps.json"], true);
 
     this.loadAndUpdateApps();
   },
@@ -956,16 +957,19 @@ this.DOMApplicationRegistry = {
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == "xpcom-shutdown") {
       this.messages.forEach((function(msgName) {
         ppmm.removeMessageListener(msgName, this);
       }).bind(this));
       Services.obs.removeObserver(this, "xpcom-shutdown");
       cpmm = null;
       ppmm = null;
+    } else if (aTopic == "memory-pressure") {
+      // Clear the manifest cache on memory pressure.
+      this._manifestCache = {};
     }
   },
 
   _loadJSONAsync: function(aFile, aCallback) {
     try {
       let channel = NetUtil.newChannel(aFile);
       channel.contentType = "application/json";
       NetUtil.asyncFetch(channel, function(aStream, aResult) {
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -456,17 +456,17 @@ MainProcessRunnable::OpenFileOnIOThread(
 
   rv = path->Append(NS_LITERAL_STRING(ASMJSCACHE_FILE_NAME));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mQuotaObject = qm->GetQuotaObject(quota::PERSISTENCE_TYPE_TEMPORARY,
                                     mGroup, mOrigin, path);
   NS_ENSURE_STATE(mQuotaObject);
 
-  int openFlags;
+  int32_t openFlags;
   if (mOpenMode == eOpenForRead) {
     rv = path->GetFileSize(&mFileSize);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     openFlags = PR_RDONLY | nsIFile::OS_READAHEAD;
   } else {
--- a/dom/bluetooth/bluedroid/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.cpp
@@ -421,17 +421,17 @@ DroidSocketImpl::ReadMsg(int aFd, void *
     return 0;
   }
 
   NS_ENSURE_FALSE(ret < 0, -1);
   NS_ENSURE_FALSE(msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE), -1);
 
   // Extract client fd from message header
   for (struct cmsghdr *cmsgptr = CMSG_FIRSTHDR(&msg);
-       cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
+       cmsgptr != nullptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
     if (cmsgptr->cmsg_level != SOL_SOCKET) {
       continue;
     }
     if (cmsgptr->cmsg_type == SCM_RIGHTS) {
       int *pDescriptors = (int *)CMSG_DATA(cmsgptr);
       // Overwrite fd with client fd
       mFd.reset(pDescriptors[0]);
       break;
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -19,16 +19,17 @@ include URIParams;
 
 
 using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
 using struct mozilla::gfx::Matrix from "mozilla/gfx/Matrix.h";
 using struct gfxSize from "gfxPoint.h";
 using CSSRect from "Units.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
 using struct mozilla::layers::ScrollableLayerGuid from "FrameMetrics.h";
+using struct mozilla::layers::ZoomConstraints from "FrameMetrics.h";
 using FrameMetrics::ViewID from "FrameMetrics.h";
 using mozilla::layout::ScrollingBehavior from "mozilla/layout/RenderFrameUtils.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
 using nscolor from "nsColor.h";
 using class mozilla::WidgetCompositionEvent from "ipc/nsGUIEventIPC.h";
 using struct nsIMEUpdatePreference from "nsIWidget.h";
 using struct nsIntPoint from "nsPoint.h";
@@ -296,17 +297,17 @@ parent:
     ContentReceivedTouch(ScrollableLayerGuid aGuid, bool aPreventDefault);
 
     /**
      * Updates the zoom constraints for a scrollable frame in this tab.
      * The zoom controller code lives on the parent side and so this allows it to
      * have up-to-date zoom constraints.
      */
     UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId, bool aIsRoot,
-                          bool aAllowZoom, CSSToScreenScale aMinZoom, CSSToScreenScale aMaxZoom);
+                          ZoomConstraints aConstraints);
 
     __delete__();
 
 child:
     /**
      * Notify the remote browser that it has been Show()n on this
      * side, with the given |visibleRect|.  This message is expected
      * to trigger creation of the remote browser's "widget".
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -516,22 +516,24 @@ TabChild::HandlePossibleViewportChange()
 
   nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
 
   nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, mInnerSize);
   uint32_t presShellId;
   ViewID viewId;
   if (APZCCallbackHelper::GetScrollIdentifiers(document->GetDocumentElement(),
                                                &presShellId, &viewId)) {
+    ZoomConstraints constraints(
+      viewportInfo.IsZoomAllowed(),
+      viewportInfo.GetMinZoom(),
+      viewportInfo.GetMaxZoom());
     SendUpdateZoomConstraints(presShellId,
                               viewId,
                               /* isRoot = */ true,
-                              viewportInfo.IsZoomAllowed(),
-                              viewportInfo.GetMinZoom(),
-                              viewportInfo.GetMaxZoom());
+                              constraints);
   }
 
 
   float screenW = mInnerSize.width;
   float screenH = mInnerSize.height;
   CSSSize viewport(viewportInfo.GetSize());
 
   // We're not being displayed in any way; don't bother doing anything because
@@ -1771,17 +1773,17 @@ TabChild::UpdateTapState(const WidgetTou
       return;
     }
     if (aStatus == nsEventStatus_eConsumeNoDefault ||
         nsIPresShell::gPreventMouseEvents ||
         aEvent.mFlags.mMultipleActionsPrevented) {
       return;
     }
 
-    Touch* touch = static_cast<Touch*>(aEvent.touches[0].get());
+    Touch* touch = aEvent.touches[0];
     mGestureDownPoint = LayoutDevicePoint(touch->mRefPoint.x, touch->mRefPoint.y);
     mActivePointerId = touch->mIdentifier;
     if (sClickHoldContextMenusEnabled) {
       MOZ_ASSERT(!mTapHoldTimer);
       mTapHoldTimer = NewRunnableMethod(this,
                                         &TabChild::FireContextMenuEvent);
       MessageLoop::current()->PostDelayedTask(FROM_HERE, mTapHoldTimer,
                                               sContextMenuDelayMs);
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1708,22 +1708,20 @@ TabParent::RecvZoomToRect(const uint32_t
   }
   return true;
 }
 
 bool
 TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
                                      const ViewID& aViewId,
                                      const bool& aIsRoot,
-                                     const bool& aAllowZoom,
-                                     const CSSToScreenScale& aMinZoom,
-                                     const CSSToScreenScale& aMaxZoom)
+                                     const ZoomConstraints& aConstraints)
 {
   if (RenderFrameParent* rfp = GetRenderFrame()) {
-    rfp->UpdateZoomConstraints(aPresShellId, aViewId, aIsRoot, aAllowZoom, aMinZoom, aMaxZoom);
+    rfp->UpdateZoomConstraints(aPresShellId, aViewId, aIsRoot, aConstraints);
   }
   return true;
 }
 
 bool
 TabParent::RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
                                     const bool& aPreventDefault)
 {
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -163,19 +163,17 @@ public:
     virtual bool RecvGetDefaultScale(double* aValue);
     virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue);
     virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
                                 const ViewID& aViewId,
                                 const CSSRect& aRect);
     virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
                                            const ViewID& aViewId,
                                            const bool& aIsRoot,
-                                           const bool& aAllowZoom,
-                                           const CSSToScreenScale& aMinZoom,
-                                           const CSSToScreenScale& aMaxZoom);
+                                           const ZoomConstraints& aConstraints);
     virtual bool RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
                                           const bool& aPreventDefault);
     virtual PContentDialogParent* AllocPContentDialogParent(const uint32_t& aType,
                                                             const nsCString& aName,
                                                             const nsCString& aFeatures,
                                                             const InfallibleTArray<int>& aIntParams,
                                                             const InfallibleTArray<nsString>& aStringParams);
     virtual bool DeallocPContentDialogParent(PContentDialogParent* aDialog)
--- a/dom/wappush/src/gonk/WapPushManager.js
+++ b/dom/wappush/src/gonk/WapPushManager.js
@@ -106,17 +106,17 @@ this.WapPushManager = {
                contentType === "application/vnd.wap.connectivity-wbxml") {
       // Apply HMAC authentication on WBXML encoded CP message.
       if (contentType === "application/vnd.wap.connectivity-wbxml") {
         let params = options.headers["content-type"].params;
         let sec = params && params.sec;
         let mac = params && params.mac;
         authInfo = CP.Authenticator.check(data.array.subarray(data.offset),
                                           sec, mac, function getNetworkPin() {
-          let imsi = gRIL.getRadioInterface(0).rilContext.imsi;
+          let imsi = gRIL.getRadioInterface(options.serviceId).rilContext.imsi;
           return CP.Authenticator.formatImsi(imsi);
         });
       }
 
       msg = CP.PduHelper.parse(data, contentType);
     } else {
       // Unsupported type, provide raw data.
       msg = {
@@ -131,17 +131,18 @@ this.WapPushManager = {
     if (parsedSender && parsedSender.internationalNumber) {
       sender = parsedSender.internationalNumber;
     }
 
     gSystemMessenger.broadcastMessage("wappush-received", {
       sender:         sender,
       contentType:    msg.contentType,
       content:        msg.content,
-      authInfo:       authInfo
+      authInfo:       authInfo,
+      serviceId:      options.serviceId
     });
   },
 
   /**
    * @param array
    *        A Uint8Array or an octet array representing raw PDU data.
    * @param length
    *        Length of the array.
--- a/gfx/2d/BaseRect.h
+++ b/gfx/2d/BaseRect.h
@@ -436,28 +436,28 @@ struct BaseRect {
    */
   Point ClampPoint(const Point& aPoint) const
   {
     return Point(std::max(x, std::min(XMost(), aPoint.x)),
                  std::max(y, std::min(YMost(), aPoint.y)));
   }
 
   /**
-   * Clamp aRect to this rectangle. This returns aRect after it is forced
-   * inside the bounds of this rectangle. It will attempt to retain the size
-   * but will shrink the dimensions that don't fit.
+   * Clamp this rectangle to be inside aRect. The function returns a copy of
+   * this rect after it is forced inside the bounds of aRect. It will attempt to
+   * retain the size but will shrink the dimensions that don't fit.
    */
-  Sub ClampRect(const Sub& aRect) const
+  Sub ForceInside(const Sub& aRect) const
   {
     Sub rect(std::max(aRect.x, x),
              std::max(aRect.y, y),
              std::min(aRect.width, width),
              std::min(aRect.height, height));
-    rect.x = std::min(rect.XMost(), XMost()) - rect.width;
-    rect.y = std::min(rect.YMost(), YMost()) - rect.height;
+    rect.x = std::min(rect.XMost(), aRect.XMost()) - rect.width;
+    rect.y = std::min(rect.YMost(), aRect.YMost()) - rect.height;
     return rect;
   }
 
 private:
   // Do not use the default operator== or operator!= !
   // Use IsEqualEdges or IsEqualInterior explicitly.
   bool operator==(const Sub& aRect) const { return false; }
   bool operator!=(const Sub& aRect) const { return false; }
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -746,17 +746,19 @@ DrawTargetSkia::CopySurface(SourceSurfac
 
   mCanvas->drawBitmapRect(bitmap, &source, dest, &paint);
   mCanvas->restore();
 }
 
 bool
 DrawTargetSkia::Init(const IntSize &aSize, SurfaceFormat aFormat)
 {
-  SkAutoTUnref<SkDevice> device(new SkDevice(GfxFormatToSkiaConfig(aFormat), aSize.width, aSize.height));
+  SkAutoTUnref<SkDevice> device(new SkDevice(GfxFormatToSkiaConfig(aFormat),
+                                             aSize.width, aSize.height,
+                                             aFormat == FORMAT_B8G8R8X8));
 
   SkBitmap bitmap = device->accessBitmap(true);
   if (!bitmap.allocPixels()) {
     return false;
   }
 
   bitmap.eraseARGB(0, 0, 0, 0);
 
--- a/gfx/ipc/GfxMessageUtils.h
+++ b/gfx/ipc/GfxMessageUtils.h
@@ -681,16 +681,36 @@ struct ParamTraits<mozilla::layers::Scro
   {
     return (ReadParam(aMsg, aIter, &aResult->mLayersId) &&
             ReadParam(aMsg, aIter, &aResult->mPresShellId) &&
             ReadParam(aMsg, aIter, &aResult->mScrollId));
   }
 };
 
 template <>
+struct ParamTraits<mozilla::layers::ZoomConstraints>
+{
+  typedef mozilla::layers::ZoomConstraints paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mAllowZoom);
+    WriteParam(aMsg, aParam.mMinZoom);
+    WriteParam(aMsg, aParam.mMaxZoom);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return (ReadParam(aMsg, aIter, &aResult->mAllowZoom) &&
+            ReadParam(aMsg, aIter, &aResult->mMinZoom) &&
+            ReadParam(aMsg, aIter, &aResult->mMaxZoom));
+  }
+};
+
+template <>
 struct ParamTraits<mozilla::layers::EventRegions>
 {
   typedef mozilla::layers::EventRegions paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mHitRegion);
     WriteParam(aMsg, aParam.mDispatchToContentHitRegion);
--- a/gfx/layers/Effects.h
+++ b/gfx/layers/Effects.h
@@ -184,17 +184,17 @@ struct EffectSolidColor : public Effect
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
   gfx::Color mColor;
 };
 
 struct EffectChain
 {
-  EffectChain() : mLayerRef(NULL) {}
+  EffectChain() : mLayerRef(nullptr) {}
   explicit EffectChain(void* aLayerRef) : mLayerRef(aLayerRef) {}
 
   RefPtr<Effect> mPrimaryEffect;
   RefPtr<Effect> mSecondaryEffects[EFFECT_MAX_SECONDARY];
   void* mLayerRef; //!< For LayerScope logging
 };
 
 /**
--- a/gfx/layers/FrameMetrics.h
+++ b/gfx/layers/FrameMetrics.h
@@ -344,12 +344,51 @@ struct ScrollableLayerGuid {
   }
 
   bool operator!=(const ScrollableLayerGuid& other) const
   {
     return !(*this == other);
   }
 };
 
+struct ZoomConstraints {
+  bool mAllowZoom;
+  CSSToScreenScale mMinZoom;
+  CSSToScreenScale mMaxZoom;
+
+  ZoomConstraints()
+    : mAllowZoom(true)
+  {
+    MOZ_COUNT_CTOR(ZoomConstraints);
+  }
+
+  ZoomConstraints(bool aAllowZoom,
+                  const CSSToScreenScale& aMinZoom,
+                  const CSSToScreenScale& aMaxZoom)
+    : mAllowZoom(aAllowZoom)
+    , mMinZoom(aMinZoom)
+    , mMaxZoom(aMaxZoom)
+  {
+    MOZ_COUNT_CTOR(ZoomConstraints);
+  }
+
+  ~ZoomConstraints()
+  {
+    MOZ_COUNT_DTOR(ZoomConstraints);
+  }
+
+  bool operator==(const ZoomConstraints& other) const
+  {
+    return mAllowZoom == other.mAllowZoom
+        && mMinZoom == other.mMinZoom
+        && mMaxZoom == other.mMaxZoom;
+  }
+
+  bool operator!=(const ZoomConstraints& other) const
+  {
+    return !(*this == other);
+  }
+};
+
 }
 }
 
 #endif /* GFX_FRAMEMETRICS_H */
--- a/gfx/layers/composite/APZCTreeManager.cpp
+++ b/gfx/layers/composite/APZCTreeManager.cpp
@@ -186,32 +186,30 @@ APZCTreeManager::UpdatePanZoomController
         } else {
           mRootApzc = apzc;
         }
 
         // Let this apzc be the parent of other controllers when we recurse downwards
         aParent = apzc;
 
         if (newApzc) {
-          bool allowZoom;
-          CSSToScreenScale minZoom, maxZoom;
           if (apzc->IsRootForLayersId()) {
             // If we just created a new apzc that is the root for its layers ID, then
             // we need to update its zoom constraints which might have arrived before this
             // was created
-            if (state->mController->GetRootZoomConstraints(&allowZoom, &minZoom, &maxZoom)) {
-              apzc->UpdateZoomConstraints(allowZoom, minZoom, maxZoom);
+            ZoomConstraints constraints;
+            if (state->mController->GetRootZoomConstraints(&constraints)) {
+              apzc->UpdateZoomConstraints(constraints);
             }
           } else {
             // For an apzc that is not the root for its layers ID, we give it the
             // same zoom constraints as its parent. This ensures that if e.g.
             // user-scalable=no was specified, none of the APZCs allow double-tap
             // to zoom.
-            apzc->GetParent()->GetZoomConstraints(&allowZoom, &minZoom, &maxZoom);
-            apzc->UpdateZoomConstraints(allowZoom, minZoom, maxZoom);
+            apzc->UpdateZoomConstraints(apzc->GetParent()->GetZoomConstraints());
           }
         }
       }
     }
 
     container->SetAsyncPanZoomController(apzc);
   }
 
@@ -571,42 +569,38 @@ APZCTreeManager::ContentReceivedTouch(co
   nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
   if (apzc) {
     apzc->ContentReceivedTouch(aPreventDefault);
   }
 }
 
 void
 APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
-                                       bool aAllowZoom,
-                                       const CSSToScreenScale& aMinScale,
-                                       const CSSToScreenScale& aMaxScale)
+                                       const ZoomConstraints& aConstraints)
 {
   nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
   // For a given layers id, non-root APZCs inherit the zoom constraints
   // of their root.
   if (apzc && apzc->IsRootForLayersId()) {
     MonitorAutoLock lock(mTreeLock);
-    UpdateZoomConstraintsRecursively(apzc.get(), aAllowZoom, aMinScale, aMaxScale);
+    UpdateZoomConstraintsRecursively(apzc.get(), aConstraints);
   }
 }
 
 void
 APZCTreeManager::UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
-                                                  bool aAllowZoom,
-                                                  const CSSToScreenScale& aMinScale,
-                                                  const CSSToScreenScale& aMaxScale)
+                                                  const ZoomConstraints& aConstraints)
 {
   mTreeLock.AssertCurrentThreadOwns();
 
-  aApzc->UpdateZoomConstraints(aAllowZoom, aMinScale, aMaxScale);
+  aApzc->UpdateZoomConstraints(aConstraints);
   for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
     // We can have subtrees with their own layers id - leave those alone.
     if (!child->IsRootForLayersId()) {
-      UpdateZoomConstraintsRecursively(child, aAllowZoom, aMinScale, aMaxScale);
+      UpdateZoomConstraintsRecursively(child, aConstraints);
     }
   }
 }
 
 void
 APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid)
 {
   nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
--- a/gfx/layers/composite/APZCTreeManager.h
+++ b/gfx/layers/composite/APZCTreeManager.h
@@ -148,23 +148,19 @@ public:
    * that have come in. If |aPreventDefault| is true, any touch events in the
    * queue will be discarded.
    */
   void ContentReceivedTouch(const ScrollableLayerGuid& aGuid,
                             bool aPreventDefault);
 
   /**
    * Updates any zoom constraints contained in the <meta name="viewport"> tag.
-   * We try to obey everything it asks us elsewhere, but here we only handle
-   * minimum-scale, maximum-scale, and user-scalable.
    */
   void UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
-                             bool aAllowZoom,
-                             const CSSToScreenScale& aMinScale,
-                             const CSSToScreenScale& aMaxScale);
+                             const ZoomConstraints& aConstraints);
 
   /**
    * Cancels any currently running animation. Note that all this does is set the
    * state of the AsyncPanZoomController back to NOTHING, but it is the
    * animation's responsibility to check this before advancing.
    */
   void CancelAnimation(const ScrollableLayerGuid &aGuid);
 
@@ -260,19 +256,17 @@ private:
   AsyncPanZoomController* GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& aHitTestPoint);
   already_AddRefed<AsyncPanZoomController> CommonAncestor(AsyncPanZoomController* aApzc1, AsyncPanZoomController* aApzc2);
   already_AddRefed<AsyncPanZoomController> RootAPZCForLayersId(AsyncPanZoomController* aApzc);
   already_AddRefed<AsyncPanZoomController> GetTouchInputBlockAPZC(const WidgetTouchEvent& aEvent, ScreenPoint aPoint);
   nsEventStatus ProcessTouchEvent(const WidgetTouchEvent& touchEvent, ScrollableLayerGuid* aOutTargetGuid, WidgetTouchEvent* aOutEvent);
   nsEventStatus ProcessMouseEvent(const WidgetMouseEvent& mouseEvent, ScrollableLayerGuid* aOutTargetGuid, WidgetMouseEvent* aOutEvent);
   nsEventStatus ProcessEvent(const WidgetInputEvent& inputEvent, ScrollableLayerGuid* aOutTargetGuid, WidgetInputEvent* aOutEvent);
   void UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
-                                        bool aAllowZoom,
-                                        const CSSToScreenScale& aMinScale,
-                                        const CSSToScreenScale& aMaxScale);
+                                        const ZoomConstraints& aConstraints);
 
   /**
    * Recursive helper function to build the APZC tree. The tree of APZC instances has
    * the same shape as the layer tree, but excludes all the layers that are not scrollable.
    * Note that this means APZCs corresponding to layers at different depths in the tree
    * may end up becoming siblings. It also means that the "root" APZC may have siblings.
    * This function walks the layer tree backwards through siblings and constructs the APZC
    * tree also as a last-child-prev-sibling tree because that simplifies the hit detection
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 20; 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/. */
 
 #ifndef MOZILLA_GFX_IMAGEHOST_H
 #define MOZILLA_GFX_IMAGEHOST_H
 
-#include <stdio.h>                      // for FILE, NULL
+#include <stdio.h>                      // for FILE
 #include "CompositableHost.h"           // for CompositableHost
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/RefPtr.h"             // for RefPtr
 #include "mozilla/gfx/Point.h"          // for Point
 #include "mozilla/gfx/Rect.h"           // for Rect
 #include "mozilla/gfx/Types.h"          // for Filter
 #include "mozilla/layers/CompositorTypes.h"  // for TextureInfo, etc
 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
@@ -65,19 +65,19 @@ public:
     mHasPictureRect = true;
   }
 
   virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
 
   virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
 
 #ifdef MOZ_DUMP_PAINTING
-  virtual void Dump(FILE* aFile=NULL,
-                    const char* aPrefix="",
-                    bool aDumpHtml=false) MOZ_OVERRIDE;
+  virtual void Dump(FILE* aFile = nullptr,
+                    const char* aPrefix = "",
+                    bool aDumpHtml = false) MOZ_OVERRIDE;
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
 #endif
 
 protected:
 
   RefPtr<TextureHost> mFrontBuffer;
   nsIntRect mPictureRect;
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -93,17 +93,17 @@ CompositorD3D9::CreateRenderTarget(const
   if (!mDeviceManager) {
     return nullptr;
   }
 
   RefPtr<IDirect3DTexture9> texture;
   HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
                                        D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
                                        D3DPOOL_DEFAULT, byRef(texture),
-                                       NULL);
+                                       nullptr);
   if (FAILED(hr)) {
     ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTarget: Failed to create texture"),
                   hr);
     return nullptr;
   }
 
   RefPtr<CompositingRenderTargetD3D9> rt =
     new CompositingRenderTargetD3D9(texture, aInit, aRect);
@@ -119,17 +119,17 @@ CompositorD3D9::CreateRenderTargetFromSo
   if (!mDeviceManager) {
     return nullptr;
   }
 
   RefPtr<IDirect3DTexture9> texture;
   HRESULT hr = device()->CreateTexture(aRect.width, aRect.height, 1,
                                        D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
                                        D3DPOOL_DEFAULT, byRef(texture),
-                                       NULL);
+                                       nullptr);
   if (FAILED(hr)) {
     ReportFailure(NS_LITERAL_CSTRING("CompositorD3D9::CreateRenderTargetFromSource: Failed to create texture"),
                   hr);
     return nullptr;
   }
 
   if (aSource) {
     nsRefPtr<IDirect3DSurface9> sourceSurface =
@@ -404,17 +404,17 @@ CompositorD3D9::DrawQuad(const gfx::Rect
       maskTexture = mDeviceManager->SetShaderMode(DeviceManagerD3D9::COMPONENTLAYERPASS2, maskType);
       d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
       d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
       d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
 
       // Restore defaults
       d3d9Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
       d3d9Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
-      d3d9Device->SetTexture(1, NULL);
+      d3d9Device->SetTexture(1, nullptr);
     }
     return;
   default:
     NS_WARNING("Unknown shader type");
     return;
   }
 
   SetMask(aEffectChain, maskTexture);
@@ -565,17 +565,17 @@ CompositorD3D9::BeginFrame(const nsIntRe
                            Rect *aRenderBoundsOut)
 {
   MOZ_ASSERT(mDeviceManager && mSwapChain);
 
   mDeviceManager->SetupRenderState();
 
   EnsureSize();
 
-  device()->Clear(0, NULL, D3DCLEAR_TARGET, 0x00000000, 0, 0);
+  device()->Clear(0, nullptr, D3DCLEAR_TARGET, 0x00000000, 0, 0);
   device()->BeginScene();
 
   if (aClipRectOut) {
     *aClipRectOut = Rect(0, 0, mSize.width, mSize.height);
   }
   if (aRenderBoundsOut) {
     *aRenderBoundsOut = Rect(0, 0, mSize.width, mSize.height);
   }
@@ -682,22 +682,22 @@ CompositorD3D9::PaintToTarget()
   nsRefPtr<IDirect3DSurface9> destSurf;
   device()->GetRenderTarget(0, getter_AddRefs(backBuff));
 
   D3DSURFACE_DESC desc;
   backBuff->GetDesc(&desc);
 
   device()->CreateOffscreenPlainSurface(desc.Width, desc.Height,
                                         D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
-                                        getter_AddRefs(destSurf), NULL);
+                                        getter_AddRefs(destSurf), nullptr);
 
   device()->GetRenderTargetData(backBuff, destSurf);
 
   D3DLOCKED_RECT rect;
-  destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
+  destSurf->LockRect(&rect, nullptr, D3DLOCK_READONLY);
   RefPtr<DataSourceSurface> sourceSurface =
     Factory::CreateWrappingDataSourceSurface((uint8_t*)rect.pBits,
                                              rect.Pitch,
                                              IntSize(desc.Width, desc.Height),
                                              FORMAT_B8G8R8A8);
   mTarget->CopySurface(sourceSurface,
                        IntRect(0, 0, desc.Width, desc.Height),
                        IntPoint());
--- a/gfx/layers/d3d9/CompositorD3D9.h
+++ b/gfx/layers/d3d9/CompositorD3D9.h
@@ -154,17 +154,17 @@ private:
 
   /* Swap chain associated with this compositor */
   nsRefPtr<SwapChainD3D9> mSwapChain;
 
   /* Widget associated with this layer manager */
   nsIWidget *mWidget;
 
   /*
-   * Context target, NULL when drawing directly to our swap chain.
+   * Context target, nullptr when drawing directly to our swap chain.
    */
   RefPtr<gfx::DrawTarget> mTarget;
 
   RefPtr<CompositingRenderTargetD3D9> mDefaultRT;
   RefPtr<CompositingRenderTargetD3D9> mCurrentRT;
 
   nsIntSize mSize;
 
--- a/gfx/layers/d3d9/DeviceManagerD3D9.cpp
+++ b/gfx/layers/d3d9/DeviceManagerD3D9.cpp
@@ -150,17 +150,17 @@ SwapChainD3D9::Present(const nsIntRect &
   r.bottom = aRect.YMost();
 
   mSwapChain->Present(&r, &r, 0, 0, 0);
 }
 
 void
 SwapChainD3D9::Present()
 {
-  mSwapChain->Present(NULL, NULL, 0, 0, 0);
+  mSwapChain->Present(nullptr, nullptr, 0, 0, 0);
 }
 
 void
 SwapChainD3D9::Reset()
 {
   mSwapChain = nullptr;
 }
 
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -179,17 +179,17 @@ TextureSourceD3D9::InitTextures(DeviceMa
 
   RefPtr<IDirect3DTexture9> tmpTexture =
     aDeviceManager->CreateTexture(aSize, aFormat, D3DPOOL_SYSTEMMEM, this);
   if (!tmpTexture) {
     return nullptr;
   }
 
   tmpTexture->GetSurfaceLevel(0, byRef(aSurface));
-  aSurface->LockRect(&aLockedRect, NULL, 0);
+  aSurface->LockRect(&aLockedRect, nullptr, 0);
   if (!aLockedRect.pBits) {
     NS_WARNING("Could not lock surface");
     return nullptr;
   }
 
   return result;
 }
 
@@ -203,17 +203,18 @@ FinishTextures(DeviceManagerD3D9* aDevic
 {
   if (!aDeviceManager) {
     return;
   }
 
   aSurface->UnlockRect();
   nsRefPtr<IDirect3DSurface9> dstSurface;
   aTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
-  aDeviceManager->device()->UpdateSurface(aSurface, NULL, dstSurface, NULL);
+  aDeviceManager->device()->UpdateSurface(aSurface, nullptr, dstSurface,
+                                          nullptr);
 }
 
 TemporaryRef<IDirect3DTexture9>
 TextureSourceD3D9::DataToTexture(DeviceManagerD3D9* aDeviceManager,
                                  unsigned char *aData,
                                  int aStride,
                                  const IntSize &aSize,
                                  _D3DFORMAT aFormat,
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -390,19 +390,17 @@ AsyncPanZoomController::AsyncPanZoomCont
      mCrossProcessCompositorParent(nullptr),
      mPaintThrottler(GetFrameTime()),
      mGeckoContentController(aGeckoContentController),
      mRefPtrMonitor("RefPtrMonitor"),
      mMonitor("AsyncPanZoomController"),
      mTouchListenerTimeoutTask(nullptr),
      mX(MOZ_THIS_IN_INITIALIZER_LIST()),
      mY(MOZ_THIS_IN_INITIALIZER_LIST()),
-     mAllowZoom(true),
-     mMinZoom(MIN_ZOOM),
-     mMaxZoom(MAX_ZOOM),
+     mZoomConstraints(true, MIN_ZOOM, MAX_ZOOM),
      mLastSampleTime(GetFrameTime()),
      mState(NOTHING),
      mLastAsyncScrollTime(GetFrameTime()),
      mLastAsyncScrollOffset(0, 0),
      mCurrentAsyncScrollOffset(0, 0),
      mAsyncScrollTimeoutTask(nullptr),
      mHandlingTouchQueue(false),
      mTreeManager(aTreeManager),
@@ -411,17 +409,17 @@ AsyncPanZoomController::AsyncPanZoomCont
      mSharedLock(nullptr)
 {
   MOZ_COUNT_CTOR(AsyncPanZoomController);
 
   if (aGestures == USE_GESTURE_DETECTOR) {
     mGestureEventListener = new GestureEventListener(this);
   }
   if (gAsyncZoomDisabled) {
-    mAllowZoom = false;
+    mZoomConstraints.mAllowZoom = false;
   }
 }
 
 AsyncPanZoomController::~AsyncPanZoomController() {
 
   PCompositorParent* compositor =
     (mCrossProcessCompositorParent ? mCrossProcessCompositorParent : mCompositorParent.get());
 
@@ -708,17 +706,17 @@ nsEventStatus AsyncPanZoomController::On
 nsEventStatus AsyncPanZoomController::OnTouchCancel(const MultiTouchInput& aEvent) {
   APZC_LOG("%p got a touch-cancel in state %d\n", this, mState);
   SetState(NOTHING);
   return nsEventStatus_eConsumeNoDefault;
 }
 
 nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEvent) {
   APZC_LOG("%p got a scale-begin in state %d\n", this, mState);
-  if (!mAllowZoom) {
+  if (!mZoomConstraints.mAllowZoom) {
     return nsEventStatus_eConsumeNoDefault;
   }
 
   SetState(PINCHING);
   mLastZoomFocus = aEvent.mFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft();
 
   return nsEventStatus_eConsumeNoDefault;
 }
@@ -755,18 +753,18 @@ nsEventStatus AsyncPanZoomController::On
     }
     ScrollBy(focusChange);
 
     // When we zoom in with focus, we can zoom too much towards the boundaries
     // that we actually go over them. These are the needed displacements along
     // either axis such that we don't overscroll the boundaries when zooming.
     CSSPoint neededDisplacement;
 
-    CSSToScreenScale realMinZoom = mMinZoom;
-    CSSToScreenScale realMaxZoom = mMaxZoom;
+    CSSToScreenScale realMinZoom = mZoomConstraints.mMinZoom;
+    CSSToScreenScale realMaxZoom = mZoomConstraints.mMaxZoom;
     realMinZoom.scale = std::max(realMinZoom.scale,
                                  mFrameMetrics.mCompositionBounds.width / mFrameMetrics.mScrollableRect.width);
     realMinZoom.scale = std::max(realMinZoom.scale,
                                  mFrameMetrics.mCompositionBounds.height / mFrameMetrics.mScrollableRect.height);
     if (realMaxZoom < realMinZoom) {
       realMaxZoom = realMinZoom;
     }
 
@@ -873,19 +871,19 @@ nsEventStatus AsyncPanZoomController::On
     }
   }
   return nsEventStatus_eIgnore;
 }
 
 nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a single-tap-up in state %d\n", this, mState);
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
-  // If mAllowZoom is true we wait for a call to OnSingleTapConfirmed before
+  // If mZoomConstraints.mAllowZoom is true we wait for a call to OnSingleTapConfirmed before
   // sending event to content
-  if (controller && !mAllowZoom) {
+  if (controller && !mZoomConstraints.mAllowZoom) {
     int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
     CSSIntPoint geckoScreenPoint;
     if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
       controller->HandleSingleTap(geckoScreenPoint, modifiers);
       return nsEventStatus_eConsumeNoDefault;
     }
   }
   return nsEventStatus_eIgnore;
@@ -904,17 +902,17 @@ nsEventStatus AsyncPanZoomController::On
   }
   return nsEventStatus_eIgnore;
 }
 
 nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) {
   APZC_LOG("%p got a double-tap in state %d\n", this, mState);
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
-    if (mAllowZoom) {
+    if (mZoomConstraints.mAllowZoom) {
       int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers);
       CSSIntPoint geckoScreenPoint;
       if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) {
         controller->HandleDoubleTap(geckoScreenPoint, modifiers);
       }
     }
 
     return nsEventStatus_eConsumeNoDefault;
@@ -1252,18 +1250,17 @@ const CSSRect AsyncPanZoomController::Ca
     scrollOffset.x = scrollableRect.x;
   }
   if (scrollOffset.y + compositionBounds.height > scrollableRect.height) {
     scrollOffset.y -= compositionBounds.height + scrollOffset.y - scrollableRect.height;
   } else if (scrollOffset.y < scrollableRect.y) {
     scrollOffset.y = scrollableRect.y;
   }
 
-  CSSRect shiftedDisplayPort = displayPort + scrollOffset;
-  return scrollableRect.ClampRect(shiftedDisplayPort) - scrollOffset;
+  return displayPort.ForceInside(scrollableRect - scrollOffset);
 }
 
 void AsyncPanZoomController::ScheduleComposite() {
   if (mCompositorParent) {
     mCompositorParent->ScheduleRenderOnCompositorThread();
   }
 }
 
@@ -1542,29 +1539,29 @@ void AsyncPanZoomController::ZoomToRect(
     CSSToScreenScale currentZoom = mFrameMetrics.mZoom;
     CSSToScreenScale targetZoom;
 
     // The minimum zoom to prevent over-zoom-out.
     // If the zoom factor is lower than this (i.e. we are zoomed more into the page),
     // then the CSS content rect, in layers pixels, will be smaller than the
     // composition bounds. If this happens, we can't fill the target composited
     // area with this frame.
-    CSSToScreenScale localMinZoom(std::max(mMinZoom.scale,
+    CSSToScreenScale localMinZoom(std::max(mZoomConstraints.mMinZoom.scale,
                                   std::max(compositionBounds.width / cssPageRect.width,
                                            compositionBounds.height / cssPageRect.height)));
-    CSSToScreenScale localMaxZoom = mMaxZoom;
+    CSSToScreenScale localMaxZoom = mZoomConstraints.mMaxZoom;
 
     if (!aRect.IsEmpty()) {
       // Intersect the zoom-to-rect to the CSS rect to make sure it fits.
       aRect = aRect.Intersect(cssPageRect);
       targetZoom = CSSToScreenScale(std::min(compositionBounds.width / aRect.width,
                                              compositionBounds.height / aRect.height));
     }
     // 1. If the rect is empty, request received from browserElementScrolling.js
-    // 2. currentZoom is equal to mMaxZoom and user still double-tapping it
+    // 2. currentZoom is equal to mZoomConstraints.mMaxZoom and user still double-tapping it
     // 3. currentZoom is equal to localMinZoom and user still double-tapping it
     // Treat these three cases as a request to zoom out as much as possible.
     if (aRect.IsEmpty() ||
         (currentZoom == localMaxZoom && targetZoom >= localMaxZoom) ||
         (currentZoom == localMinZoom && targetZoom <= localMinZoom)) {
       CSSRect compositedRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
       float y = scrollOffset.y;
       float newHeight =
@@ -1683,35 +1680,29 @@ bool AsyncPanZoomController::IsPanningSt
   return (aState == PANNING || aState == PANNING_LOCKED_X || aState == PANNING_LOCKED_Y);
 }
 
 void AsyncPanZoomController::TimeoutTouchListeners() {
   mTouchListenerTimeoutTask = nullptr;
   ContentReceivedTouch(false);
 }
 
-void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom,
-                                                   const CSSToScreenScale& aMinZoom,
-                                                   const CSSToScreenScale& aMaxZoom) {
+void AsyncPanZoomController::UpdateZoomConstraints(const ZoomConstraints& aConstraints) {
   if (gAsyncZoomDisabled) {
     return;
   }
-  mAllowZoom = aAllowZoom;
-  mMinZoom = (MIN_ZOOM > aMinZoom ? MIN_ZOOM : aMinZoom);
-  mMaxZoom = (MAX_ZOOM > aMaxZoom ? aMaxZoom : MAX_ZOOM);
+  mZoomConstraints.mAllowZoom = aConstraints.mAllowZoom;
+  mZoomConstraints.mMinZoom = (MIN_ZOOM > aConstraints.mMinZoom ? MIN_ZOOM : aConstraints.mMinZoom);
+  mZoomConstraints.mMaxZoom = (MAX_ZOOM > aConstraints.mMaxZoom ? aConstraints.mMaxZoom : MAX_ZOOM);
 }
 
-void
-AsyncPanZoomController::GetZoomConstraints(bool* aAllowZoom,
-                                           CSSToScreenScale* aMinZoom,
-                                           CSSToScreenScale* aMaxZoom)
+ZoomConstraints
+AsyncPanZoomController::GetZoomConstraints() const
 {
-  *aAllowZoom = mAllowZoom;
-  *aMinZoom = mMinZoom;
-  *aMaxZoom = mMaxZoom;
+  return mZoomConstraints;
 }
 
 
 void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) {
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     controller->PostDelayedTask(aTask, aDelayMs);
   }
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -125,30 +125,24 @@ public:
    * definitively whether or not content has preventDefaulted any touch events
    * that have come in. If |aPreventDefault| is true, any touch events in the
    * queue will be discarded.
    */
   void ContentReceivedTouch(bool aPreventDefault);
 
   /**
    * Updates any zoom constraints contained in the <meta name="viewport"> tag.
-   * We try to obey everything it asks us elsewhere, but here we only handle
-   * minimum-scale, maximum-scale, and user-scalable.
    */
-  void UpdateZoomConstraints(bool aAllowZoom,
-                             const CSSToScreenScale& aMinScale,
-                             const CSSToScreenScale& aMaxScale);
+  void UpdateZoomConstraints(const ZoomConstraints& aConstraints);
 
   /**
    * Return the zoom constraints last set for this APZC (in the constructor
    * or in UpdateZoomConstraints()).
    */
-  void GetZoomConstraints(bool* aAllowZoom,
-                          CSSToScreenScale* aMinScale,
-                          CSSToScreenScale* aMaxScale);
+  ZoomConstraints GetZoomConstraints() const;
 
   /**
    * Schedules a runnable to run on the controller/UI thread at some time
    * in the future.
    */
   void PostDelayedTask(Task* aTask, int aDelayMs);
 
   // --------------------------------------------------------------------------
@@ -604,19 +598,17 @@ private:
   CancelableTask* mTouchListenerTimeoutTask;
 
   AxisX mX;
   AxisY mY;
 
   // Most up-to-date constraints on zooming. These should always be reasonable
   // values; for example, allowing a min zoom of 0.0 can cause very bad things
   // to happen.
-  bool mAllowZoom;
-  CSSToScreenScale mMinZoom;
-  CSSToScreenScale mMaxZoom;
+  ZoomConstraints mZoomConstraints;
 
   // The last time the compositor has sampled the content transform for this
   // frame.
   TimeStamp mLastSampleTime;
   // The last time a touch event came through on the UI thread.
   uint32_t mLastEventTime;
 
   // Stores the previous focus point if there is a pinch gesture happening. Used
--- a/gfx/layers/ipc/GeckoContentController.h
+++ b/gfx/layers/ipc/GeckoContentController.h
@@ -71,19 +71,17 @@ public:
    */
   virtual void PostDelayedTask(Task* aTask, int aDelayMs) = 0;
 
   /**
    * Retrieves the last known zoom constraints for the root scrollable layer
    * for this layers tree. This function should return false if there are no
    * last known zoom constraints.
    */
-  virtual bool GetRootZoomConstraints(bool* aOutAllowZoom,
-                                      CSSToScreenScale* aOutMinZoom,
-                                      CSSToScreenScale* aOutMaxZoom)
+  virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
   {
     return false;
   }
 
   /**
    * General tranformation notices for consumers. These fire any time
    * the apzc is modifying the view, including panning, zooming, and
    * fling.
--- a/gfx/src/nsRegion.h
+++ b/gfx/src/nsRegion.h
@@ -261,17 +261,17 @@ private:
     return *this;
   }
 
   nsRegion& Copy (const nsRect& aRect)
   {
     // pixman needs to distinguish between an empty region and a region
     // with one rect so that it can return a different number of rectangles.
     // Empty rect: data = empty_box
-    //     1 rect: data = NULL
+    //     1 rect: data = null
     //    >1 rect: data = rects
     if (aRect.IsEmpty()) {
       pixman_region32_clear(&mImpl);
     } else {
       pixman_box32_t box = RectToBox(aRect);
       pixman_region32_reset(&mImpl, &box);
     }
     return *this;
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp
+++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp
@@ -479,17 +479,17 @@ TEST(AsyncPanZoomController, OverScrollP
 TEST(AsyncPanZoomController, ShortPress) {
   nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
 
   apzc->SetFrameMetrics(TestFrameMetrics());
   apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
-  apzc->UpdateZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0));
+  apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
 
   EXPECT_CALL(*mcc, HandleSingleTap(CSSIntPoint(10, 10), 0)).Times(1);
 
   int time = 0;
   nsEventStatus status = ApzcTap(apzc, 10, 10, time, 100);
   EXPECT_EQ(nsEventStatus_eIgnore, status);
 
   apzc->Destroy();
@@ -498,17 +498,17 @@ TEST(AsyncPanZoomController, ShortPress)
 TEST(AsyncPanZoomController, MediumPress) {
   nsRefPtr<MockContentController> mcc = new NiceMock<MockContentController>();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
 
   apzc->SetFrameMetrics(TestFrameMetrics());
   apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
-  apzc->UpdateZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0));
+  apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
 
   EXPECT_CALL(*mcc, HandleSingleTap(CSSIntPoint(10, 10), 0)).Times(1);
 
   int time = 0;
   nsEventStatus status = ApzcTap(apzc, 10, 10, time, 400);
   EXPECT_EQ(nsEventStatus_eIgnore, status);
 
   apzc->Destroy();
@@ -517,17 +517,17 @@ TEST(AsyncPanZoomController, MediumPress
 TEST(AsyncPanZoomController, LongPress) {
   nsRefPtr<MockContentControllerDelayed> mcc = new MockContentControllerDelayed();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
 
   apzc->SetFrameMetrics(TestFrameMetrics());
   apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
-  apzc->UpdateZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0));
+  apzc->UpdateZoomConstraints(ZoomConstraints(false, CSSToScreenScale(1.0), CSSToScreenScale(1.0)));
 
   int time = 0;
 
   nsEventStatus status = ApzcDown(apzc, 10, 10, time);
   EXPECT_EQ(nsEventStatus_eConsumeNoDefault, status);
 
   Task* t = mcc->GetDelayedTask();
 
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -871,17 +871,17 @@ gfxASurface::WriteAsPNG_internal(FILE* a
     if (aFile) {
       fwrite(imgData, 1, imgSize, aFile);
     } else {
       NS_WARNING("Can't write binary image data without a file!");
     }
     return;
   }
 
-  // base 64, result will be NULL terminated
+  // base 64, result will be null-terminated
   nsCString encodedImg;
   rv = Base64Encode(Substring(imgData, imgSize), encodedImg);
   moz_free(imgData);
   if (NS_FAILED(rv)) // not sure why this would fail
     return;
 
   nsCString string("data:image/png;base64,");
   string.Append(encodedImg);
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -73,25 +73,25 @@ struct Int32x4 {
 };
 } // namespace js
 
 #define LANE_ACCESSOR(Type32x4, lane) \
     bool Type32x4##Lane##lane(JSContext *cx, unsigned argc, Value *vp) { \
         static const char *laneNames[] = {"lane 0", "lane 1", "lane 2", "lane3"}; \
         CallArgs args = CallArgsFromVp(argc, vp); \
         if(!args.thisv().isObject() || !IsTypedDatum(args.thisv().toObject())) { \
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, \
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, \
                                  X4Type::class_.name, laneNames[lane], \
                                  InformalValueTypeName(args.thisv())); \
             return false; \
         } \
         TypedDatum &datum = AsTypedDatum(args.thisv().toObject()); \
         TypeRepresentation *typeRepr = datum.datumTypeRepresentation(); \
         if (typeRepr->kind() != TypeRepresentation::X4 || typeRepr->asX4()->type() != Type32x4::type) { \
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, \
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, \
                                  X4Type::class_.name, laneNames[lane], \
                                  InformalValueTypeName(args.thisv())); \
             return false; \
         } \
         Type32x4::Elem *data = reinterpret_cast<Type32x4::Elem *>(datum.typedMem()); \
         Type32x4::setReturn(args, data[lane]); \
         return true; \
     }
@@ -104,25 +104,25 @@ struct Int32x4 {
     LANE_ACCESSOR(Int32x4, 2);
     LANE_ACCESSOR(Int32x4, 3);
 #undef LANE_ACCESSOR
 
 #define SIGN_MASK(Type32x4) \
     bool Type32x4##SignMask(JSContext *cx, unsigned argc, Value *vp) { \
         CallArgs args = CallArgsFromVp(argc, vp); \
         if(!args.thisv().isObject() || !IsTypedDatum(args.thisv().toObject())) { \
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, \
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, \
                                  X4Type::class_.name, "signMask", \
                                  InformalValueTypeName(args.thisv())); \
             return false; \
         } \
         TypedDatum &datum = AsTypedDatum(args.thisv().toObject()); \
         TypeRepresentation *typeRepr = datum.datumTypeRepresentation(); \
         if (typeRepr->kind() != TypeRepresentation::X4 || typeRepr->asX4()->type() != Type32x4::type) { \
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, \
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, \
                                  X4Type::class_.name, "signMask", \
                                  InformalValueTypeName(args.thisv())); \
             return false; \
         } \
         Type32x4::Elem *data = reinterpret_cast<Type32x4::Elem *>(datum.typedMem()); \
         int32_t mx = data[0] < 0.0 ? 1 : 0; \
         int32_t my = data[1] < 0.0 ? 1 : 0; \
         int32_t mz = data[2] < 0.0 ? 1 : 0; \
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1123,16 +1123,40 @@ SetJitCompilerOption(JSContext *cx, unsi
 
     JS_SetGlobalJitCompilerOption(cx, opt, uint32_t(number));
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
+GetJitCompilerOptions(JSContext *cx, unsigned argc, jsval *vp)
+{
+    RootedObject info(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
+    if (!info)
+        return false;
+
+    RootedValue value(cx);
+
+#define JIT_COMPILER_MATCH(key, string)                         \
+    opt = JSJITCOMPILER_ ## key;                                \
+    value.setInt32(JS_GetGlobalJitCompilerOption(cx, opt));     \
+    if (!JS_SetProperty(cx, info, string, value))               \
+        return false;
+
+    JSJitCompilerOption opt = JSJITCOMPILER_NOT_AN_OPTION;
+    JIT_COMPILER_OPTIONS(JIT_COMPILER_MATCH);
+#undef JIT_COMPILER_MATCH
+
+    *vp = ObjectValue(*info);
+
+    return true;
+}
+
+static bool
 SetIonCheckGraphCoherency(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 #ifdef JS_ION
     jit::js_JitOptions.checkGraphConsistency = ToBoolean(args.get(0));
 #endif
     args.rval().setUndefined();
     return true;
@@ -1541,16 +1565,20 @@ static const JSFunctionSpecWithHelp Test
 "  inferred name based on where the function was defined. This can be\n"
 "  different from the 'name' property on the function."),
 
     JS_FN_HELP("isAsmJSCompilationAvailable", IsAsmJSCompilationAvailable, 0, 0,
 "isAsmJSCompilationAvailable",
 "  Returns whether asm.js compilation is currently available or whether it is disabled\n"
 "  (e.g., by the debugger)."),
 
+    JS_FN_HELP("getJitCompilerOptions", GetJitCompilerOptions, 0, 0,
+"getCompilerOptions()",
+"Return an object describing some of the JIT compiler options.\n"),
+
     JS_FN_HELP("isAsmJSModule", IsAsmJSModule, 1, 0,
 "isAsmJSModule(fn)",
 "  Returns whether the given value is a function containing \"use asm\" that has been\n"
 "  validated according to the asm.js spec."),
 
     JS_FN_HELP("isAsmJSModuleLoadedFromCache", IsAsmJSModuleLoadedFromCache, 1, 0,
 "isAsmJSModuleLoadedFromCache(fn)",
 "  Return whether the given asm.js module function has been loaded directly\n"
--- a/js/src/builtin/TypeRepresentation.cpp
+++ b/js/src/builtin/TypeRepresentation.cpp
@@ -776,17 +776,17 @@ SizedArrayTypeRepresentation::appendStri
     SizedTypeRepresentation *elementType = element();
     while (elementType->isSizedArray())
         elementType = elementType->asSizedArray()->element();
     if (!elementType->appendString(cx, contents))
         return false;
 
     contents.append(".array(");
     SizedArrayTypeRepresentation *arrayType = this;
-    while (arrayType != NULL) {
+    while (arrayType != nullptr) {
         if (!NumberValueToStringBuffer(cx, NumberValue(length()), contents))
             return false;
 
         if (arrayType->element()->isSizedArray()) {
             if (!contents.append(","))
                 return false;
             arrayType = arrayType->element()->asSizedArray();
         } else {
--- a/js/src/devtools/vprof/vprof.cpp
+++ b/js/src/devtools/vprof/vprof.cpp
@@ -48,17 +48,17 @@
 #if THREAD_SAFE
 #define LOCK(lock) DO_LOCK(lock)
 #define UNLOCK(lock) DO_UNLOCK(lock)
 #else
 #define LOCK(lock) { (void)(lock);
 #define UNLOCK(lock) }
 #endif
 
-static entry* entries = NULL;
+static entry* entries = nullptr;
 static bool notInitialized = true;
 static long glock = LOCK_IS_FREE;
 
 #define Lock(lock) while (_InterlockedCompareExchange(lock, LOCK_IS_TAKEN, LOCK_IS_FREE) == LOCK_IS_TAKEN){};
 #define Unlock(lock) _InterlockedCompareExchange(lock, LOCK_IS_FREE, LOCK_IS_TAKEN);
 
 #if defined(WIN32)
 	static void vprof_printf(const char* format, ...)
@@ -77,17 +77,17 @@ static long glock = LOCK_IS_FREE;
 #else
 	#define vprof_printf printf
 #endif
 
 static inline entry* reverse (entry* s)
 {
     entry_t e, n, p;
 
-    p = NULL;
+    p = nullptr;
     for (e = s; e; e = n) {
         n = e->next;
         e->next = p;
         p = e;
     }
 
     return p;
 }
@@ -153,56 +153,56 @@ static void dumpProfile (void)
 
 static inline entry_t findEntry (char* file, int line)
 {
     for (entry_t e =  entries; e; e = e->next) {
         if ((e->line == line) && (VMPI_strcmp (e->file, file) == 0)) {
             return e;
         }
     }
-    return NULL;
+    return nullptr;
 }
 
 // Initialize the location pointed to by 'id' to a new value profile entry
 // associated with 'file' and 'line', or do nothing if already initialized.
 // An optional final argument provides a user-defined probe function.
 
 int initValueProfile(void** id, char* file, int line, ...)
 {
     DO_LOCK (&glock);
         entry_t e = (entry_t) *id;
         if (notInitialized) {
             atexit (dumpProfile);
             notInitialized = false;
         }
 
-        if (e == NULL) {
+        if (e == nullptr) {
             e = findEntry (file, line);
             if (e) {
                 *id = e;
             }
         }
 
-        if (e == NULL) {
+        if (e == nullptr) {
             va_list va;
             e = (entry_t) malloc (sizeof(entry));
             e->lock = LOCK_IS_FREE;
             e->file = file;
             e->line = line;
             e->value = 0;
             e->sum = 0;
             e->count = 0;
             e->min = 0;
             e->max = 0;
             // optional probe function argument
             va_start (va, line);
             e->func = (void (__cdecl*)(void*)) va_arg (va, void*);
             va_end (va);
-            e->h = NULL;
-            e->genptr = NULL;
+            e->h = nullptr;
+            e->genptr = nullptr;
             VMPI_memset (&e->ivar,   0, sizeof(e->ivar));
             VMPI_memset (&e->i64var, 0, sizeof(e->i64var));
             VMPI_memset (&e->dvar,   0, sizeof(e->dvar));
             e->next = entries;
             entries = e;
             *id = e;
         }
     DO_UNLOCK (&glock);
@@ -242,39 +242,39 @@ int initHistProfile(void** id, char* fil
 {
     DO_LOCK (&glock);
         entry_t e = (entry_t) *id;
         if (notInitialized) {
             atexit (dumpProfile);
             notInitialized = false;
         }
 
-        if (e == NULL) {
+        if (e == nullptr) {
             e = findEntry (file, line);
             if (e) {
                 *id = e;
             }
         }
 
-        if (e == NULL) {
+        if (e == nullptr) {
             va_list va;
             hist_t h;
             int b, n, s;
             int64_t* lb;
 
             e = (entry_t) malloc (sizeof(entry));
             e->lock = LOCK_IS_FREE;
             e->file = file;
             e->line = line;
             e->value = 0;
             e->sum = 0;
             e->count = 0;
             e->min = 0;
             e->max = 0;
-            e->func = NULL;
+            e->func = nullptr;
             e->h = h = (hist_t) malloc (sizeof(hist));
             n = 1+MAX(nbins,0);
             h->nbins = n-1;
             s = n*sizeof(int64_t);
             lb = (int64_t*) malloc (s);
             h->lb = lb;
             VMPI_memset (h->lb, 0, s);
             h->count = (int64_t*) malloc (s);
@@ -283,17 +283,17 @@ int initHistProfile(void** id, char* fil
             va_start (va, nbins);
             for (b = 0; b < nbins; b++) {
                 //lb[b] = va_arg (va, int64_t);
                 lb[b] = va_arg (va, int);
             }
             lb[b] = MAXINT64;
             va_end (va);
 
-            e->genptr = NULL;
+            e->genptr = nullptr;
             VMPI_memset (&e->ivar,   0, sizeof(e->ivar));
             VMPI_memset (&e->i64var, 0, sizeof(e->i64var));
             VMPI_memset (&e->dvar,   0, sizeof(e->dvar));
             e->next = entries;
             entries = e;
             *id = e;
         }
     DO_UNLOCK (&glock);
--- a/js/src/jit-test/tests/basic/testArrayBufferSlice.js
+++ b/js/src/jit-test/tests/basic/testArrayBufferSlice.js
@@ -1,8 +1,11 @@
+// Bug 956434 - Disable test due to unpredictable failures on ggc builds
+quit(0);
+
 function testSlice() {
     function test(subBuf, starts, size) {
         var byteLength = size;
         var subBuffer = eval(subBuf);
         var subArray = new Int8Array(subBuffer);
         assertEq(subBuffer.byteLength, byteLength);
         for (var i = 0; i < size; ++i)
             assertEq(starts + i, subArray[i]);
--- a/js/src/jit-test/tests/ion/bug909997.js
+++ b/js/src/jit-test/tests/ion/bug909997.js
@@ -16,11 +16,14 @@ var method_D = function() {
     for (var t = 0; t < wait; ++t) {}
 }
 
 var func = [method_A, method_B, method_C, method_D]
 
 for (var n = 0; n < 4; ++n) {
     setJitCompilerOption("baseline.enable", n & 1);
     setJitCompilerOption("ion.enable", n & 2 ? 1: 0);
+    var opt = getJitCompilerOptions();
+    assertEq(opt["baseline.enable"], n & 1);
+    assertEq(opt["ion.enable"], n & 2 ? 1 : 0);
     for (var i = 0; i < 1001; ++i)
         func[n]();
 }
\ No newline at end of file
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -490,17 +490,17 @@ class RetType
         Double = Type::Double,
         Float = Type::Float
     };
 
   private:
     Which which_;
 
   public:
-    RetType() {}
+    RetType() : which_(Which(-1)) {}
     RetType(Which w) : which_(w) {}
     RetType(AsmJSCoercion coercion) {
         switch (coercion) {
           case AsmJS_ToInt32: which_ = Signed; break;
           case AsmJS_ToNumber: which_ = Double; break;
           case AsmJS_FRound: which_ = Float; break;
         }
     }
@@ -587,35 +587,34 @@ class VarType
     }
     MIRType toMIRType() const {
         switch(which_) {
           case Int:     return MIRType_Int32;
           case Double:  return MIRType_Double;
           case Float:   return MIRType_Float32;
         }
         MOZ_ASSUME_UNREACHABLE("VarType can only be Int, Double or Float");
-        return MIRType_None;
     }
     AsmJSCoercion toCoercion() const {
         switch(which_) {
           case Int:     return AsmJS_ToInt32;
           case Double:  return AsmJS_ToNumber;
           case Float:   return AsmJS_FRound;
         }
         MOZ_ASSUME_UNREACHABLE("VarType can only be Int, Double or Float");
-        return AsmJS_ToInt32;
     }
     static VarType FromMIRType(MIRType type) {
         JS_ASSERT(type == MIRType_Int32 || type == MIRType_Double || type == MIRType_Float32);
         switch(type) {
           case MIRType_Int32:   return Int;
           case MIRType_Float32: return Float;
           case MIRType_Double:  return Double;
-          default: MOZ_ASSUME_UNREACHABLE("FromMIRType MIR type not handled"); return Int;
+          default:;
         }
+        MOZ_ASSUME_UNREACHABLE("FromMIRType MIR type not handled");
     }
     static VarType FromCheckedType(Type type) {
         JS_ASSERT(type.isInt() || type.isMaybeDouble() || type.isFloatish());
         if (type.isMaybeDouble())
             return Double;
         else if (type.isFloatish())
             return Float;
         else
@@ -724,197 +723,16 @@ bool operator==(const Signature &lhs, co
 
 static inline
 bool operator!=(const Signature &lhs, const Signature &rhs)
 {
     return !(lhs == rhs);
 }
 
 /*****************************************************************************/
-// Numeric literal utilities
-
-namespace {
-
-// Represents the type and value of an asm.js numeric literal.
-//
-// A literal is a double iff the literal contains an exponent or decimal point
-// (even if the fractional part is 0). Otherwise, integers may be classified:
-//  fixnum: [0, 2^31)
-//  negative int: [-2^31, 0)
-//  big unsigned: [2^31, 2^32)
-//  out of range: otherwise
-class NumLit
-{
-  public:
-    enum Which {
-        Fixnum = Type::Fixnum,
-        NegativeInt = Type::Signed,
-        BigUnsigned = Type::Unsigned,
-        Double = Type::Double,
-        OutOfRangeInt = -1
-    };
-
-  private:
-    Which which_;
-    Value v_;
-
-  public:
-    NumLit() {}
-
-    NumLit(Which w, Value v)
-      : which_(w), v_(v)
-    {}
-
-    Which which() const {
-        return which_;
-    }
-
-    int32_t toInt32() const {
-        JS_ASSERT(which_ == Fixnum || which_ == NegativeInt || which_ == BigUnsigned);
-        return v_.toInt32();
-    }
-
-    double toDouble() const {
-        return v_.toDouble();
-    }
-
-    Type type() const {
-        JS_ASSERT(which_ != OutOfRangeInt);
-        return Type::Which(which_);
-    }
-
-    Value value() const {
-        JS_ASSERT(which_ != OutOfRangeInt);
-        return v_;
-    }
-};
-
-} /* anonymous namespace */
-
-// Note: '-' is never rolled into the number; numbers are always positive and
-// negations must be applied manually.
-static bool
-IsNumericLiteral(ParseNode *pn)
-{
-    return pn->isKind(PNK_NUMBER) ||
-           (pn->isKind(PNK_NEG) && UnaryKid(pn)->isKind(PNK_NUMBER));
-}
-
-static NumLit
-ExtractNumericLiteral(ParseNode *pn)
-{
-    // The JS grammar treats -42 as -(42) (i.e., with separate grammar
-    // productions) for the unary - and literal 42). However, the asm.js spec
-    // recognizes -42 (modulo parens, so -(42) and -((42))) as a single literal
-    // so fold the two potential parse nodes into a single double value.
-    JS_ASSERT(IsNumericLiteral(pn));
-    ParseNode *numberNode;
-    double d;
-    if (pn->isKind(PNK_NEG)) {
-        numberNode = UnaryKid(pn);
-        d = -NumberNodeValue(numberNode);
-    } else {
-        numberNode = pn;
-        d = NumberNodeValue(numberNode);
-    }
-
-    // The asm.js spec syntactically distinguishes any literal containing a
-    // decimal point or the literal -0 as having double type.
-    if (NumberNodeHasFrac(numberNode) || IsNegativeZero(d))
-        return NumLit(NumLit::Double, DoubleValue(d));
-
-    // The syntactic checks above rule out these double values.
-    JS_ASSERT(!IsNegativeZero(d));
-    JS_ASSERT(!IsNaN(d));
-
-    // Although doubles can only *precisely* represent 53-bit integers, they
-    // can *imprecisely* represent integers much bigger than an int64_t.
-    // Furthermore, d may be inf or -inf. In both cases, casting to an int64_t
-    // is undefined, so test against the integer bounds using doubles.
-    if (d < double(INT32_MIN) || d > double(UINT32_MAX))
-        return NumLit(NumLit::OutOfRangeInt, UndefinedValue());
-
-    // With the above syntactic and range limitations, d is definitely an
-    // integer in the range [INT32_MIN, UINT32_MAX] range.
-    int64_t i64 = int64_t(d);
-    if (i64 >= 0) {
-        if (i64 <= INT32_MAX)
-            return NumLit(NumLit::Fixnum, Int32Value(i64));
-        JS_ASSERT(i64 <= UINT32_MAX);
-        return NumLit(NumLit::BigUnsigned, Int32Value(uint32_t(i64)));
-    }
-    JS_ASSERT(i64 >= INT32_MIN);
-    return NumLit(NumLit::NegativeInt, Int32Value(i64));
-}
-
-static bool
-ExtractFRoundableLiteral(ParseNode *pn, double *value)
-{
-    if (!IsNumericLiteral(pn))
-        return false;
-
-    NumLit literal = ExtractNumericLiteral(pn);
-    switch (literal.which()) {
-      case NumLit::Double:
-        *value = literal.toDouble();
-        return true;
-      case NumLit::Fixnum:
-      case NumLit::NegativeInt:
-      case NumLit::BigUnsigned:
-        literal = NumLit(NumLit::Double, DoubleValue(literal.toInt32()));
-        *value = literal.toDouble();
-        return true;
-      case NumLit::OutOfRangeInt:
-        break;
-    }
-    return false;
-}
-
-static inline bool
-IsLiteralInt(ParseNode *pn, uint32_t *u32)
-{
-    if (!IsNumericLiteral(pn))
-        return false;
-
-    NumLit literal = ExtractNumericLiteral(pn);
-    switch (literal.which()) {
-      case NumLit::Fixnum:
-      case NumLit::BigUnsigned:
-      case NumLit::NegativeInt:
-        *u32 = uint32_t(literal.toInt32());
-        return true;
-      case NumLit::Double:
-      case NumLit::OutOfRangeInt:
-        return false;
-    }
-
-    MOZ_ASSUME_UNREACHABLE("Bad literal type");
-}
-
-static inline bool
-IsBits32(ParseNode *pn, int32_t i)
-{
-    if (!IsNumericLiteral(pn))
-        return false;
-
-    NumLit literal = ExtractNumericLiteral(pn);
-    switch (literal.which()) {
-      case NumLit::Fixnum:
-      case NumLit::BigUnsigned:
-      case NumLit::NegativeInt:
-        return literal.toInt32() == i;
-      case NumLit::Double:
-      case NumLit::OutOfRangeInt:
-        return false;
-    }
-
-    MOZ_ASSUME_UNREACHABLE("Bad literal type");
-}
-
-/*****************************************************************************/
 // Typed array utilities
 
 static Type
 TypedArrayLoadType(ArrayBufferView::ViewType viewType)
 {
     switch (viewType) {
       case ArrayBufferView::TYPE_INT8:
       case ArrayBufferView::TYPE_INT16:
@@ -1842,16 +1660,242 @@ class MOZ_STACK_CLASS ModuleCompiler
         *module = module_.forget();
         return true;
     }
 };
 
 } /* anonymous namespace */
 
 /*****************************************************************************/
+// Numeric literal utilities
+
+namespace {
+
+// Represents the type and value of an asm.js numeric literal.
+//
+// A literal is a double iff the literal contains an exponent or decimal point
+// (even if the fractional part is 0). Otherwise, integers may be classified:
+//  fixnum: [0, 2^31)
+//  negative int: [-2^31, 0)
+//  big unsigned: [2^31, 2^32)
+//  out of range: otherwise
+// Lastly, a literal may be a float literal which is any double or integer
+// literal coerced with Math.fround.
+class NumLit
+{
+  public:
+    enum Which {
+        Fixnum = Type::Fixnum,
+        NegativeInt = Type::Signed,
+        BigUnsigned = Type::Unsigned,
+        Double = Type::Double,
+        Float = Type::Float,
+        OutOfRangeInt = -1
+    };
+
+  private:
+    Which which_;
+    Value v_;
+
+  public:
+    NumLit() {}
+
+    NumLit(Which w, Value v)
+      : which_(w), v_(v)
+    {}
+
+    Which which() const {
+        return which_;
+    }
+
+    int32_t toInt32() const {
+        JS_ASSERT(which_ == Fixnum || which_ == NegativeInt || which_ == BigUnsigned);
+        return v_.toInt32();
+    }
+
+    double toDouble() const {
+        JS_ASSERT(which_ == Double);
+        return v_.toDouble();
+    }
+
+    float toFloat() const {
+        JS_ASSERT(which_ == Float);
+        return float(v_.toDouble());
+    }
+
+    Value value() const {
+        JS_ASSERT(which_ != OutOfRangeInt);
+        return v_;
+    }
+
+    bool hasType() const {
+        return which_ != OutOfRangeInt;
+    }
+
+    Type type() const {
+        JS_ASSERT(hasType());
+        return Type::Which(which_);
+    }
+
+    VarType varType() const {
+        JS_ASSERT(hasType());
+        switch (which_) {
+          case NumLit::Fixnum:
+          case NumLit::NegativeInt:
+          case NumLit::BigUnsigned:
+            return VarType::Int;
+          case NumLit::Double:
+            return VarType::Double;
+          case NumLit::Float:
+            return VarType::Float;
+          case NumLit::OutOfRangeInt:;
+        }
+        MOZ_ASSUME_UNREACHABLE("Unexpected NumLit type");
+    }
+};
+
+} /* anonymous namespace */
+
+static bool
+IsNumericNonFloatLiteral(ParseNode *pn)
+{
+    // Note: '-' is never rolled into the number; numbers are always positive
+    // and negations must be applied manually.
+    return pn->isKind(PNK_NUMBER) ||
+           (pn->isKind(PNK_NEG) && UnaryKid(pn)->isKind(PNK_NUMBER));
+}
+
+static bool
+IsFloatCoercion(ModuleCompiler &m, ParseNode *pn, ParseNode **coercedExpr)
+{
+    if (!pn->isKind(PNK_CALL))
+        return false;
+
+    ParseNode *callee = CallCallee(pn);
+    if (!callee->isKind(PNK_NAME))
+        return false;
+
+    const ModuleCompiler::Global *global = m.lookupGlobal(callee->name());
+    if (!global ||
+        global->which() != ModuleCompiler::Global::MathBuiltin ||
+        global->mathBuiltin() != AsmJSMathBuiltin_fround)
+    {
+        return false;
+    }
+
+    if (CallArgListLength(pn) != 1)
+        return false;
+
+    if (coercedExpr)
+        *coercedExpr = CallArgList(pn);
+
+    return true;
+}
+
+static bool
+IsNumericFloatLiteral(ModuleCompiler &m, ParseNode *pn)
+{
+    ParseNode *coercedExpr;
+    if (!IsFloatCoercion(m, pn, &coercedExpr))
+        return false;
+
+    return IsNumericNonFloatLiteral(coercedExpr);
+}
+
+static bool
+IsNumericLiteral(ModuleCompiler &m, ParseNode *pn)
+{
+    return IsNumericNonFloatLiteral(pn) ||
+           IsNumericFloatLiteral(m, pn);
+}
+
+// The JS grammar treats -42 as -(42) (i.e., with separate grammar
+// productions) for the unary - and literal 42). However, the asm.js spec
+// recognizes -42 (modulo parens, so -(42) and -((42))) as a single literal
+// so fold the two potential parse nodes into a single double value.
+static double
+ExtractNumericNonFloatValue(ParseNode **pn)
+{
+    JS_ASSERT(IsNumericNonFloatLiteral(*pn));
+
+    if ((*pn)->isKind(PNK_NEG)) {
+        *pn = UnaryKid(*pn);
+        return -NumberNodeValue(*pn);
+    }
+
+    return NumberNodeValue(*pn);
+}
+
+static NumLit
+ExtractNumericLiteral(ModuleCompiler &m, ParseNode *pn)
+{
+    JS_ASSERT(IsNumericLiteral(m, pn));
+
+    // Float literals are explicitly coerced and thus the coerced literal may be
+    // any valid (non-float) numeric literal.
+    if (pn->isKind(PNK_CALL)) {
+        pn = CallArgList(pn);
+        double d = ExtractNumericNonFloatValue(&pn);
+        return NumLit(NumLit::Float, DoubleValue(d));
+    }
+
+    double d = ExtractNumericNonFloatValue(&pn);
+
+    // The asm.js spec syntactically distinguishes any literal containing a
+    // decimal point or the literal -0 as having double type.
+    if (NumberNodeHasFrac(pn) || IsNegativeZero(d))
+        return NumLit(NumLit::Double, DoubleValue(d));
+
+    // The syntactic checks above rule out these double values.
+    JS_ASSERT(!IsNegativeZero(d));
+    JS_ASSERT(!IsNaN(d));
+
+    // Although doubles can only *precisely* represent 53-bit integers, they
+    // can *imprecisely* represent integers much bigger than an int64_t.
+    // Furthermore, d may be inf or -inf. In both cases, casting to an int64_t
+    // is undefined, so test against the integer bounds using doubles.
+    if (d < double(INT32_MIN) || d > double(UINT32_MAX))
+        return NumLit(NumLit::OutOfRangeInt, UndefinedValue());
+
+    // With the above syntactic and range limitations, d is definitely an
+    // integer in the range [INT32_MIN, UINT32_MAX] range.
+    int64_t i64 = int64_t(d);
+    if (i64 >= 0) {
+        if (i64 <= INT32_MAX)
+            return NumLit(NumLit::Fixnum, Int32Value(i64));
+        JS_ASSERT(i64 <= UINT32_MAX);
+        return NumLit(NumLit::BigUnsigned, Int32Value(uint32_t(i64)));
+    }
+    JS_ASSERT(i64 >= INT32_MIN);
+    return NumLit(NumLit::NegativeInt, Int32Value(i64));
+}
+
+static inline bool
+IsLiteralInt(ModuleCompiler &m, ParseNode *pn, uint32_t *u32)
+{
+    if (!IsNumericLiteral(m, pn))
+        return false;
+
+    NumLit literal = ExtractNumericLiteral(m, pn);
+    switch (literal.which()) {
+      case NumLit::Fixnum:
+      case NumLit::BigUnsigned:
+      case NumLit::NegativeInt:
+        *u32 = uint32_t(literal.toInt32());
+        return true;
+      case NumLit::Double:
+      case NumLit::Float:
+      case NumLit::OutOfRangeInt:
+        return false;
+    }
+
+    MOZ_ASSUME_UNREACHABLE("Bad literal type");
+}
+
+/*****************************************************************************/
 
 namespace {
 
 // Encapsulates the compilation of a single function in an asm.js module. The
 // function compiler handles the creation and final backend compilation of the
 // MIR graph. Also see ModuleCompiler comment.
 class FunctionCompiler
 {
@@ -2060,32 +2104,21 @@ class FunctionCompiler
     {
         if (locals_.has(name))
             return nullptr;
         return m_.lookupGlobal(name);
     }
 
     /***************************** Code generation (after local scope setup) */
 
-    MDefinition *constant(const Value &v)
+    MDefinition *constant(Value v, Type t)
     {
         if (!curBlock_)
             return nullptr;
-        JS_ASSERT(v.isNumber());
-        MConstant *constant = MConstant::New(alloc(), v);
-        curBlock_->add(constant);
-        return constant;
-    }
-
-    MDefinition *constantFloat(float f)
-    {
-        if (!curBlock_)
-            return NULL;
-
-        MConstant *constant = MConstant::NewAsmJS(alloc(), DoubleValue(double(f)), MIRType_Float32);
+        MConstant *constant = MConstant::NewAsmJS(alloc(), v, t.toMIRType());
         curBlock_->add(constant);
         return constant;
     }
 
     template <class T>
     MDefinition *unary(MDefinition *op)
     {
         if (!curBlock_)
@@ -2921,96 +2954,54 @@ CheckPrecedingStatements(ModuleCompiler 
 
     return true;
 }
 
 static bool
 CheckGlobalVariableInitConstant(ModuleCompiler &m, PropertyName *varName, ParseNode *initNode,
                                 bool isConst)
 {
-    NumLit literal = ExtractNumericLiteral(initNode);
-    VarType type;
-    switch (literal.which()) {
-      case NumLit::Fixnum:
-      case NumLit::NegativeInt:
-      case NumLit::BigUnsigned:
-        type = VarType::Int;
-        break;
-      case NumLit::Double:
-        type = VarType::Double;
-        break;
-      case NumLit::OutOfRangeInt:
+    NumLit literal = ExtractNumericLiteral(m, initNode);
+    if (!literal.hasType())
         return m.fail(initNode, "global initializer is out of representable integer range");
-    }
-    return m.addGlobalVarInitConstant(varName, type, literal.value(), isConst);
-}
-
-static bool
-CheckFloat32Coercion(ModuleCompiler &m, ParseNode *callNode, ParseNode **coercedExpr,
-                     const char* errorMessage)
-{
-    JS_ASSERT(callNode->isKind(PNK_CALL));
-
-    ParseNode *callee = CallCallee(callNode);
-    if (!callee->isKind(PNK_NAME))
-        return m.fail(callee, errorMessage);
-
-    PropertyName *calleeName = callee->name();
-
-    const ModuleCompiler::Global *global = m.lookupGlobal(calleeName);
-    if (!global || global->which() != ModuleCompiler::Global::MathBuiltin ||
-        global->mathBuiltin() != AsmJSMathBuiltin_fround)
-    {
-        return m.fail(callee, errorMessage);
-    }
-
-    unsigned numArgs = CallArgListLength(callNode);
-    if (numArgs != 1)
-        return m.failf(callee, "fround passed %u arguments, expected one", numArgs);
-
-    if (coercedExpr)
-        *coercedExpr = CallArgList(callNode);
-    return true;
+
+    return m.addGlobalVarInitConstant(varName, literal.varType(), literal.value(), isConst);
 }
 
 static bool
 CheckTypeAnnotation(ModuleCompiler &m, ParseNode *coercionNode, AsmJSCoercion *coercion,
                     ParseNode **coercedExpr = nullptr)
 {
-    static const char *errorMessage = "in coercion expression, the expression must be of the form +x, fround(x) or x|0";
     switch (coercionNode->getKind()) {
       case PNK_BITOR: {
         ParseNode *rhs = BinaryRight(coercionNode);
-
-        if (!IsNumericLiteral(rhs))
+        uint32_t i;
+        if (!IsLiteralInt(m, rhs, &i) || i != 0)
             return m.fail(rhs, "must use |0 for argument/return coercion");
-
-        NumLit rhsLiteral = ExtractNumericLiteral(rhs);
-        if (rhsLiteral.which() != NumLit::Fixnum || rhsLiteral.toInt32() != 0)
-            return m.fail(rhs, "must use |0 for argument/return coercion");
-
         *coercion = AsmJS_ToInt32;
         if (coercedExpr)
             *coercedExpr = BinaryLeft(coercionNode);
         return true;
       }
       case PNK_POS: {
         *coercion = AsmJS_ToNumber;
         if (coercedExpr)
             *coercedExpr = UnaryKid(coercionNode);
         return true;
       }
       case PNK_CALL: {
         *coercion = AsmJS_FRound;
-        return CheckFloat32Coercion(m, coercionNode, coercedExpr, errorMessage);
+        if (!IsFloatCoercion(m, coercionNode, coercedExpr))
+            return m.fail(coercionNode, "call must be to fround coercion");
+        return true;
       }
       default:;
     }
 
-    return m.fail(coercionNode, errorMessage);
+    return m.fail(coercionNode, "must be of the form +x, fround(x) or x|0");
 }
 
 static bool
 CheckGlobalVariableImportExpr(ModuleCompiler &m, PropertyName *varName, AsmJSCoercion coercion,
                               ParseNode *coercedExpr, bool isConst)
 {
     if (!coercedExpr->isKind(PNK_DOT))
         return m.failName(coercedExpr, "invalid import expression for global '%s'", varName);
@@ -3034,34 +3025,16 @@ CheckGlobalVariableInitImport(ModuleComp
     AsmJSCoercion coercion;
     ParseNode *coercedExpr;
     if (!CheckTypeAnnotation(m, initNode, &coercion, &coercedExpr))
         return false;
     return CheckGlobalVariableImportExpr(m, varName, coercion, coercedExpr, isConst);
 }
 
 static bool
-CheckGlobalVariableInitFloat32(ModuleCompiler &m, PropertyName *varName, ParseNode *initNode,
-                               bool isConst)
-{
-    ParseNode *arg = NULL;
-    if (!CheckFloat32Coercion(m, initNode, &arg, "call must be of the form fround(x)"))
-        return false;
-
-    if (IsNumericLiteral(arg)) {
-        double value;
-        if (!ExtractFRoundableLiteral(arg, &value))
-            return m.fail(arg, "float global initializer needs to be a double literal");
-        return m.addGlobalVarInitConstant(varName, VarType::Float, DoubleValue(value), isConst);
-    }
-
-    return CheckGlobalVariableImportExpr(m, varName, AsmJSCoercion::AsmJS_FRound, arg, isConst);
-}
-
-static bool
 CheckNewArrayView(ModuleCompiler &m, PropertyName *varName, ParseNode *newExpr)
 {
     ParseNode *ctorExpr = ListHead(newExpr);
     if (!ctorExpr->isKind(PNK_DOT))
         return m.fail(ctorExpr, "only valid 'new' import is 'new global.*Array(buf)'");
 
     ParseNode *base = DotBase(ctorExpr);
     PropertyName *field = DotMember(ctorExpr);
@@ -3147,25 +3120,22 @@ CheckModuleGlobal(ModuleCompiler &m, Par
 
     if (!CheckModuleLevelName(m, var, var->name()))
         return false;
 
     ParseNode *initNode = MaybeDefinitionInitializer(var);
     if (!initNode)
         return m.fail(var, "module import needs initializer");
 
-    if (IsNumericLiteral(initNode))
+    if (IsNumericLiteral(m, initNode))
         return CheckGlobalVariableInitConstant(m, var->name(), initNode, isConst);
 
-    if (initNode->isKind(PNK_BITOR) || initNode->isKind(PNK_POS))
+    if (initNode->isKind(PNK_BITOR) || initNode->isKind(PNK_POS) || initNode->isKind(PNK_CALL))
         return CheckGlobalVariableInitImport(m, var->name(), initNode, isConst);
 
-    if (initNode->isKind(PNK_CALL))
-        return CheckGlobalVariableInitFloat32(m, var->name(), initNode, isConst);
-
     if (initNode->isKind(PNK_NEW))
         return CheckNewArrayView(m, var->name(), initNode);
 
     if (initNode->isKind(PNK_DOT))
         return CheckGlobalDotImport(m, var->name(), initNode);
 
     return m.fail(initNode, "unsupported import expression");
 }
@@ -3251,28 +3221,31 @@ CheckArguments(FunctionCompiler &f, Pars
     return true;
 }
 
 static bool
 CheckFinalReturn(FunctionCompiler &f, ParseNode *stmt, RetType *retType)
 {
     if (stmt && stmt->isKind(PNK_RETURN)) {
         if (ParseNode *coercionNode = UnaryKid(stmt)) {
-            if (IsNumericLiteral(coercionNode)) {
-                switch (ExtractNumericLiteral(coercionNode).which()) {
+            if (IsNumericLiteral(f.m(), coercionNode)) {
+                switch (ExtractNumericLiteral(f.m(), coercionNode).which()) {
                   case NumLit::BigUnsigned:
                   case NumLit::OutOfRangeInt:
                     return f.fail(coercionNode, "returned literal is out of integer range");
                   case NumLit::Fixnum:
                   case NumLit::NegativeInt:
                     *retType = RetType::Signed;
                     break;
                   case NumLit::Double:
                     *retType = RetType::Double;
                     break;
+                  case NumLit::Float:
+                    *retType = RetType::Float;
+                    break;
                 }
                 return true;
             }
 
             AsmJSCoercion coercion;
             if (!CheckTypeAnnotation(f.m(), coercionNode, &coercion))
                 return false;
 
@@ -3299,47 +3272,24 @@ CheckVariable(FunctionCompiler &f, Parse
 
     if (!CheckIdentifier(f.m(), var, name))
         return false;
 
     ParseNode *initNode = MaybeDefinitionInitializer(var);
     if (!initNode)
         return f.failName(var, "var '%s' needs explicit type declaration via an initial value", name);
 
-    if (initNode->isKind(PNK_CALL)) {
-        ParseNode *coercedVar = NULL;
-        if (!CheckFloat32Coercion(f.m(), initNode, &coercedVar, "caller in var initializer can only be fround"))
-            return false;
-
-        double value;
-        if (!ExtractFRoundableLiteral(coercedVar, &value))
-            return f.failName(coercedVar, "float initializer for '%s' needs to be a double literal", name);
-
-        return f.addVariable(var, name, VarType::Float, DoubleValue(value));
-    }
-
-    if (!IsNumericLiteral(initNode))
+    if (!IsNumericLiteral(f.m(), initNode))
         return f.failName(initNode, "initializer for '%s' needs to be a numeric literal", name);
 
-    NumLit literal = ExtractNumericLiteral(initNode);
-    VarType type;
-    switch (literal.which()) {
-      case NumLit::Fixnum:
-      case NumLit::NegativeInt:
-      case NumLit::BigUnsigned:
-        type = VarType::Int;
-        break;
-      case NumLit::Double:
-        type = VarType::Double;
-        break;
-      case NumLit::OutOfRangeInt:
+    NumLit literal = ExtractNumericLiteral(f.m(), initNode);
+    if (!literal.hasType())
         return f.failName(initNode, "initializer for '%s' is out of range", name);
-    }
-
-    return f.addVariable(var, name, type, literal.value());
+
+    return f.addVariable(var, name, literal.varType(), literal.value());
 }
 
 static bool
 CheckVariables(FunctionCompiler &f, ParseNode **stmtIter)
 {
     ParseNode *stmt = *stmtIter;
 
     for (; stmt && stmt->isKind(PNK_VAR); stmt = NextNonEmptyStatement(stmt)) {
@@ -3354,31 +3304,22 @@ CheckVariables(FunctionCompiler &f, Pars
 }
 
 static bool
 CheckExpr(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type);
 
 static bool
 CheckNumericLiteral(FunctionCompiler &f, ParseNode *num, MDefinition **def, Type *type)
 {
-    JS_ASSERT(IsNumericLiteral(num));
-    NumLit literal = ExtractNumericLiteral(num);
-
-    switch (literal.which()) {
-      case NumLit::Fixnum:
-      case NumLit::NegativeInt:
-      case NumLit::BigUnsigned:
-      case NumLit::Double:
-        break;
-      case NumLit::OutOfRangeInt:
+    NumLit literal = ExtractNumericLiteral(f.m(), num);
+    if (!literal.hasType())
         return f.fail(num, "numeric literal out of representable integer range");
-    }
 
     *type = literal.type();
-    *def = f.constant(literal.value());
+    *def = f.constant(literal.value(), literal.type());
     return true;
 }
 
 static bool
 CheckVarRef(FunctionCompiler &f, ParseNode *varRef, MDefinition **def, Type *type)
 {
     PropertyName *name = varRef->name();
 
@@ -3386,17 +3327,17 @@ CheckVarRef(FunctionCompiler &f, ParseNo
         *def = f.getLocalDef(*local);
         *type = local->type.toType();
         return true;
     }
 
     if (const ModuleCompiler::Global *global = f.lookupGlobal(name)) {
         switch (global->which()) {
           case ModuleCompiler::Global::Constant:
-            *def = f.constant(DoubleValue(global->constant()));
+            *def = f.constant(DoubleValue(global->constant()), Type::Double);
             *type = Type::Double;
             break;
           case ModuleCompiler::Global::Variable:
             *def = f.loadGlobalVar(*global);
             *type = global->varType().toType();
             break;
           case ModuleCompiler::Global::Function:
           case ModuleCompiler::Global::FFI:
@@ -3409,26 +3350,28 @@ CheckVarRef(FunctionCompiler &f, ParseNo
     }
 
     return f.failName(varRef, "'%s' not found in local or asm.js module scope", name);
 }
 
 static inline bool
 IsLiteralOrConstInt(FunctionCompiler &f, ParseNode *pn, uint32_t *u32)
 {
-    if (IsLiteralInt(pn, u32))
+    if (IsLiteralInt(f.m(), pn, u32))
         return true;
 
     if (pn->getKind() != PNK_NAME)
         return false;
 
     PropertyName *name = pn->name();
     const ModuleCompiler::Global *global = f.lookupGlobal(name);
-    if (!global || global->which() != ModuleCompiler::Global::Variable ||
-        !global->varIsLitConstant()) {
+    if (!global ||
+        global->which() != ModuleCompiler::Global::Variable ||
+        !global->varIsLitConstant())
+    {
         return false;
     }
 
     const Value &v = global->litConstValue();
     if (!v.isInt32())
         return false;
 
     *u32 = (uint32_t) v.toInt32();
@@ -3480,32 +3423,32 @@ CheckArrayAccess(FunctionCompiler &f, Pa
         if (pointer > (uint32_t(INT32_MAX) >> TypedArrayShift(*viewType)))
             return f.fail(indexExpr, "constant index out of range");
         pointer <<= TypedArrayShift(*viewType);
         // It is adequate to note pointer+1 rather than rounding up to the next
         // access-size boundary because access is always aligned and the constraint
         // will be rounded up to a larger alignment later.
         f.m().requireHeapLengthToBeAtLeast(uint32_t(pointer) + 1);
         *needsBoundsCheck = NO_BOUNDS_CHECK;
-        *def = f.constant(Int32Value(pointer));
+        *def = f.constant(Int32Value(pointer), Type::Int);
         return true;
     }
 
     // Mask off the low bits to account for the clearing effect of a right shift
     // followed by the left shift implicit in the array access. E.g., H32[i>>2]
     // loses the low two bits.
     int32_t mask = ~((uint32_t(1) << TypedArrayShift(*viewType)) - 1);
 
     MDefinition *pointerDef;
     if (indexExpr->isKind(PNK_RSH)) {
         ParseNode *shiftNode = BinaryRight(indexExpr);
         ParseNode *pointerNode = BinaryLeft(indexExpr);
 
         uint32_t shift;
-        if (!IsLiteralInt(shiftNode, &shift))
+        if (!IsLiteralInt(f.m(), shiftNode, &shift))
             return f.failf(shiftNode, "shift amount must be constant");
 
         unsigned requiredShift = TypedArrayShift(*viewType);
         if (shift != requiredShift)
             return f.failf(shiftNode, "shift amount must be %u", requiredShift);
 
         if (pointerNode->isKind(PNK_BITAND))
             FoldMaskedArrayIndex(f, &pointerNode, &mask, needsBoundsCheck);
@@ -3513,17 +3456,17 @@ CheckArrayAccess(FunctionCompiler &f, Pa
         // Fold a 'literal constant right shifted' now, and skip the bounds check if
         // currently possible. This handles the optimization of many of these uses without
         // the need for range analysis, and saves the generation of a MBitAnd op.
         if (IsLiteralOrConstInt(f, pointerNode, &pointer) && pointer <= uint32_t(INT32_MAX)) {
             // Cases: b[c>>n], and b[(c&m)>>n]
             pointer &= mask;
             if (pointer < f.m().minHeapLength())
                 *needsBoundsCheck = NO_BOUNDS_CHECK;
-            *def = f.constant(Int32Value(pointer));
+            *def = f.constant(Int32Value(pointer), Type::Int);
             return true;
         }
 
         Type pointerType;
         if (!CheckExpr(f, pointerNode, &pointerDef, &pointerType))
             return false;
 
         if (!pointerType.isIntish())
@@ -3551,17 +3494,17 @@ CheckArrayAccess(FunctionCompiler &f, Pa
         }
     }
 
     // Don't generate the mask op if there is no need for it which could happen for
     // a shift of zero.
     if (mask == -1)
         *def = pointerDef;
     else
-        *def = f.bitwise<MBitAnd>(pointerDef, f.constant(Int32Value(mask)));
+        *def = f.bitwise<MBitAnd>(pointerDef, f.constant(Int32Value(mask), Type::Int));
 
     return true;
 }
 
 static bool
 CheckLoadArray(FunctionCompiler &f, ParseNode *elem, MDefinition **def, Type *type)
 {
     ArrayBufferView::ViewType viewType;
@@ -3917,17 +3860,17 @@ CheckFuncPtrCall(FunctionCompiler &f, Pa
 
     if (!indexExpr->isKind(PNK_BITAND))
         return f.fail(indexExpr, "function-pointer table index expression needs & mask");
 
     ParseNode *indexNode = BinaryLeft(indexExpr);
     ParseNode *maskNode = BinaryRight(indexExpr);
 
     uint32_t mask;
-    if (!IsLiteralInt(maskNode, &mask) || mask == UINT32_MAX || !IsPowerOfTwo(mask + 1))
+    if (!IsLiteralInt(f.m(), maskNode, &mask) || mask == UINT32_MAX || !IsPowerOfTwo(mask + 1))
         return f.fail(maskNode, "function-pointer table index mask value must be a power of two");
 
     MDefinition *indexDef;
     Type indexType;
     if (!CheckExpr(f, indexNode, &indexDef, &indexType))
         return false;
 
     if (!indexType.isIntish())
@@ -3979,35 +3922,21 @@ CheckFFICall(FunctionCompiler &f, ParseN
 
     *type = retType.toType();
     return true;
 }
 
 static bool CheckCall(FunctionCompiler &f, ParseNode *call, RetType retType, MDefinition **def, Type *type);
 
 static bool
-CheckFRoundArg(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type, const char* error)
-{
-    ParseNode *arg = NULL;
-    if (!CheckFloat32Coercion(f.m(), expr, &arg, error))
-        return false;
-
+CheckFRoundArg(FunctionCompiler &f, ParseNode *arg, MDefinition **def, Type *type)
+{
     if (arg->isKind(PNK_CALL))
         return CheckCall(f, arg, RetType::Float, def, type);
 
-    if (IsNumericLiteral(arg)) {
-        double value;
-        if (!ExtractFRoundableLiteral(arg, &value))
-            return f.fail(arg, "call to fround with literal expects the literal to be a double");
-
-        *def = f.constantFloat(value);
-        *type = Type::Float;
-        return true;
-    }
-
     MDefinition *inputDef;
     Type inputType;
     if (!CheckExpr(f, arg, &inputDef, &inputType))
         return false;
 
     if (inputType.isMaybeDouble() || inputType.isSigned())
         *def = f.unary<MToFloat32>(inputDef);
     else if (inputType.isUnsigned())
@@ -4017,22 +3946,28 @@ CheckFRoundArg(FunctionCompiler &f, Pars
     else
         return f.failf(arg, "%s is not a subtype of signed, unsigned, double? or floatish", inputType.toChars());
 
     *type = Type::Float;
     return true;
 }
 
 static bool
-CheckFRound(FunctionCompiler &f, ParseNode *callNode, RetType retType, MDefinition **def, Type *type)
-{
+CheckMathFRound(FunctionCompiler &f, ParseNode *callNode, RetType retType, MDefinition **def, Type *type)
+{
+    ParseNode *argNode = nullptr;
+    if (!IsFloatCoercion(f.m(), callNode, &argNode))
+        return f.fail(callNode, "invalid call to fround");
+
     MDefinition *operand;
     Type operandType;
-    if (!CheckFRoundArg(f, callNode, &operand, &operandType, "coercion to float should use fround"))
-        return false;
+    if (!CheckFRoundArg(f, argNode, &operand, &operandType))
+        return false;
+
+    JS_ASSERT(operandType == Type::Float);
 
     switch (retType.which()) {
       case RetType::Double:
         *def = f.unary<MToDouble>(operand);
         *type = Type::Double;
         return true;
       case RetType::Signed:
         *def = f.unary<MTruncateToInt32>(operand);
@@ -4071,17 +4006,17 @@ CheckMathBuiltinCall(FunctionCompiler &f
                      RetType retType, MDefinition **def, Type *type)
 {
     unsigned arity = 0;
     AsmJSImmKind doubleCallee, floatCallee;
     switch (mathBuiltin) {
       case AsmJSMathBuiltin_imul:   return CheckMathIMul(f, callNode, retType, def, type);
       case AsmJSMathBuiltin_abs:    return CheckMathAbs(f, callNode, retType, def, type);
       case AsmJSMathBuiltin_sqrt:   return CheckMathSqrt(f, callNode, retType, def, type);
-      case AsmJSMathBuiltin_fround: return CheckFRound(f, callNode, retType, def, type);
+      case AsmJSMathBuiltin_fround: return CheckMathFRound(f, callNode, retType, def, type);
       case AsmJSMathBuiltin_sin:    arity = 1; doubleCallee = AsmJSImm_SinD; floatCallee = AsmJSImm_SinF;      break;
       case AsmJSMathBuiltin_cos:    arity = 1; doubleCallee = AsmJSImm_CosD; floatCallee = AsmJSImm_CosF;      break;
       case AsmJSMathBuiltin_tan:    arity = 1; doubleCallee = AsmJSImm_TanD; floatCallee = AsmJSImm_TanF;      break;
       case AsmJSMathBuiltin_asin:   arity = 1; doubleCallee = AsmJSImm_ASinD; floatCallee = AsmJSImm_ASinF;    break;
       case AsmJSMathBuiltin_acos:   arity = 1; doubleCallee = AsmJSImm_ACosD; floatCallee = AsmJSImm_ACosF;    break;
       case AsmJSMathBuiltin_atan:   arity = 1; doubleCallee = AsmJSImm_ATanD; floatCallee = AsmJSImm_ATanF;    break;
       case AsmJSMathBuiltin_ceil:   arity = 1; doubleCallee = AsmJSImm_CeilD; floatCallee = AsmJSImm_CeilF;    break;
       case AsmJSMathBuiltin_floor:  arity = 1; doubleCallee = AsmJSImm_FloorD; floatCallee = AsmJSImm_FloorF;  break;
@@ -4352,30 +4287,31 @@ CheckConditional(FunctionCompiler &f, Pa
     if (!f.joinIfElse(thenBlocks, elseExpr))
         return false;
 
     *def = f.popPhiOutput();
     return true;
 }
 
 static bool
-IsValidIntMultiplyConstant(ParseNode *expr)
-{
-    if (!IsNumericLiteral(expr))
-        return false;
-
-    NumLit literal = ExtractNumericLiteral(expr);
+IsValidIntMultiplyConstant(ModuleCompiler &m, ParseNode *expr)
+{
+    if (!IsNumericLiteral(m, expr))
+        return false;
+
+    NumLit literal = ExtractNumericLiteral(m, expr);
     switch (literal.which()) {
       case NumLit::Fixnum:
       case NumLit::NegativeInt:
         if (abs(literal.toInt32()) < (1<<20))
             return true;
         return false;
       case NumLit::BigUnsigned:
       case NumLit::Double:
+      case NumLit::Float:
       case NumLit::OutOfRangeInt:
         return false;
     }
 
     MOZ_ASSUME_UNREACHABLE("Bad literal");
 }
 
 static bool
@@ -4391,17 +4327,17 @@ CheckMultiply(FunctionCompiler &f, Parse
         return false;
 
     MDefinition *rhsDef;
     Type rhsType;
     if (!CheckExpr(f, rhs, &rhsDef, &rhsType))
         return false;
 
     if (lhsType.isInt() && rhsType.isInt()) {
-        if (!IsValidIntMultiplyConstant(lhs) && !IsValidIntMultiplyConstant(rhs))
+        if (!IsValidIntMultiplyConstant(f.m(), lhs) && !IsValidIntMultiplyConstant(f.m(), rhs))
             return f.fail(star, "one arg to int multiply must be a small (-2^20, 2^20) int literal");
         *def = f.mul(lhsDef, rhsDef, MIRType_Int32, MMul::Integer);
         *type = Type::Intish;
         return true;
     }
 
     if (lhsType.isMaybeDouble() && rhsType.isMaybeDouble()) {
         *def = f.mul(lhsDef, rhsDef, MIRType_Double, MMul::Normal);
@@ -4589,26 +4525,27 @@ CheckBitwise(FunctionCompiler &f, ParseN
       case PNK_BITAND: identityElement = -1; onlyOnRight = false; *type = Type::Signed;   break;
       case PNK_BITXOR: identityElement = 0;  onlyOnRight = false; *type = Type::Signed;   break;
       case PNK_LSH:    identityElement = 0;  onlyOnRight = true;  *type = Type::Signed;   break;
       case PNK_RSH:    identityElement = 0;  onlyOnRight = true;  *type = Type::Signed;   break;
       case PNK_URSH:   identityElement = 0;  onlyOnRight = true;  *type = Type::Unsigned; break;
       default: MOZ_ASSUME_UNREACHABLE("not a bitwise op");
     }
 
-    if (!onlyOnRight && IsBits32(lhs, identityElement)) {
+    uint32_t i;
+    if (!onlyOnRight && IsLiteralInt(f.m(), lhs, &i) && i == uint32_t(identityElement)) {
         Type rhsType;
         if (!CheckExpr(f, rhs, def, &rhsType))
             return false;
         if (!rhsType.isIntish())
             return f.failf(bitwise, "%s is not a subtype of intish", rhsType.toChars());
         return true;
     }
 
-    if (IsBits32(rhs, identityElement)) {
+    if (IsLiteralInt(f.m(), rhs, &i) && i == uint32_t(identityElement)) {
         if (bitwise->isKind(PNK_BITOR) && lhs->isKind(PNK_CALL))
             return CheckCall(f, lhs, RetType::Signed, def, type);
 
         Type lhsType;
         if (!CheckExpr(f, lhs, def, &lhsType))
             return false;
         if (!lhsType.isIntish())
             return f.failf(bitwise, "%s is not a subtype of intish", lhsType.toChars());
@@ -4641,34 +4578,37 @@ CheckBitwise(FunctionCompiler &f, ParseN
     }
 
     return true;
 }
 
 static bool
 CheckUncoercedCall(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type)
 {
-    static const char* callError = "all function calls must either be ignored (via "
-                                   "f(); or comma-expression), coerced to signed "
-                                   "(via f()|0), coerced to float (via fround(f()))"
-                                   " or coerced to double (via +f())";
-
     JS_ASSERT(expr->isKind(PNK_CALL));
-    return CheckFRoundArg(f, expr, def, type, callError);
+
+    ParseNode *arg;
+    if (!IsFloatCoercion(f.m(), expr, &arg)) {
+        return f.fail(expr, "all function calls must either be ignored (via f(); or "
+                            "comma-expression), coerced to signed (via f()|0), coerced to float "
+                            "(via fround(f())) or coerced to double (via +f())");
+    }
+
+    return CheckFRoundArg(f, arg, def, type);
 }
 
 static bool
 CheckExpr(FunctionCompiler &f, ParseNode *expr, MDefinition **def, Type *type)
 {
     JS_CHECK_RECURSION_DONT_REPORT(f.cx(), return f.m().failOverRecursed());
 
     if (!f.mirGen().ensureBallast())
         return false;
 
-    if (IsNumericLiteral(expr))
+    if (IsNumericLiteral(f.m(), expr))
         return CheckNumericLiteral(f, expr, def, type);
 
     switch (expr->getKind()) {
       case PNK_NAME:        return CheckVarRef(f, expr, def, type);
       case PNK_ELEM:        return CheckLoadArray(f, expr, def, type);
       case PNK_ASSIGN:      return CheckAssign(f, expr, def, type);
       case PNK_POS:         return CheckPos(f, expr, def, type);
       case PNK_NOT:         return CheckNot(f, expr, def, type);
@@ -4787,17 +4727,17 @@ CheckFor(FunctionCompiler &f, ParseNode 
     if (maybeCond) {
         Type condType;
         if (!CheckExpr(f, maybeCond, &condDef, &condType))
             return false;
 
         if (!condType.isInt())
             return f.failf(maybeCond, "%s is not a subtype of int", condType.toChars());
     } else {
-        condDef = f.constant(Int32Value(1));
+        condDef = f.constant(Int32Value(1), Type::Int);
     }
 
     MBasicBlock *afterLoop;
     if (!f.branchAndStartLoopBody(condDef, &afterLoop, body, NextNode(forStmt)))
         return false;
 
     if (!CheckStatement(f, body))
         return false;
@@ -4925,29 +4865,30 @@ CheckIf(FunctionCompiler &f, ParseNode *
     }
 
     return true;
 }
 
 static bool
 CheckCaseExpr(FunctionCompiler &f, ParseNode *caseExpr, int32_t *value)
 {
-    if (!IsNumericLiteral(caseExpr))
+    if (!IsNumericLiteral(f.m(), caseExpr))
         return f.fail(caseExpr, "switch case expression must be an integer literal");
 
-    NumLit literal = ExtractNumericLiteral(caseExpr);
+    NumLit literal = ExtractNumericLiteral(f.m(), caseExpr);
     switch (literal.which()) {
       case NumLit::Fixnum:
       case NumLit::NegativeInt:
         *value = literal.toInt32();
         break;
       case NumLit::OutOfRangeInt:
       case NumLit::BigUnsigned:
         return f.fail(caseExpr, "switch case expression out of integer range");
       case NumLit::Double:
+      case NumLit::Float:
         return f.fail(caseExpr, "switch case expression must be an integer literal");
     }
 
     return true;
 }
 
 static bool
 CheckDefaultAtEnd(FunctionCompiler &f, ParseNode *stmt)
@@ -5030,17 +4971,17 @@ CheckSwitch(FunctionCompiler &f, ParseNo
     if (!cases.resize(tableLength))
         return false;
 
     MBasicBlock *switchBlock;
     if (!f.startSwitch(switchStmt, exprDef, low, high, &switchBlock))
         return false;
 
     for (; stmt && stmt->isKind(PNK_CASE); stmt = NextNode(stmt)) {
-        int32_t caseValue = ExtractNumericLiteral(CaseExpr(stmt)).toInt32();
+        int32_t caseValue = ExtractNumericLiteral(f.m(), CaseExpr(stmt)).toInt32();
         unsigned caseIndex = caseValue - low;
 
         if (cases[caseIndex])
             return f.fail(stmt, "no duplicate case labels");
 
         if (!f.startSwitchCase(switchBlock, &cases[caseIndex], stmt))
             return false;
 
@@ -5256,17 +5197,17 @@ CheckFunction(ModuleCompiler &m, LifoAll
     RetType retType;
     if (!CheckFinalReturn(f, lastNonEmptyStmt, &retType))
         return false;
 
     if (!CheckReturnType(f, lastNonEmptyStmt, retType))
         return false;
 
     Signature sig(Move(argTypes), retType);
-    ModuleCompiler::Func *func;
+    ModuleCompiler::Func *func = nullptr;
     if (!CheckFunctionSignature(m, fn, Move(sig), FunctionName(fn), &func))
         return false;
 
     if (func->defined())
         return m.failName(fn, "function '%s' already defined", FunctionName(fn));
 
     func->define(fn->pn_pos.begin);
     func->accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC);
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -6310,17 +6310,17 @@ IonBuilder::getStaticName(JSObject *stat
     if (staticType->unknownProperties()) {
         *psucceeded = false;
         return true;
     }
 
     types::HeapTypeSetKey property = staticType->property(id);
     if (!property.maybeTypes() ||
         !property.maybeTypes()->definiteProperty() ||
-        property.configured(constraints()))
+        property.nonData(constraints()))
     {
         // The property has been reconfigured as non-configurable, non-enumerable
         // or non-writable.
         *psucceeded = false;
         return true;
     }
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
@@ -6399,17 +6399,18 @@ IonBuilder::setStaticName(JSObject *stat
 
     types::TypeObjectKey *staticType = types::TypeObjectKey::get(staticObject);
     if (staticType->unknownProperties())
         return jsop_setprop(name);
 
     types::HeapTypeSetKey property = staticType->property(id);
     if (!property.maybeTypes() ||
         !property.maybeTypes()->definiteProperty() ||
-        property.configured(constraints()))
+        property.nonData(constraints()) ||
+        property.nonWritable(constraints()))
     {
         // The property has been reconfigured as non-configurable, non-enumerable
         // or non-writable.
         return jsop_setprop(name);
     }
 
     if (!TypeSetIncludes(property.maybeTypes(), value->type(), value->resultTypeSet()))
         return jsop_setprop(name);
@@ -7849,17 +7850,17 @@ IonBuilder::getDefiniteSlot(types::Tempo
     if (type->unknownProperties() || type->singleton())
         return false;
 
     jsid id = NameToId(name);
 
     *property = type->property(id);
     return property->maybeTypes() &&
            property->maybeTypes()->definiteProperty() &&
-           !property->configured(constraints());
+           !property->nonData(constraints());
 }
 
 bool
 IonBuilder::jsop_runonce()
 {
     MRunOncePrologue *ins = MRunOncePrologue::New(alloc());
     current->add(ins);
     return resumeAfter(ins);
@@ -7914,17 +7915,17 @@ IonBuilder::objectsHaveCommonPrototype(t
             if (!isGetter && clasp->ops.setGeneric)
                 return false;
 
             // Test for isOwnProperty() without freezing. If we end up
             // optimizing, freezePropertiesForCommonPropFunc will freeze the
             // property type sets later on.
             types::HeapTypeSetKey property = type->property(NameToId(name));
             if (types::TypeSet *types = property.maybeTypes()) {
-                if (!types->empty() || types->configuredProperty())
+                if (!types->empty() || types->nonDataProperty())
                     return false;
             }
             if (JSObject *obj = type->singleton()) {
                 if (types::CanHaveEmptyPropertyTypesForOwnProperty(obj))
                     return false;
             }
 
             if (!type->hasTenuredProto())
@@ -8910,16 +8911,19 @@ IonBuilder::setPropTryDefiniteSlot(bool 
 
     if (barrier)
         return true;
 
     types::HeapTypeSetKey property;
     if (!getDefiniteSlot(obj->resultTypeSet(), name, &property))
         return true;
 
+    if (property.nonWritable(constraints()))
+        return true;
+
     MStoreFixedSlot *fixed = MStoreFixedSlot::New(alloc(), obj, property.maybeTypes()->definiteSlot(), value);
     current->add(fixed);
     current->push(value);
 
     if (property.needsBarrier(constraints()))
         fixed->setNeedsBarrier();
 
     if (!resumeAfter(fixed))
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -3135,17 +3135,17 @@ jit::PropertyReadIsIdempotent(types::Com
     for (size_t i = 0; i < types->getObjectCount(); i++) {
         types::TypeObjectKey *object = types->getObject(i);
         if (object) {
             if (object->unknownProperties())
                 return false;
 
             // Check if the property has been reconfigured or is a getter.
             types::HeapTypeSetKey property = object->property(NameToId(name));
-            if (property.configured(constraints))
+            if (property.nonData(constraints))
                 return false;
         }
     }
 
     return true;
 }
 
 bool
--- a/js/src/jit/shared/MoveEmitter-x86-shared.cpp
+++ b/js/src/jit/shared/MoveEmitter-x86-shared.cpp
@@ -251,78 +251,72 @@ MoveEmitterX86::breakCycle(const MoveOpe
             masm.store32(to.reg(), cycleSlot());
         }
         break;
 #endif
 #ifndef JS_CPU_X64
       case MoveOp::INT32:
 #endif
       case MoveOp::GENERAL:
-        JS_ASSERT(pushedAtCycle_ == -1);
         masm.Push(toOperand(to));
-        pushedAtCycle_ = masm.framePushed();
         break;
       default:
         MOZ_ASSUME_UNREACHABLE("Unexpected move type");
     }
 }
 
 void
 MoveEmitterX86::completeCycle(const MoveOperand &to, MoveOp::Type type)
 {
-    JS_ASSERT(pushedAtCycle_ != -1);
-
     // There is some pattern:
     //   (A -> B)
     //   (B -> A)
     //
     // This case handles (B -> A), which we reach last. We emit a move from the
     // saved value of B, to A.
     switch (type) {
       case MoveOp::FLOAT32:
+        JS_ASSERT(pushedAtCycle_ != -1);
         JS_ASSERT(pushedAtCycle_ - pushedAtStart_ >= sizeof(float));
         if (to.isMemory()) {
             masm.loadFloat32(cycleSlot(), ScratchFloatReg);
             masm.storeFloat32(ScratchFloatReg, toAddress(to));
         } else {
             masm.loadFloat32(cycleSlot(), to.floatReg());
         }
         break;
       case MoveOp::DOUBLE:
+        JS_ASSERT(pushedAtCycle_ != -1);
         JS_ASSERT(pushedAtCycle_ - pushedAtStart_ >= sizeof(double));
         if (to.isMemory()) {
             masm.loadDouble(cycleSlot(), ScratchFloatReg);
             masm.storeDouble(ScratchFloatReg, toAddress(to));
         } else {
             masm.loadDouble(cycleSlot(), to.floatReg());
         }
         break;
 #ifdef JS_CPU_X64
       case MoveOp::INT32:
+        JS_ASSERT(pushedAtCycle_ != -1);
         JS_ASSERT(pushedAtCycle_ - pushedAtStart_ >= sizeof(int32_t));
         // x64 can't pop to a 32-bit destination.
         if (to.isMemory()) {
             masm.load32(cycleSlot(), ScratchReg);
             masm.store32(ScratchReg, toAddress(to));
         } else {
             masm.load32(cycleSlot(), to.reg());
         }
         break;
 #endif
 #ifndef JS_CPU_X64
       case MoveOp::INT32:
 #endif
       case MoveOp::GENERAL:
-        JS_ASSERT(pushedAtCycle_ - pushedAtStart_ >= sizeof(intptr_t));
-        if (to.isMemory()) {
-            masm.Pop(toPopOperand(to));
-        } else {
-            masm.Pop(to.reg());
-        }
-        pushedAtCycle_ = -1;
+        JS_ASSERT(masm.framePushed() - pushedAtStart_ >= sizeof(intptr_t));
+        masm.Pop(toPopOperand(to));
         break;
       default:
         MOZ_ASSUME_UNREACHABLE("Unexpected move type");
     }
 }
 
 void
 MoveEmitterX86::emitInt32Move(const MoveOperand &from, const MoveOperand &to)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2425,17 +2425,17 @@ JS_SetPrototype(JSContext *cx, JS::Handl
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, proto);
 
     bool succeeded;
     if (!JSObject::setProto(cx, obj, proto, &succeeded))
         return false;
 
     if (!succeeded) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SETPROTOTYPEOF_FAIL);
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL);
         return false;
     }
 
     return true;
 }
 
 JS_PUBLIC_API(JSObject *)
 JS_GetParent(JSObject *obj)
@@ -6035,16 +6035,36 @@ JS_SetGlobalJitCompilerOption(JSContext 
         }
         break;
       default:
         break;
     }
 #endif
 }
 
+JS_PUBLIC_API(int)
+JS_GetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt)
+{
+#ifdef JS_ION
+    switch (opt) {
+      case JSJITCOMPILER_BASELINE_USECOUNT_TRIGGER:
+        return jit::js_JitOptions.baselineUsesBeforeCompile;
+      case JSJITCOMPILER_ION_USECOUNT_TRIGGER:
+        return jit::js_JitOptions.forcedDefaultIonUsesBeforeCompile;
+      case JSJITCOMPILER_ION_ENABLE:
+        return JS::ContextOptionsRef(cx).ion();
+      case JSJITCOMPILER_BASELINE_ENABLE:
+        return JS::ContextOptionsRef(cx).baseline();
+      default:
+        break;
+    }
+#endif
+    return 0;
+}
+
 /************************************************************************/
 
 #if !defined(STATIC_EXPORTABLE_JS_API) && !defined(STATIC_JS_API) && defined(XP_WIN)
 
 #include "jswin.h"
 
 /*
  * Initialization routine for the JS DLL.
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4552,16 +4552,18 @@ typedef enum JSJitCompilerOption {
     JIT_COMPILER_OPTIONS(JIT_COMPILER_DECLARE)
 #undef JIT_COMPILER_DECLARE
 
     JSJITCOMPILER_NOT_AN_OPTION
 } JSJitCompilerOption;
 
 extern JS_PUBLIC_API(void)
 JS_SetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt, uint32_t value);
+extern JS_PUBLIC_API(int)
+JS_GetGlobalJitCompilerOption(JSContext *cx, JSJitCompilerOption opt);
 
 /*
  * Convert a uint32_t index into a jsid.
  */
 extern JS_PUBLIC_API(bool)
 JS_IndexToId(JSContext *cx, uint32_t index, JS::MutableHandleId);
 
 /*
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -411,18 +411,21 @@ ConstraintTypeSet::add(JSContext *cx, Ty
 
     if (callExisting)
         addTypesToConstraint(cx, constraint);
 }
 
 void
 TypeSet::print()
 {
-    if (flags & TYPE_FLAG_CONFIGURED_PROPERTY)
-        fprintf(stderr, " [configured]");
+    if (flags & TYPE_FLAG_NON_DATA_PROPERTY)
+        fprintf(stderr, " [non-data]");
+
+    if (flags & TYPE_FLAG_NON_WRITABLE_PROPERTY)
+        fprintf(stderr, " [non-writable]");
 
     if (definiteProperty())
         fprintf(stderr, " [definite:%d]", definiteSlot());
 
     if (baseFlags() == 0 && !baseObjectCount()) {
         fprintf(stderr, " missing");
         return;
     }
@@ -1179,17 +1182,17 @@ HeapTypeSetKey::knownTypeTag(CompilerCon
     JS_ASSERT_IF(types->empty(), type == JSVAL_TYPE_UNKNOWN);
 
     return type;
 }
 
 bool
 HeapTypeSetKey::isOwnProperty(CompilerConstraintList *constraints)
 {
-    if (maybeTypes() && (!maybeTypes()->empty() || maybeTypes()->configuredProperty()))
+    if (maybeTypes() && (!maybeTypes()->empty() || maybeTypes()->nonDataProperty()))
         return true;
     if (JSObject *obj = object()->singleton()) {
         if (CanHaveEmptyPropertyTypesForOwnProperty(obj))
             return true;
     }
     freeze(constraints);
     return false;
 }
@@ -1216,17 +1219,17 @@ TemporaryTypeSet::getSingleton()
     return getSingleObject(0);
 }
 
 JSObject *
 HeapTypeSetKey::singleton(CompilerConstraintList *constraints)
 {
     HeapTypeSet *types = maybeTypes();
 
-    if (!types || types->configuredProperty() || types->baseFlags() != 0 || types->getObjectCount() != 1)
+    if (!types || types->nonDataProperty() || types->baseFlags() != 0 || types->getObjectCount() != 1)
         return nullptr;
 
     JSObject *obj = types->getSingleObject(0);
 
     if (obj)
         freeze(constraints);
 
     return obj;
@@ -1500,52 +1503,74 @@ ObjectStateChange(ExclusiveContext *cxAr
     }
 }
 
 static void
 CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun);
 
 namespace {
 
-class ConstraintDataFreezeConfiguredProperty
+class ConstraintDataFreezePropertyState
 {
   public:
-    ConstraintDataFreezeConfiguredProperty()
+    enum Which {
+        NON_DATA,
+        NON_WRITABLE
+    } which;
+
+    ConstraintDataFreezePropertyState(Which which)
+      : which(which)
     {}
 
-    const char *kind() { return "freezeConfiguredProperty"; }
+    const char *kind() { return (which == NON_DATA) ? "freezeNonDataProperty" : "freezeNonWritableProperty"; }
 
     bool invalidateOnNewType(Type type) { return false; }
     bool invalidateOnNewPropertyState(TypeSet *property) {
-        return property->configuredProperty();
+        return (which == NON_DATA)
+               ? property->nonDataProperty()
+               : property->nonWritableProperty();
     }
     bool invalidateOnNewObjectState(TypeObject *object) { return false; }
 
     bool constraintHolds(JSContext *cx,
                          const HeapTypeSetKey &property, TemporaryTypeSet *expected)
     {
-        return !property.maybeTypes()->configuredProperty();
+        return !invalidateOnNewPropertyState(property.maybeTypes());
     }
 
     bool shouldSweep() { return false; }
 };
 
 } /* anonymous namespace */
 
 bool
-HeapTypeSetKey::configured(CompilerConstraintList *constraints)
+HeapTypeSetKey::nonData(CompilerConstraintList *constraints)
 {
-    if (maybeTypes() && maybeTypes()->configuredProperty())
+    if (maybeTypes() && maybeTypes()->nonDataProperty())
         return true;
 
     LifoAlloc *alloc = constraints->alloc();
 
-    typedef CompilerConstraintInstance<ConstraintDataFreezeConfiguredProperty> T;
+    typedef CompilerConstraintInstance<ConstraintDataFreezePropertyState> T;
     constraints->add(alloc->new_<T>(alloc, *this,
-                                    ConstraintDataFreezeConfiguredProperty()));
+                                    ConstraintDataFreezePropertyState(ConstraintDataFreezePropertyState::NON_DATA)));
+    return false;
+}
+
+bool
+HeapTypeSetKey::nonWritable(CompilerConstraintList *constraints)
+{
+    if (maybeTypes() && maybeTypes()->nonWritableProperty())
+        return true;
+
+    LifoAlloc *alloc = constraints->alloc();
+
+    typedef CompilerConstraintInstance<ConstraintDataFreezePropertyState> T;
+    constraints->add(alloc->new_<T>(alloc, *this,
+                                    ConstraintDataFreezePropertyState(ConstraintDataFreezePropertyState::NON_WRITABLE)));
     return false;
 }
 
 bool
 TemporaryTypeSet::filtersType(const TemporaryTypeSet *other, Type filteredType) const
 {
     if (other->unknown())
         return unknown();
@@ -2066,17 +2091,17 @@ PrototypeHasIndexedProperty(CompilerCons
 {
     do {
         TypeObjectKey *type = TypeObjectKey::get(obj);
         if (ClassCanHaveExtraProperties(type->clasp()))
             return true;
         if (type->unknownProperties())
             return true;
         HeapTypeSetKey index = type->property(JSID_VOID);
-        if (index.configured(constraints) || index.isOwnProperty(constraints))
+        if (index.nonData(constraints) || index.isOwnProperty(constraints))
             return true;
         if (!obj->hasTenuredProto())
             return true;
         obj = obj->getProto();
     } while (obj);
 
     return false;
 }
@@ -2734,20 +2759,20 @@ TypeObject::setProto(JSContext *cx, Tagg
     setProtoUnchecked(proto);
 }
 
 static inline void
 UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, JSObject *obj, Shape *shape,
                    bool indexed)
 {
     if (!shape->writable())
-        types->setConfiguredProperty(cx);
+        types->setNonWritableProperty(cx);
 
     if (shape->hasGetterValue() || shape->hasSetterValue()) {
-        types->setConfiguredProperty(cx);
+        types->setNonDataProperty(cx);
         if (!types->TypeSet::addType(Type::UnknownType(), &cx->typeLifoAlloc()))
             cx->compartment()->types.setPendingNukeTypes(cx);
     } else if (shape->hasDefaultGetter() && shape->hasSlot()) {
         if (!indexed && types->canSetDefinite(shape->slot()))
             types->setDefinite(shape->slot());
 
         const Value &value = obj->nativeGetSlot(shape->slot());
 
@@ -2804,20 +2829,20 @@ TypeObject::addProperty(ExclusiveContext
             RootedId rootedId(cx, id);
             Shape *shape = singleton()->nativeLookup(cx, rootedId);
             if (shape)
                 UpdatePropertyType(cx, &base->types, singleton(), shape, false);
         }
 
         if (singleton()->watched()) {
             /*
-             * Mark the property as configured, to inhibit optimizations on it
+             * Mark the property as non-data, to inhibit optimizations on it
              * and avoid bypassing the watchpoint handler.
              */
-            base->types.setConfiguredProperty(cx);
+            base->types.setNonDataProperty(cx);
         }
     }
 
     *pprop = base;
 
     InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
               InferSpewColor(&base->types), &base->types, InferSpewColorReset(),
               TypeObjectString(this), TypeIdString(id));
@@ -2923,33 +2948,54 @@ TypeObject::addPropertyType(ExclusiveCon
 
 void
 TypeObject::addPropertyType(ExclusiveContext *cx, const char *name, const Value &value)
 {
     addPropertyType(cx, name, GetValueType(value));
 }
 
 void
-TypeObject::markPropertyConfigured(ExclusiveContext *cx, jsid id)
+TypeObject::markPropertyNonData(ExclusiveContext *cx, jsid id)
 {
     AutoEnterAnalysis enter(cx);
 
     id = IdToTypeId(id);
 
     HeapTypeSet *types = getProperty(cx, id);
     if (types)
-        types->setConfiguredProperty(cx);
+        types->setNonDataProperty(cx);
+}
+
+void
+TypeObject::markPropertyNonWritable(ExclusiveContext *cx, jsid id)
+{
+    AutoEnterAnalysis enter(cx);
+
+    id = IdToTypeId(id);
+
+    HeapTypeSet *types = getProperty(cx, id);
+    if (types)
+        types->setNonWritableProperty(cx);
 }
 
 bool
-TypeObject::isPropertyConfigured(jsid id)
+TypeObject::isPropertyNonData(jsid id)
 {
     TypeSet *types = maybeGetProperty(id);
     if (types)
-        return types->configuredProperty();
+        return types->nonDataProperty();
+    return false;
+}
+
+bool
+TypeObject::isPropertyNonWritable(jsid id)
+{
+    TypeSet *types = maybeGetProperty(id);
+    if (types)
+        return types->nonWritableProperty();
     return false;
 }
 
 void
 TypeObject::markStateChange(ExclusiveContext *cxArg)
 {
     if (unknownProperties())
         return;
@@ -3017,17 +3063,17 @@ TypeObject::markUnknown(ExclusiveContext
      * any properties accessed already accounts for possible values read from them.
      */
 
     unsigned count = getPropertyCount();
     for (unsigned i = 0; i < count; i++) {
         Property *prop = getProperty(i);
         if (prop) {
             prop->types.addType(cx, Type::UnknownType());
-            prop->types.setConfiguredProperty(cx);
+            prop->types.setNonDataProperty(cx);
         }
     }
 }
 
 void
 TypeObject::clearAddendum(ExclusiveContext *cx)
 {
     JS_ASSERT(!(flags() & OBJECT_FLAG_ADDENDUM_CLEARED));
@@ -3081,17 +3127,17 @@ TypeObject::clearNewScriptAddendum(Exclu
      * been deleted/reconfigured, which will have the same effect on JITs
      * wanting to use the definite bits to optimize property accesses.
      */
     for (unsigned i = 0; i < getPropertyCount(); i++) {
         Property *prop = getProperty(i);
         if (!prop)
             continue;
         if (prop->types.definiteProperty())
-            prop->types.setConfiguredProperty(cx);
+            prop->types.setNonDataProperty(cx);
     }
 
     /*
      * If we cleared the new script while in the middle of initializing an
      * object, it will still have the new script's shape and reflect the no
      * longer correct state of the object once its initialization is completed.
      * We can't really detect the possibility of this statically, but the new
      * script keeps track of where each property is initialized so we can walk
@@ -3243,21 +3289,23 @@ class TypeConstraintClearDefiniteGetterS
 
     void newPropertyState(JSContext *cx, TypeSet *source)
     {
         if (!object->hasNewScript())
             return;
         /*
          * Clear out the newScript shape and definite property information from
          * an object if the source type set could be a setter or could be
-         * non-writable, both of which are indicated by the source type set
-         * being marked as configured.
+         * non-writable.
          */
-        if (!(object->flags() & OBJECT_FLAG_ADDENDUM_CLEARED) && source->configuredProperty())
+        if (!(object->flags() & OBJECT_FLAG_ADDENDUM_CLEARED) &&
+            (source->nonDataProperty() || source->nonWritableProperty()))
+        {
             object->clearAddendum(cx);
+        }
     }
 
     void newType(JSContext *cx, TypeSet *source, Type type) {}
 
     TypeConstraint *sweep(TypeZone &zone) {
         if (IsTypeObjectAboutToBeFinalized(&object))
             return nullptr;
         TypeConstraint *res = zone.typeLifoAlloc.new_<TypeConstraintClearDefiniteGetterSetter>(object);
@@ -3276,17 +3324,17 @@ types::AddClearDefiniteGetterSetterForPr
      * properties get cleared from the type.
      */
     RootedObject parent(cx, type->proto().toObjectOrNull());
     while (parent) {
         TypeObject *parentObject = parent->getType(cx);
         if (!parentObject || parentObject->unknownProperties())
             return false;
         HeapTypeSet *parentTypes = parentObject->getProperty(cx, id);
-        if (!parentTypes || parentTypes->configuredProperty())
+        if (!parentTypes || parentTypes->nonDataProperty() || parentTypes->nonWritableProperty())
             return false;
         parentTypes->add(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(type));
         parent = parent->getProto();
     }
     return true;
 }
 
 /*
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -320,17 +320,17 @@ public:
     /* Debugging name for this kind of constraint. */
     virtual const char *kind() = 0;
 
     /* Register a new type for the set this constraint is listening to. */
     virtual void newType(JSContext *cx, TypeSet *source, Type type) = 0;
 
     /*
      * For constraints attached to an object property's type set, mark the
-     * property as having been configured.
+     * property as having its configuration changed.
      */
     virtual void newPropertyState(JSContext *cx, TypeSet *source) {}
 
     /*
      * For constraints attached to the JSID_EMPTY type set on an object,
      * indicate a change in one of the object's dynamic property flags or other
      * state.
      */
@@ -369,32 +369,35 @@ enum MOZ_ENUM_TYPE(uint32_t) {
 
     /* Mask of normal type flags on a type set. */
     TYPE_FLAG_BASE_MASK           = 0x000020ff,
 
     /* Additional flags for HeapTypeSet sets. */
 
     /*
      * Whether the property has ever been deleted or reconfigured to behave
-     * differently from a normal native property (e.g. made non-writable or
-     * given a scripted getter or setter).
+     * differently from a plain data property, other than making the property
+     * non-writable.
      */
-    TYPE_FLAG_CONFIGURED_PROPERTY = 0x00010000,
+    TYPE_FLAG_NON_DATA_PROPERTY = 0x00004000,
+
+    /* Whether the property has ever been made non-writable. */
+    TYPE_FLAG_NON_WRITABLE_PROPERTY = 0x00008000,
 
     /*
      * Whether the property is definitely in a particular slot on all objects
      * from which it has not been deleted or reconfigured. For singletons
      * this may be a fixed or dynamic slot, and for other objects this will be
      * a fixed slot.
      *
      * If the property is definite, mask and shift storing the slot + 1.
      * Otherwise these bits are clear.
      */
-    TYPE_FLAG_DEFINITE_MASK       = 0xfffe0000,
-    TYPE_FLAG_DEFINITE_SHIFT      = 17
+    TYPE_FLAG_DEFINITE_MASK       = 0xffff0000,
+    TYPE_FLAG_DEFINITE_SHIFT      = 16
 };
 typedef uint32_t TypeFlags;
 
 /* Flags and other state stored in TypeObject::flags */
 enum MOZ_ENUM_TYPE(uint32_t) {
     /* Whether this type object is associated with some allocation site. */
     OBJECT_FLAG_FROM_ALLOCATION_SITE  = 0x1,
 
@@ -509,18 +512,21 @@ class TypeSet
     bool unknownObject() const { return !!(flags & (TYPE_FLAG_UNKNOWN | TYPE_FLAG_ANYOBJECT)); }
     bool empty() const { return !baseFlags() && !baseObjectCount(); }
 
     bool hasAnyFlag(TypeFlags flags) const {
         JS_ASSERT((flags & TYPE_FLAG_BASE_MASK) == flags);
         return !!(baseFlags() & flags);
     }
 
-    bool configuredProperty() const {
-        return flags & TYPE_FLAG_CONFIGURED_PROPERTY;
+    bool nonDataProperty() const {
+        return flags & TYPE_FLAG_NON_DATA_PROPERTY;
+    }
+    bool nonWritableProperty() const {
+        return flags & TYPE_FLAG_NON_WRITABLE_PROPERTY;
     }
     bool definiteProperty() const { return flags & TYPE_FLAG_DEFINITE_MASK; }
     unsigned definiteSlot() const {
         JS_ASSERT(definiteProperty());
         return (flags >> TYPE_FLAG_DEFINITE_SHIFT) - 1;
     }
 
     /* Join two type sets into a new set. The result should not be modified further. */
@@ -542,19 +548,16 @@ class TypeSet
     inline TypeObjectKey *getObject(unsigned i) const;
     inline JSObject *getSingleObject(unsigned i) const;
     inline TypeObject *getTypeObject(unsigned i) const;
     inline bool getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **obj) const;
 
     /* The Class of an object in this set. */
     inline const Class *getObjectClass(unsigned i) const;
 
-    void setConfiguredProperty() {
-        flags |= TYPE_FLAG_CONFIGURED_PROPERTY;
-    }
     bool canSetDefinite(unsigned slot) {
         // Note: the cast is required to work around an MSVC issue.
         return (slot + 1) <= (unsigned(TYPE_FLAG_DEFINITE_MASK) >> TYPE_FLAG_DEFINITE_SHIFT);
     }
     void setDefinite(unsigned slot) {
         JS_ASSERT(canSetDefinite(slot));
         flags |= ((slot + 1) << TYPE_FLAG_DEFINITE_SHIFT);
         JS_ASSERT(definiteSlot() == slot);
@@ -608,19 +611,24 @@ class ConstraintTypeSet : public TypeSet
 
 class StackTypeSet : public ConstraintTypeSet
 {
   public:
 };
 
 class HeapTypeSet : public ConstraintTypeSet
 {
+    inline void newPropertyState(ExclusiveContext *cx);
+
   public:
-    /* Mark this type set as representing a configured property. */
-    inline void setConfiguredProperty(ExclusiveContext *cx);
+    /* Mark this type set as representing a non-data property. */
+    inline void setNonDataProperty(ExclusiveContext *cx);
+
+    /* Mark this type set as representing a non-writable property. */
+    inline void setNonWritableProperty(ExclusiveContext *cx);
 };
 
 class CompilerConstraintList;
 
 CompilerConstraintList *
 NewCompilerConstraintList(jit::TempAllocator &alloc);
 
 class TemporaryTypeSet : public TypeSet
@@ -1118,24 +1126,26 @@ struct TypeObject : gc::BarrieredCell<Ty
     bool addProperty(ExclusiveContext *cx, jsid id, Property **pprop);
     bool addDefiniteProperties(ExclusiveContext *cx, JSObject *obj);
     bool matchDefiniteProperties(HandleObject obj);
     void addPrototype(JSContext *cx, TypeObject *proto);
     void addPropertyType(ExclusiveContext *cx, jsid id, Type type);
     void addPropertyType(ExclusiveContext *cx, jsid id, const Value &value);
     void addPropertyType(ExclusiveContext *cx, const char *name, Type type);
     void addPropertyType(ExclusiveContext *cx, const char *name, const Value &value);
-    void markPropertyConfigured(ExclusiveContext *cx, jsid id);
+    void markPropertyNonData(ExclusiveContext *cx, jsid id);
+    void markPropertyNonWritable(ExclusiveContext *cx, jsid id);
     void markStateChange(ExclusiveContext *cx);
     void setFlags(ExclusiveContext *cx, TypeObjectFlags flags);
     void markUnknown(ExclusiveContext *cx);
     void clearAddendum(ExclusiveContext *cx);
     void clearNewScriptAddendum(ExclusiveContext *cx);
     void clearTypedObjectAddendum(ExclusiveContext *cx);
-    bool isPropertyConfigured(jsid id);
+    bool isPropertyNonData(jsid id);
+    bool isPropertyNonWritable(jsid id);
 
     void print();
 
     inline void clearProperties();
     inline void sweep(FreeOp *fop);
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
@@ -1404,17 +1414,18 @@ class HeapTypeSetKey
     TypeObjectKey *object() const { return object_; }
     jsid id() const { return id_; }
     HeapTypeSet *maybeTypes() const { return maybeTypes_; }
 
     bool instantiate(JSContext *cx);
 
     void freeze(CompilerConstraintList *constraints);
     JSValueType knownTypeTag(CompilerConstraintList *constraints);
-    bool configured(CompilerConstraintList *constraints);
+    bool nonData(CompilerConstraintList *constraints);
+    bool nonWritable(CompilerConstraintList *constraints);
     bool isOwnProperty(CompilerConstraintList *constraints);
     bool knownSubset(CompilerConstraintList *constraints, const HeapTypeSetKey &other);
     JSObject *singleton(CompilerConstraintList *constraints);
     bool needsBarrier(CompilerConstraintList *constraints);
 };
 
 /*
  * Information about the result of the compilation of a script.  This structure
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -481,34 +481,46 @@ MarkTypeObjectUnknownProperties(JSContex
     if (cx->typeInferenceEnabled()) {
         if (!obj->unknownProperties())
             obj->markUnknown(cx);
         if (markSetsUnknown && !(obj->flags() & OBJECT_FLAG_SETS_MARKED_UNKNOWN))
             cx->compartment()->types.markSetsUnknown(cx, obj);
     }
 }
 
-/*
- * Mark any property which has been deleted or configured to be non-writable or
- * have a getter/setter.
- */
 inline void
-MarkTypePropertyConfigured(ExclusiveContext *cx, JSObject *obj, jsid id)
+MarkTypePropertyNonData(ExclusiveContext *cx, JSObject *obj, jsid id)
 {
     if (cx->typeInferenceEnabled()) {
         id = IdToTypeId(id);
         if (TrackPropertyTypes(cx, obj, id))
-            obj->type()->markPropertyConfigured(cx, id);
+            obj->type()->markPropertyNonData(cx, id);
+    }
+}
+
+inline void
+MarkTypePropertyNonWritable(ExclusiveContext *cx, JSObject *obj, jsid id)
+{
+    if (cx->typeInferenceEnabled()) {
+        id = IdToTypeId(id);
+        if (TrackPropertyTypes(cx, obj, id))
+            obj->type()->markPropertyNonWritable(cx, id);
     }
 }
 
 inline bool
-IsTypePropertyIdMarkedConfigured(JSObject *obj, jsid id)
+IsTypePropertyIdMarkedNonData(JSObject *obj, jsid id)
 {
-    return obj->type()->isPropertyConfigured(id);
+    return obj->type()->isPropertyNonData(id);
+}
+
+inline bool
+IsTypePropertyIdMarkedNonWritable(JSObject *obj, jsid id)
+{
+    return obj->type()->isPropertyNonWritable(id);
 }
 
 /* Mark a state change on a particular object. */
 inline void
 MarkObjectStateChange(ExclusiveContext *cx, JSObject *obj)
 {
     if (cx->typeInferenceEnabled() && !obj->hasLazyType() && !obj->type()->unknownProperties())
         obj->type()->markStateChange(cx);
@@ -1135,35 +1147,50 @@ ConstraintTypeSet::addType(ExclusiveCont
             constraint = constraint->next;
         }
     } else {
         JS_ASSERT(!constraintList);
     }
 }
 
 inline void
-HeapTypeSet::setConfiguredProperty(ExclusiveContext *cxArg)
+HeapTypeSet::newPropertyState(ExclusiveContext *cxArg)
 {
-    if (flags & TYPE_FLAG_CONFIGURED_PROPERTY)
-        return;
-
-    flags |= TYPE_FLAG_CONFIGURED_PROPERTY;
-
     /* Propagate the change to all constraints. */
     if (JSContext *cx = cxArg->maybeJSContext()) {
         TypeConstraint *constraint = constraintList;
         while (constraint) {
             constraint->newPropertyState(cx, this);
             constraint = constraint->next;
         }
     } else {
         JS_ASSERT(!constraintList);
     }
 }
 
+inline void
+HeapTypeSet::setNonDataProperty(ExclusiveContext *cx)
+{
+    if (flags & TYPE_FLAG_NON_DATA_PROPERTY)
+        return;
+
+    flags |= TYPE_FLAG_NON_DATA_PROPERTY;
+    newPropertyState(cx);
+}
+
+inline void
+HeapTypeSet::setNonWritableProperty(ExclusiveContext *cx)
+{
+    if (flags & TYPE_FLAG_NON_WRITABLE_PROPERTY)
+        return;
+
+    flags |= TYPE_FLAG_NON_WRITABLE_PROPERTY;
+    newPropertyState(cx);
+}
+
 inline unsigned
 TypeSet::getObjectCount() const
 {
     JS_ASSERT(!unknownObject());
     uint32_t count = baseObjectCount();
     if (count > SET_ARRAY_SIZE)
         return HashSetCapacity(count);
     return count;
@@ -1297,17 +1324,17 @@ TypeObject::getProperty(ExclusiveContext
         }
     }
 
     if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
         markUnknown(cx);
 
         /*
          * Return an arbitrary property in the object, as all have unknown
-         * type and are treated as configured.
+         * type and are treated as non-data properties.
          */
         unsigned count = getPropertyCount();
         for (unsigned i = 0; i < count; i++) {
             if (Property *prop = getProperty(i))
                 return &prop->types;
         }
 
         MOZ_ASSUME_UNREACHABLE("Missing property");
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1129,18 +1129,18 @@ JSObject::sealOrFreeze(JSContext *cx, Ha
         }
         Reverse(shapes.begin(), shapes.end());
 
         for (size_t i = 0; i < shapes.length(); i++) {
             StackShape child(shapes[i]);
             StackShape::AutoRooter rooter(cx, &child);
             child.attrs |= getSealedOrFrozenAttributes(child.attrs, it);
 
-            if (!JSID_IS_EMPTY(child.propid))
-                MarkTypePropertyConfigured(cx, obj, child.propid);
+            if (!JSID_IS_EMPTY(child.propid) && it == FREEZE)
+                MarkTypePropertyNonWritable(cx, obj, child.propid);
 
             last = cx->compartment()->propertyTree.getChild(cx, last, obj->numFixedSlots(), child);
             if (!last)
                 return false;
         }
 
         JS_ASSERT(obj->lastProperty()->slotSpan() == last->slotSpan());
         JS_ALWAYS_TRUE(setLastProperty(cx, obj, last));
@@ -3422,24 +3422,30 @@ UpdateShapeTypeAndValue(typename Executi
     if (shape->hasSlot()) {
         if (mode == ParallelExecution) {
             if (!obj->nativeSetSlotIfHasType(shape, value))
                 return false;
         } else {
             obj->nativeSetSlotWithType(cx->asExclusiveContext(), shape, value);
         }
     }
-    if (!shape->hasSlot() || !shape->writable() ||
-        !shape->hasDefaultGetter() || !shape->hasDefaultSetter())
-    {
+    if (!shape->hasSlot() || !shape->hasDefaultGetter() || !shape->hasDefaultSetter()) {
         if (mode == ParallelExecution) {
-            if (!IsTypePropertyIdMarkedConfigured(obj, id))
+            if (!IsTypePropertyIdMarkedNonData(obj, id))
                 return false;
         } else {
-            MarkTypePropertyConfigured(cx->asExclusiveContext(), obj, id);
+            MarkTypePropertyNonData(cx->asExclusiveContext(), obj, id);
+        }
+    }
+    if (!shape->writable()) {
+        if (mode == ParallelExecution) {
+            if (!IsTypePropertyIdMarkedNonWritable(obj, id))
+                return false;
+        } else {
+            MarkTypePropertyNonWritable(cx->asExclusiveContext(), obj, id);
         }
     }
     return true;
 }
 
 template <ExecutionMode mode>
 static inline bool
 DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
@@ -4881,17 +4887,17 @@ baseops::SetAttributes(JSContext *cx, Ha
         if (!JSObject::sparsifyDenseElement(cx, nobj, JSID_TO_INT(id)))
             return false;
         shape = obj->nativeLookup(cx, id);
     }
     if (nobj->isNative()) {
         if (!JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp))
             return false;
         if (*attrsp & JSPROP_READONLY)
-            MarkTypePropertyConfigured(cx, obj, id);
+            MarkTypePropertyNonWritable(cx, obj, id);
         return true;
     } else {
         return JSObject::setGenericAttributes(cx, nobj, id, attrsp);
     }
 }
 
 bool
 baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded)
@@ -4975,17 +4981,17 @@ js::WatchGuts(JSContext *cx, JS::HandleO
     }
 
     if (obj->isNative()) {
         // Use sparse indexes for watched objects, as dense elements can be
         // written to without checking the watchpoint map.
         if (!JSObject::sparsifyDenseElements(cx, obj))
             return false;
 
-        types::MarkTypePropertyConfigured(cx, obj, id);
+        types::MarkTypePropertyNonData(cx, obj, id);
     }
 
     WatchpointMap *wpmap = cx->compartment()->watchpointMap;
     if (!wpmap) {
         wpmap = cx->runtime()->new_<WatchpointMap>();
         if (!wpmap || !wpmap->init()) {
             js_ReportOutOfMemory(cx);
             return false;
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -22,17 +22,17 @@
 #include "jsinferinlines.h"
 
 #include "vm/ObjectImpl-inl.h"
 
 /* static */ inline bool
 JSObject::setGenericAttributes(JSContext *cx, js::HandleObject obj,
                                js::HandleId id, unsigned *attrsp)
 {
-    js::types::MarkTypePropertyConfigured(cx, obj, id);
+    js::types::MarkTypePropertyNonData(cx, obj, id);
     js::GenericAttributesOp op = obj->getOps()->setGenericAttributes;
     return (op ? op : js::baseops::SetAttributes)(cx, obj, id, attrsp);
 }
 
 /* static */ inline bool
 JSObject::changePropertyAttributes(JSContext *cx, js::HandleObject obj,
                                    js::HandleShape shape, unsigned attrs)
 {
@@ -40,38 +40,38 @@ JSObject::changePropertyAttributes(JSCon
                                                      shape->getter(), shape->setter());
 }
 
 /* static */ inline bool
 JSObject::deleteProperty(JSContext *cx, js::HandleObject obj, js::HandlePropertyName name,
                          bool *succeeded)
 {
     JS::RootedId id(cx, js::NameToId(name));
-    js::types::MarkTypePropertyConfigured(cx, obj, id);
+    js::types::MarkTypePropertyNonData(cx, obj, id);
     js::DeletePropertyOp op = obj->getOps()->deleteProperty;
     return (op ? op : js::baseops::DeleteProperty)(cx, obj, name, succeeded);
 }
 
 /* static */ inline bool
 JSObject::deleteElement(JSContext *cx, js::HandleObject obj, uint32_t index, bool *succeeded)
 {
     JS::RootedId id(cx);
     if (!js::IndexToId(cx, index, &id))
         return false;
-    js::types::MarkTypePropertyConfigured(cx, obj, id);
+    js::types::MarkTypePropertyNonData(cx, obj, id);
     js::DeleteElementOp op = obj->getOps()->deleteElement;
     return (op ? op : js::baseops::DeleteElement)(cx, obj, index, succeeded);
 }
 
 /* static */ inline bool
 JSObject::deleteSpecial(JSContext *cx, js::HandleObject obj, js::HandleSpecialId sid,
                         bool *succeeded)
 {
     JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
-    js::types::MarkTypePropertyConfigured(cx, obj, id);
+    js::types::MarkTypePropertyNonData(cx, obj, id);
     js::DeleteSpecialOp op = obj->getOps()->deleteSpecial;
     return (op ? op : js::baseops::DeleteSpecial)(cx, obj, sid, succeeded);
 }
 
 /* static */ inline bool
 JSObject::watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
                 JS::HandleObject callable)
 {
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -349,17 +349,17 @@ BaseProxyHandler::getPrototypeOf(JSConte
 }
 
 bool
 BaseProxyHandler::setPrototypeOf(JSContext *cx, HandleObject, HandleObject, bool *)
 {
     // Disallow sets of protos on proxies with lazy protos, but no hook.
     // This keeps us away from the footgun of having the first proto set opt
     // you out of having dynamic protos altogether.
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SETPROTOTYPEOF_FAIL);
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL);
     return false;
 }
 
 bool
 BaseProxyHandler::watch(JSContext *cx, HandleObject proxy, HandleId id, HandleObject callable)
 {
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH,
                          proxy->getClass()->name);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -843,17 +843,17 @@ js::XDRScript(XDRState<mode> *xdr, Handl
     }
 
     if (mode == XDR_DECODE) {
         scriptp.set(script);
 
         /* see BytecodeEmitter::tellDebuggerAboutCompiledScript */
         CallNewScriptHook(cx, script, fun);
         if (!fun) {
-            RootedGlobalObject global(cx, script->compileAndGo() ? &script->global() : NULL);
+            RootedGlobalObject global(cx, script->compileAndGo() ? &script->global() : nullptr);
             Debugger::onNewScript(cx, script, global);
         }
     }
 
     return true;
 }
 
 template bool
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -16,16 +16,17 @@
 #include "frontend/BytecodeCompiler.h"
 #include "jit/ExecutionModeInlines.h"
 #include "jit/IonBuilder.h"
 #include "vm/Debugger.h"
 
 #include "jscntxtinlines.h"
 #include "jscompartmentinlines.h"
 #include "jsobjinlines.h"
+#include "jsscriptinlines.h"
 
 using namespace js;
 
 using mozilla::ArrayLength;
 using mozilla::DebugOnly;
 
 bool
 js::EnsureWorkerThreadsInitialized(ExclusiveContext *cx)
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -660,17 +660,17 @@ SecurityWrapper<Base>::nativeCall(JSCont
     return false;
 }
 
 template <class Base>
 bool
 SecurityWrapper<Base>::setPrototypeOf(JSContext *cx, HandleObject wrapper,
                                       HandleObject proto, bool *bp)
 {
-    JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_UNWRAP_DENIED);
+    JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_UNWRAP_DENIED);
     return false;
 }
 
 // For security wrappers, we run the DefaultValue algorithm on the wrapper
 // itself, which means that the existing security policy on operations like
 // toString() will take effect and do the right thing here.
 template <class Base>
 bool
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -148,17 +148,17 @@ ProtoSetterImpl(JSContext *cx, CallArgs 
     if (!CheckAccess(cx, obj, nid, JSAccessMode(JSACC_PROTO | JSACC_WRITE), &v, &dummy))
         return false;
 
     bool success;
     if (!JSObject::setProto(cx, obj, newProto, &success))
         return false;
 
     if (!success) {
-        JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_SETPROTOTYPEOF_FAIL);
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SETPROTOTYPEOF_FAIL);
         return false;
     }
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
--- a/js/src/vm/OldDebugAPI.cpp
+++ b/js/src/vm/OldDebugAPI.cpp
@@ -336,17 +336,17 @@ JS_SetWatchPoint(JSContext *cx, JSObject
 
     /*
      * Use sparse indexes for watched objects, as dense elements can be written
      * to without checking the watchpoint map.
      */
     if (!JSObject::sparsifyDenseElements(cx, obj))
         return false;
 
-    types::MarkTypePropertyConfigured(cx, obj, propid);
+    types::MarkTypePropertyNonData(cx, obj, propid);
 
     WatchpointMap *wpmap = cx->compartment()->watchpointMap;
     if (!wpmap) {
         wpmap = cx->runtime()->new_<WatchpointMap>();
         if (!wpmap || !wpmap->init()) {
             js_ReportOutOfMemory(cx);
             return false;
         }
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -969,20 +969,20 @@ JSObject::changeProperty(typename Execut
 
     attrs |= shape->attrs & mask;
 
     /* Allow only shared (slotless) => unshared (slotful) transition. */
     JS_ASSERT(!((attrs ^ shape->attrs) & JSPROP_SHARED) ||
               !(attrs & JSPROP_SHARED));
 
     if (mode == ParallelExecution) {
-        if (!types::IsTypePropertyIdMarkedConfigured(obj, shape->propid()))
+        if (!types::IsTypePropertyIdMarkedNonData(obj, shape->propid()))
             return nullptr;
     } else {
-        types::MarkTypePropertyConfigured(cx->asExclusiveContext(), obj, shape->propid());
+        types::MarkTypePropertyNonData(cx->asExclusiveContext(), obj, shape->propid());
     }
 
     if (getter == JS_PropertyStub)
         getter = nullptr;
     if (setter == JS_StrictPropertyStub)
         setter = nullptr;
 
     if (!CheckCanChangeAttrs(cx, obj, shape, &attrs))
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -711,17 +711,17 @@ static void RecordFrameMetrics(nsIFrame*
                                       && aScrollFrame == presShell->GetRootScrollFrame();
   if (isRootContentDocRootScrollFrame) {
     if (nsIWidget* widget = aForFrame->GetNearestWidget()) {
       nsIntRect bounds;
       widget->GetBounds(bounds);
       ScreenIntRect screenBounds = ScreenIntRect::FromUnknownRect(mozilla::gfx::IntRect(
           bounds.x, bounds.y, bounds.width, bounds.height));
       AdjustForScrollBars(screenBounds, scrollableFrame);
-      metrics.mCompositionBounds = screenBounds.ClampRect(metrics.mCompositionBounds);
+      metrics.mCompositionBounds = metrics.mCompositionBounds.ForceInside(screenBounds);
       useWidgetBounds = true;
     }
   }
 
   // Adjust composition bounds for the size of scroll bars.
   // If the widget bounds were used to clamp the composition bounds,
   // this adjustment was already made to the widget bounds.
   if (!useWidgetBounds) {
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -495,17 +495,16 @@ GetFrom(nsFrameLoader* aFrameLoader)
 }
 
 class RemoteContentController : public GeckoContentController {
 public:
   RemoteContentController(RenderFrameParent* aRenderFrame)
     : mUILoop(MessageLoop::current())
     , mRenderFrame(aRenderFrame)
     , mHaveZoomConstraints(false)
-    , mAllowZoom(true)
   { }
 
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) MOZ_OVERRIDE
   {
     // We always need to post requests into the "UI thread" otherwise the
     // requests may get processed out of order.
     mUILoop->PostTask(
       FROM_HERE,
@@ -606,34 +605,26 @@ public:
     }
   }
 
   virtual void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE
   {
     MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
   }
 
-  void SaveZoomConstraints(bool aAllowZoom,
-                           const CSSToScreenScale& aMinZoom,
-                           const CSSToScreenScale& aMaxZoom)
+  void SaveZoomConstraints(const ZoomConstraints& aConstraints)
   {
     mHaveZoomConstraints = true;
-    mAllowZoom = aAllowZoom;
-    mMinZoom = aMinZoom;
-    mMaxZoom = aMaxZoom;
+    mZoomConstraints = aConstraints;
   }
 
-  virtual bool GetRootZoomConstraints(bool* aOutAllowZoom,
-                                      CSSToScreenScale* aOutMinZoom,
-                                      CSSToScreenScale* aOutMaxZoom)
+  virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
   {
-    if (mHaveZoomConstraints) {
-      *aOutAllowZoom = mAllowZoom;
-      *aOutMinZoom = mMinZoom;
-      *aOutMaxZoom = mMaxZoom;
+    if (mHaveZoomConstraints && aOutConstraints) {
+      *aOutConstraints = mZoomConstraints;
     }
     return mHaveZoomConstraints;
   }
 
   virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid)
   {
     if (MessageLoop::current() != mUILoop) {
       mUILoop->PostTask(
@@ -671,19 +662,17 @@ private:
       browser->UpdateFrame(aFrameMetrics);
     }
   }
 
   MessageLoop* mUILoop;
   RenderFrameParent* mRenderFrame;
 
   bool mHaveZoomConstraints;
-  bool mAllowZoom;
-  CSSToScreenScale mMinZoom;
-  CSSToScreenScale mMaxZoom;
+  ZoomConstraints mZoomConstraints;
 };
 
 RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader,
                                      ScrollingBehavior aScrollingBehavior,
                                      TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                      uint64_t* aId)
   : mLayersId(0)
   , mFrameLoader(aFrameLoader)
@@ -1088,26 +1077,24 @@ RenderFrameParent::ContentReceivedTouch(
     GetApzcTreeManager()->ContentReceivedTouch(aGuid, aPreventDefault);
   }
 }
 
 void
 RenderFrameParent::UpdateZoomConstraints(uint32_t aPresShellId,
                                          ViewID aViewId,
                                          bool aIsRoot,
-                                         bool aAllowZoom,
-                                         const CSSToScreenScale& aMinZoom,
-                                         const CSSToScreenScale& aMaxZoom)
+                                         const ZoomConstraints& aConstraints)
 {
   if (mContentController && aIsRoot) {
-    mContentController->SaveZoomConstraints(aAllowZoom, aMinZoom, aMaxZoom);
+    mContentController->SaveZoomConstraints(aConstraints);
   }
   if (GetApzcTreeManager()) {
     GetApzcTreeManager()->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
-                                                aAllowZoom, aMinZoom, aMaxZoom);
+                                                aConstraints);
   }
 }
 
 bool
 RenderFrameParent::HitTest(const nsRect& aRect)
 {
   return mTouchRegion.Contains(aRect);
 }
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -44,16 +44,17 @@ class RenderFrameParent : public PRender
   typedef mozilla::layers::ContainerLayer ContainerLayer;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::layers::TargetConfig TargetConfig;
   typedef mozilla::layers::LayerTransactionParent LayerTransactionParent;
   typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
   typedef mozilla::layers::TextureFactoryIdentifier TextureFactoryIdentifier;
   typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
+  typedef mozilla::layers::ZoomConstraints ZoomConstraints;
   typedef FrameMetrics::ViewID ViewID;
 
 public:
   typedef std::map<ViewID, nsRefPtr<nsContentView> > ViewMap;
 
   /**
    * Select the desired scrolling behavior.  If ASYNC_PAN_ZOOM is
    * chosen, then RenderFrameParent will watch input events and use
@@ -113,19 +114,17 @@ public:
   void ZoomToRect(uint32_t aPresShellId, ViewID aViewId, const CSSRect& aRect);
 
   void ContentReceivedTouch(const ScrollableLayerGuid& aGuid,
                             bool aPreventDefault);
 
   void UpdateZoomConstraints(uint32_t aPresShellId,
                              ViewID aViewId,
                              bool aIsRoot,
-                             bool aAllowZoom,
-                             const CSSToScreenScale& aMinZoom,
-                             const CSSToScreenScale& aMaxZoom);
+                             const ZoomConstraints& aConstraints);
 
   bool HitTest(const nsRect& aRect);
 
 protected:
   void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   virtual bool RecvNotifyCompositorTransaction() MOZ_OVERRIDE;
 
--- a/media/libcubeb/src/cubeb_opensl.c
+++ b/media/libcubeb/src/cubeb_opensl.c
@@ -504,21 +504,23 @@ opensl_stream_destroy(cubeb_stream * stm
     free(stm->queuebuf[i]);
   }
   free(stm);
 }
 
 static int
 opensl_stream_start(cubeb_stream * stm)
 {
+  /* To refill the queues before starting playback in order to avoid racing
+  * with refills started by SetPlayState on OpenSLES ndk threads. */
+  bufferqueue_callback(NULL, stm);
   SLresult res = (*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PLAYING);
   if (res != SL_RESULT_SUCCESS)
     return CUBEB_ERROR;
   stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
-  bufferqueue_callback(NULL, stm);
   return CUBEB_OK;
 }
 
 static int
 opensl_stream_stop(cubeb_stream * stm)
 {
   SLresult res = (*stm->play)->SetPlayState(stm->play, SL_PLAYSTATE_PAUSED);
   if (res != SL_RESULT_SUCCESS)
--- a/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c
+++ b/media/mtransport/third_party/nICEr/src/ice/ice_media_stream.c
@@ -187,16 +187,18 @@ int nr_ice_media_stream_get_attributes(n
       if (comp->state != NR_ICE_COMPONENT_DISABLED) {
         nr_ice_candidate *cand;
 
         cand=TAILQ_FIRST(&comp->candidates);
         while(cand){
           if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
             assert(index < attrct);
 
+            if (index >= attrct)
+              ABORT(R_INTERNAL);
 
             if(r=nr_ice_format_candidate_attribute(cand, attrs[index],NR_ICE_MAX_ATTRIBUTE_SIZE))
               ABORT(r);
 
             index++;
           }
 
           cand=TAILQ_NEXT(cand,entry_comp);
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -1008,22 +1008,22 @@ public:
         }
         rv = uuidgen->GenerateUUIDInPlace(&id);
         NS_ENSURE_SUCCESS(rv, NS_OK);
         id.ToProvidedString(uuid);
         // Strip off the { and } surrounding the UUID string
         dnsUUID.Assign(Substring(nsDependentCString(uuid), 1, NSID_LENGTH - 3));
 
         // Create events for A and SRV resolvers
-        events[0] = CreateEvent(NULL, TRUE, FALSE, TEXT("FinishedA"));
+        events[0] = CreateEvent(nullptr, TRUE, FALSE, TEXT("FinishedA"));
         if (!events[0]) {
             goto library_cleanup;
         }
 
-        events[1] = CreateEvent(NULL, TRUE, FALSE, TEXT("FinishedSRV"));
+        events[1] = CreateEvent(nullptr, TRUE, FALSE, TEXT("FinishedSRV"));
         if (!events[1]) {
             goto aevent_cleanup;
         }
 
         // dispatch A resolver
         mResolveAThread->Dispatch(new ExperimentResolver(DNS_TYPE_A,
                                                          dnsUUID,
                                                          &events[0],
--- a/netwerk/protocol/rtsp/rtsp/ARTPConnection.cpp
+++ b/netwerk/protocol/rtsp/rtsp/ARTPConnection.cpp
@@ -110,17 +110,20 @@ void ARTPConnection::MakePortPair(
 
     bumpSocketBufferSize(*rtpSocket);
 
     *rtcpSocket = socket(AF_INET, SOCK_DGRAM, 0);
     CHECK_GE(*rtcpSocket, 0);
 
     bumpSocketBufferSize(*rtcpSocket);
 
-    unsigned start = (rand() * 1000)/ RAND_MAX + 15550;
+    // Reduce the chance of using duplicate port numbers.
+    srand(time(NULL));
+    // rand() * 1000 may overflow int type, use long long.
+    unsigned start = (unsigned)((rand() * 1000ll) / RAND_MAX) + 15550;
     start &= ~1;
 
     for (unsigned port = start; port < 65536; port += 2) {
         struct sockaddr_in addr;
         memset(addr.sin_zero, 0, sizeof(addr.sin_zero));
         addr.sin_family = AF_INET;
         addr.sin_addr.s_addr = htonl(INADDR_ANY);
         addr.sin_port = htons(port);
--- a/netwerk/protocol/websocket/WebSocketChannel.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannel.cpp
@@ -64,26 +64,27 @@
 
 extern PRThread *gSocketThread;
 
 using namespace mozilla;
 
 namespace mozilla {
 namespace net {
 
-NS_IMPL_ISUPPORTS11(WebSocketChannel,
+NS_IMPL_ISUPPORTS12(WebSocketChannel,
                     nsIWebSocketChannel,
                     nsIHttpUpgradeListener,
                     nsIRequestObserver,
                     nsIStreamListener,
                     nsIProtocolHandler,
                     nsIInputStreamCallback,
                     nsIOutputStreamCallback,
                     nsITimerCallback,
                     nsIDNSListener,
+                    nsIProtocolProxyCallback,
                     nsIInterfaceRequestor,
                     nsIChannelEventSink)
 
 // We implement RFC 6455, which uses Sec-WebSocket-Version: 13 on the wire.
 #define SEC_WEBSOCKET_VERSION "13"
 
 /*
  * About SSL unsigned certificates
@@ -989,17 +990,17 @@ WebSocketChannel::WebSocketChannel() :
 WebSocketChannel::~WebSocketChannel()
 {
   LOG(("WebSocketChannel::~WebSocketChannel() %p\n", this));
 
   if (mWasOpened) {
     MOZ_ASSERT(mCalledOnStop, "WebSocket was opened but OnStop was not called");
     MOZ_ASSERT(mStopped, "WebSocket was opened but never stopped");
   }
-  MOZ_ASSERT(!mDNSRequest, "DNS Request still alive at destruction");
+  MOZ_ASSERT(!mCancelable, "DNS/Proxy Request still alive at destruction");
   MOZ_ASSERT(!mConnecting, "Should not be connecting in destructor");
 
   moz_free(mBuffer);
   moz_free(mDynamicOutput);
   delete mCompressor;
   delete mCurrentOut;
 
   while ((mCurrentOut = (OutboundMessage *) mOutgoingPingMessages.PopFront()))
@@ -1954,19 +1955,19 @@ WebSocketChannel::StopSession(nsresult r
       mLingeringCloseTimer->InitWithCallback(this, kLingeringCloseTimeout,
                                              nsITimer::TYPE_ONE_SHOT);
     else
       CleanupConnection();
   } else {
     CleanupConnection();
   }
 
-  if (mDNSRequest) {
-    mDNSRequest->Cancel(NS_ERROR_UNEXPECTED);
-    mDNSRequest = nullptr;
+  if (mCancelable) {
+    mCancelable->Cancel(NS_ERROR_UNEXPECTED);
+    mCancelable = nullptr;
   }
 
   mInflateReader = nullptr;
   mInflateStream = nullptr;
 
   delete mCompressor;
   mCompressor = nullptr;
 
@@ -2193,44 +2194,61 @@ WebSocketChannel::SetupRequest()
   NS_ENSURE_SUCCESS(rv, rv);
   LOG(("WebSocketChannel::SetupRequest: expected server key %s\n",
        mHashedSecret.get()));
 
   return NS_OK;
 }
 
 nsresult
-WebSocketChannel::ApplyForAdmission()
+WebSocketChannel::DoAdmissionDNS()
 {
-  LOG(("WebSocketChannel::ApplyForAdmission() %p\n", this));
-
-  // Websockets has a policy of 1 session at a time being allowed in the
-  // CONNECTING state per server IP address (not hostname)
-
   nsresult rv;
-  nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
 
   nsCString hostName;
   rv = mURI->GetHost(hostName);
   NS_ENSURE_SUCCESS(rv, rv);
   mAddress = hostName;
   rv = mURI->GetPort(&mPort);
   NS_ENSURE_SUCCESS(rv, rv);
   if (mPort == -1)
     mPort = (mEncrypted ? kDefaultWSSPort : kDefaultWSPort);
-
-  // expect the callback in ::OnLookupComplete
-  LOG(("WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"));
+  nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIThread> mainThread;
   NS_GetMainThread(getter_AddRefs(mainThread));
-  dns->AsyncResolve(hostName, 0, this, mainThread, getter_AddRefs(mDNSRequest));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
+  MOZ_ASSERT(!mCancelable);
+  return dns->AsyncResolve(hostName, 0, this, mainThread, getter_AddRefs(mCancelable));
+}
+
+nsresult
+WebSocketChannel::ApplyForAdmission()
+{
+  LOG(("WebSocketChannel::ApplyForAdmission() %p\n", this));
+
+  // Websockets has a policy of 1 session at a time being allowed in the
+  // CONNECTING state per server IP address (not hostname)
+
+  // Check to see if a proxy is being used before making DNS call
+  nsCOMPtr<nsIProtocolProxyService> pps =
+    do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID);
+
+  if (!pps) {
+    // go straight to DNS
+    // expect the callback in ::OnLookupComplete
+    LOG(("WebSocketChannel::ApplyForAdmission: checking for concurrent open\n"));
+    return DoAdmissionDNS();
+  }
+
+  MOZ_ASSERT(!mCancelable);
+
+  return pps->AsyncResolve(mURI,
+                           nsIProtocolProxyService::RESOLVE_PREFER_HTTPS_PROXY |
+                           nsIProtocolProxyService::RESOLVE_ALWAYS_TUNNEL,
+                           this, getter_AddRefs(mCancelable));
 }
 
 // Called after both OnStartRequest and OnTransportAvailable have
 // executed. This essentially ends the handshake and starts the websockets
 // protocol state machine.
 nsresult
 WebSocketChannel::StartWebsocketData()
 {
@@ -2295,48 +2313,79 @@ WebSocketChannel::ReportConnectionTeleme
   LOG(("WebSocketChannel::ReportConnectionTelemetry() %p %d", this, value));
   Telemetry::Accumulate(Telemetry::WEBSOCKETS_HANDSHAKE_TYPE, value);
 }
 
 // nsIDNSListener
 
 NS_IMETHODIMP
 WebSocketChannel::OnLookupComplete(nsICancelable *aRequest,
-                                     nsIDNSRecord *aRecord,
-                                     nsresult aStatus)
+                                   nsIDNSRecord *aRecord,
+                                   nsresult aStatus)
 {
   LOG(("WebSocketChannel::OnLookupComplete() %p [%p %p %x]\n",
        this, aRequest, aRecord, aStatus));
 
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "not main thread");
-  NS_ABORT_IF_FALSE(aRequest == mDNSRequest || mStopped,
-                    "wrong dns request");
 
   if (mStopped) {
     LOG(("WebSocketChannel::OnLookupComplete: Request Already Stopped\n"));
+    mCancelable = nullptr;
     return NS_OK;
   }
 
-  mDNSRequest = nullptr;
+  mCancelable = nullptr;
 
   // These failures are not fatal - we just use the hostname as the key
   if (NS_FAILED(aStatus)) {
     LOG(("WebSocketChannel::OnLookupComplete: No DNS Response\n"));
+
+    // set host in case we got here without calling DoAdmissionDNS()
+    mURI->GetHost(mAddress);
   } else {
     nsresult rv = aRecord->GetNextAddrAsString(mAddress);
     if (NS_FAILED(rv))
       LOG(("WebSocketChannel::OnLookupComplete: Failed GetNextAddr\n"));
   }
 
   LOG(("WebSocket OnLookupComplete: Proceeding to ConditionallyConnect\n"));
   sWebSocketAdmissions->ConditionallyConnect(this);
 
   return NS_OK;
 }
 
+// nsIProtocolProxyCallback
+NS_IMETHODIMP
+WebSocketChannel::OnProxyAvailable(nsICancelable *aRequest, nsIURI *aURI,
+                                   nsIProxyInfo *pi, nsresult status)
+{
+  if (mStopped) {
+    LOG(("WebSocketChannel::OnProxyAvailable: [%p] Request Already Stopped\n", this));
+    mCancelable = nullptr;
+    return NS_OK;
+  }
+
+  MOZ_ASSERT(aRequest == mCancelable);
+  mCancelable = nullptr;
+
+  nsAutoCString type;
+  if (NS_SUCCEEDED(status) && pi &&
+      NS_SUCCEEDED(pi->GetType(type)) &&
+      !type.EqualsLiteral("direct")) {
+    LOG(("WebSocket OnProxyAvailable [%p] Proxy found skip DNS lookup\n", this));
+    // call DNS callback directly without DNS resolver
+    OnLookupComplete(nullptr, nullptr, NS_ERROR_FAILURE);
+    return NS_OK;
+  }
+
+  LOG(("WebSocketChannel::OnProxyAvailable[%] checking DNS resolution\n", this));
+  DoAdmissionDNS();
+  return NS_OK;
+}
+
 // nsIInterfaceRequestor
 
 NS_IMETHODIMP
 WebSocketChannel::GetInterface(const nsIID & iid, void **result)
 {
   LOG(("WebSocketChannel::GetInterface() %p\n", this));
 
   if (iid.Equals(NS_GET_IID(nsIChannelEventSink)))
--- a/netwerk/protocol/websocket/WebSocketChannel.h
+++ b/netwerk/protocol/websocket/WebSocketChannel.h
@@ -9,16 +9,17 @@
 
 #include "nsISupports.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIStreamListener.h"
 #include "nsIAsyncInputStream.h"
 #include "nsIAsyncOutputStream.h"
 #include "nsITimer.h"
 #include "nsIDNSListener.h"
+#include "nsIProtocolProxyCallback.h"
 #include "nsIChannelEventSink.h"
 #include "nsIHttpChannelInternal.h"
 #include "BaseWebSocketChannel.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include "nsINetworkManager.h"
 #include "nsProxyRelease.h" // for nsMainThreadPtrHandle
 #endif
@@ -56,28 +57,30 @@ enum wsConnectingState {
 
 class WebSocketChannel : public BaseWebSocketChannel,
                          public nsIHttpUpgradeListener,
                          public nsIStreamListener,
                          public nsIInputStreamCallback,
                          public nsIOutputStreamCallback,
                          public nsITimerCallback,
                          public nsIDNSListener,
+                         public nsIProtocolProxyCallback,
                          public nsIInterfaceRequestor,
                          public nsIChannelEventSink
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIHTTPUPGRADELISTENER
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIINPUTSTREAMCALLBACK
   NS_DECL_NSIOUTPUTSTREAMCALLBACK
   NS_DECL_NSITIMERCALLBACK
   NS_DECL_NSIDNSLISTENER
+  NS_DECL_NSIPROTOCOLPROXYCALLBACK
   NS_DECL_NSIINTERFACEREQUESTOR
   NS_DECL_NSICHANNELEVENTSINK
 
   // nsIWebSocketChannel methods BaseWebSocketChannel didn't implement for us
   //
   NS_IMETHOD AsyncOpen(nsIURI *aURI,
                        const nsACString &aOrigin,
                        nsIWebSocketListener *aListener,
@@ -129,16 +132,17 @@ private:
   void DeleteCurrentOutGoingMessage();
   void GeneratePong(uint8_t *payload, uint32_t len);
   void GeneratePing();
 
   void     BeginOpen();
   nsresult HandleExtensions();
   nsresult SetupRequest();
   nsresult ApplyForAdmission();
+  nsresult DoAdmissionDNS();
   nsresult StartWebsocketData();
   uint16_t ResultToCloseCode(nsresult resultCode);
   void     ReportConnectionTelemetry();
 
   void StopSession(nsresult reason);
   void AbortSession(nsresult reason);
   void ReleaseSession();
   void CleanupConnection();
@@ -160,17 +164,17 @@ private:
       mPingOutstanding = 0;
       mPingTimer->SetDelay(mPingInterval);
     }
   }
 
   nsCOMPtr<nsIEventTarget>                 mSocketThread;
   nsCOMPtr<nsIHttpChannelInternal>         mChannel;
   nsCOMPtr<nsIHttpChannel>                 mHttpChannel;
-  nsCOMPtr<nsICancelable>                  mDNSRequest;
+  nsCOMPtr<nsICancelable>                  mCancelable;
   nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
   nsCOMPtr<nsIRandomGenerator>             mRandomGenerator;
 
   nsCString                       mHashedSecret;
 
   // Used as key for connection managment: Initially set to hostname from URI,
   // then to IP address (unless we're leaving DNS resolution to a proxy server)
   nsCString                       mAddress;
--- a/netwerk/sctp/src/user_environment.c
+++ b/netwerk/sctp/src/user_environment.c
@@ -87,15 +87,15 @@ read_random_phony(void *buf, int count)
 	uint32_t randval;
 	int size, i;
 
 	/* srandom() is called in kern/init_main.c:proc0_post() */
 
 	/* Fill buf[] with random(9) output */
 	for (i = 0; i < count; i+= (int)sizeof(uint32_t)) {
 		randval = random();
-		size = MIN(count - i, sizeof(uint32_t));
+		size = MIN(count - i, (int)sizeof(uint32_t));
 		memcpy(&((char *)buf)[i], &randval, (size_t)size);
 	}
 
 	return (count);
 }
 
--- a/testing/mach_commands.py
+++ b/testing/mach_commands.py
@@ -37,16 +37,21 @@ haven't been told about this test suite 
 please file a bug at https://bugzilla.mozilla.org/enter_bug.cgi?product=Testing&component=General
 and request support be added.
 '''.strip()
 
 MOCHITEST_CHUNK_BY_DIR = 4
 MOCHITEST_TOTAL_CHUNKS = 5
 
 TEST_SUITES = {
+    'cppunittest': {
+        'aliases': ('Cpp', 'cpp'),
+        'mach_command': 'cppunittest',
+        'kwargs': {'test_file': None},
+    },
     'crashtest': {
         'aliases': ('C', 'Rc', 'RC', 'rc'),
         'mach_command': 'crashtest',
         'kwargs': {'test_file': None},
     },
     'crashtest-ipc': {
         'aliases': ('Cipc', 'cipc'),
         'mach_command': 'crashtest-ipc',
@@ -159,8 +164,43 @@ class Test(MachCommandBase):
             return 1
 
         if os.path.isdir(what):
             print(HANDLE_DIR_ERROR % what)
             return 1
 
         print(UNKNOWN_TEST % what)
         return 1
+
+@CommandProvider
+class MachCommands(MachCommandBase):
+    @Command('cppunittest', category='testing',
+        description='Run cpp unit tests.')
+    @CommandArgument('test_files', nargs='*', metavar='N',
+        help='Test to run. Can be specified as one or more files or ' \
+            'directories, or omitted. If omitted, the entire test suite is ' \
+            'executed.')
+
+    def run_cppunit_test(self, **params):
+        import runcppunittests as cppunittests
+        import logging
+
+        if len(params['test_files']) == 0:
+            testdir = os.path.join(self.distdir, 'cppunittests')
+            progs = cppunittests.extract_unittests_from_args([testdir], None)
+        else:
+            progs = cppunittests.extract_unittests_from_args(params['test_files'], None)
+
+        # See if we have crash symbols
+        symbols_path = os.path.join(self.distdir, 'crashreporter-symbols')
+        if not os.path.isdir(symbols_path):
+            symbols_path = None
+
+        tester = cppunittests.CPPUnitTests()
+        try:
+            result = tester.run_tests(progs, self.bindir, symbols_path)
+        except Exception, e:
+            self.log(logging.ERROR, 'cppunittests',
+                {'exception': str(e)},
+                'Caught exception running cpp unit tests: {exception}')
+            result = False
+
+        return 0 if result else 1
--- a/testing/runcppunittests.py
+++ b/testing/runcppunittests.py
@@ -140,35 +140,36 @@ class CPPUnittestOptions(OptionParser):
         self.add_option("--skip-manifest",
                         action = "store", type = "string", dest = "manifest_file",
                         default = None,
                         help = "absolute path to a manifest file")
 
 def extract_unittests_from_args(args, manifest_file):
     """Extract unittests from args, expanding directories as needed"""
     progs = []
-    skipped_progs = set()
+
+    # Known files commonly packaged with the cppunittests that are not tests
+    skipped_progs = set(['.mkdir.done', 'remotecppunittests.py', 'runcppunittests.py', 'runcppunittests.pyc'])
 
     if manifest_file:
         skipped_progs.add(os.path.basename(manifest_file))
         with open(manifest_file) as f:
             for line in f:
                 # strip out comment, if any
                 prog = line.split('#')[0]
                 if prog:
                     skipped_progs.add(prog.strip())
 
     for p in args:
         if os.path.isdir(p):
             progs.extend([os.path.abspath(os.path.join(p, x)) for x in os.listdir(p) if not x in skipped_progs])
         elif p not in skipped_progs:
             progs.append(os.path.abspath(p))
 
-    #filter out python files packaged with the unit tests
-    return filter(lambda x: not x.endswith('.py') and not x.endswith('.pyc'), progs)
+    return progs
 
 def main():
     parser = CPPUnittestOptions()
     options, args = parser.parse_args()
     if not args:
         print >>sys.stderr, """Usage: %s <test binary> [<test binary>...]""" % sys.argv[0]
         sys.exit(1)
     if not options.xre_path:
--- a/tools/jprof/bfd.cpp
+++ b/tools/jprof/bfd.cpp
@@ -13,50 +13,50 @@
 #include <libgen.h>
 #include <bfd.h>
 #include <cxxabi.h>
 
 static bfd *try_debug_file(const char *filename, unsigned long crc32)
 {
   int fd = open(filename, O_RDONLY);
   if (fd < 0)
-    return NULL;
+    return nullptr;
 
   unsigned char buf[4*1024];
   unsigned long crc = 0;
 
   while (1) {
     ssize_t count = read(fd, buf, sizeof(buf));
     if (count <= 0)
       break;
 
     crc = bfd_calc_gnu_debuglink_crc32(crc, buf, count);
   }
 
   close(fd);
 
   if (crc != crc32)
-    return NULL;
+    return nullptr;
 
-  bfd *object = bfd_openr(filename, NULL);
+  bfd *object = bfd_openr(filename, nullptr);
   if (!bfd_check_format(object, bfd_object)) {
     bfd_close(object);
-    return NULL;
+    return nullptr;
   }
 
   return object;
 }
 
 static bfd *find_debug_file(bfd *lib, const char *aFileName)
 {
   // check for a separate debug file with symbols
   asection *sect = bfd_get_section_by_name(lib, ".gnu_debuglink");
 
   if (!sect)
-    return NULL;
+    return nullptr;
 
   bfd_size_type debuglinkSize = bfd_section_size (objfile->obfd, sect);
 
   char *debuglink = new char[debuglinkSize];
   bfd_get_section_contents(lib, sect, debuglink, 0, debuglinkSize);
 
   // crc checksum is aligned to 4 bytes, and after the NUL.
   int crc_offset = (int(strlen(debuglink)) & ~3) + 4;
@@ -120,17 +120,17 @@ Symbol ** leaky::ExtendSymbols(int num)
                          if (sp >= lastSymbol) { \
                            sp = ExtendSymbols(16384); \
                          } \
                        } while (0)
 
 void leaky::ReadSymbols(const char *aFileName, u_long aBaseAddress)
 {
   int initialSymbols = usefulSymbols;
-  if (NULL == externalSymbols) {
+  if (nullptr == externalSymbols) {
     externalSymbols = (Symbol**) calloc(sizeof(Symbol*),10000);
     Symbol *new_array = new Symbol[10000];
     for (int i = 0; i < 10000; i++) {
       externalSymbols[i] = &new_array[i];
     }
     numExternalSymbols = 10000;
   }
   Symbol** sp = externalSymbols + usefulSymbols;
@@ -144,18 +144,18 @@ void leaky::ReadSymbols(const char *aFil
   bfd_boolean kDynamic = (bfd_boolean) false;
 
   static int firstTime = 1;
   if (firstTime) {
     firstTime = 0;
     bfd_init ();
   }
 
-  bfd* lib = bfd_openr(aFileName, NULL);
-  if (NULL == lib) {
+  bfd* lib = bfd_openr(aFileName, nullptr);
+  if (nullptr == lib) {
     return;
   }
   if (!bfd_check_format(lib, bfd_object)) {
     bfd_close(lib);
     return;
   }
 
   bfd *symbolFile = find_debug_file(lib, aFileName);
@@ -194,17 +194,17 @@ void leaky::ReadSymbols(const char *aFil
     sym = bfd_minisymbol_to_symbol(symbolFile, kDynamic, (const PTR) from, store);
 
     symbol_info syminfo;
     bfd_get_symbol_info (symbolFile, sym, &syminfo);
 
 //    if ((syminfo.type == 'T') || (syminfo.type == 't')) {
       const char* nm = bfd_asymbol_name(sym);
       if (nm && nm[0]) {
-        char* dnm = NULL;
+        char* dnm = nullptr;
         if (strncmp("__thunk", nm, 7)) {
           dnm = abi::__cxa_demangle(nm, 0, 0, 0);
         }
         (*sp)->Init(dnm ? dnm : nm, syminfo.value + aBaseAddress);
         if (dnm) {
           free(dnm);
         }
         NEXT_SYMBOL;
--- a/tools/jprof/coff.cpp
+++ b/tools/jprof/coff.cpp
@@ -33,17 +33,17 @@ static char *Demangle(char *rawName)
     return strdup(namebuf);
 #endif
 }
 
 void leaky::readSymbols(const char *fileName)
 {
     LDFILE *ldptr;
 
-    ldptr = ldopen(fileName, NULL);
+    ldptr = ldopen(fileName, nullptr);
     if (!ldptr) {
 	fprintf(stderr, "%s: unable to open \"%s\"\n", applicationName,
 		fileName);
 	exit(-1);
     }
     if (PSYMTAB(ldptr) == 0) {
 	fprintf(stderr, "%s: \"%s\": has no symbol table\n", applicationName,
 		fileName);
--- a/tools/jprof/leaky.cpp
+++ b/tools/jprof/leaky.cpp
@@ -54,17 +54,17 @@ int main(int argc, char** argv)
       l->outputfd = fopen(name,"w");
       // if an error we won't process the file
     }
     if (l->outputfd) { // paranoia
       l->open(argv[l->logFileIndex + i]);
 
       if (l->outputfd != stderr) {
         fclose(l->outputfd);
-        l->outputfd = NULL;
+        l->outputfd = nullptr;
       }
     }
   }
 
   return 0;
 }
 
 char *
@@ -110,18 +110,18 @@ htmlify(const char *in)
   } while (*p);
   *q = '\0';
 
   return out;
 }
 
 leaky::leaky()
 {
-  applicationName = NULL;
-  progFile = NULL;
+  applicationName = nullptr;
+  progFile = nullptr;
 
   quiet = true;
   showAddress = false;
   showThreads = false;
   stackDepth = 100000;
   onlyThread = 0;
   cleo = false;
 
@@ -130,17 +130,17 @@ leaky::leaky()
 
   sfd = -1;
   externalSymbols = 0;
   usefulSymbols = 0;
   numExternalSymbols = 0;
   lowestSymbolAddr = 0;
   highestSymbolAddr = 0;
 
-  loadMap = NULL;
+  loadMap = nullptr;
 
   collect_last  = false;
   collect_start = -1;
   collect_end   = -1;
 }
 
 leaky::~leaky()
 {
@@ -162,24 +162,24 @@ void leaky::usageError()
           "\t--output-dir dir: write output files to dir\n"
           "\tIf there's one log, output goes to stdout unless --output-dir is set\n"
           "\tIf there are more than one log, output files will be named with .html added\n"
           );
   exit(-1);
 }
 
 static struct option longopts[] = {
-    { "threads", 0, NULL, 't' },
-    { "only-thread", 1, NULL, 'T' },
-    { "last", 0, NULL, 'l' },
-    { "start", 1, NULL, 'x' },
-    { "end", 1, NULL, 'n' },
-    { "cleo",0, NULL, 'c' },
-    { "output-dir", 1, NULL, 'd' },
-    { NULL, 0, NULL, 0 },
+    { "threads", 0, nullptr, 't' },
+    { "only-thread", 1, nullptr, 'T' },
+    { "last", 0, nullptr, 'l' },
+    { "start", 1, nullptr, 'x' },
+    { "end", 1, nullptr, 'n' },
+    { "cleo",0, nullptr, 'c' },
+    { "output-dir", 1, nullptr, 'd' },
+    { nullptr, 0, nullptr, 0 },
 };
 
 void leaky::initialize(int argc, char** argv)
 {
   applicationName = argv[0];
   applicationName = strrchr(applicationName, '/');
   if (!applicationName) {
     applicationName = argv[0];
@@ -187,17 +187,17 @@ void leaky::initialize(int argc, char** 
     applicationName++;
   }
 
   int arg;
   int errflg = 0;
   int longindex = 0;
 
   onlyThread = 0;
-  output_dir = NULL;
+  output_dir = nullptr;
   cleo = false;
 
   // XXX tons of cruft here left over from tracemalloc
   // XXX The -- options shouldn't need short versions, or they should be documented
   while (((arg = getopt_long(argc, argv, "adEe:gh:i:r:Rs:tT:qvx:ln:",longopts,&longindex)) != -1)) {
     switch (arg) {
       case '?':
       default:
@@ -459,17 +459,17 @@ static int symbolOrder(void const* a, vo
   Symbol const** bp = (Symbol const **)b;
   return (*ap)->address == (*bp)->address ? 0 :
     ((*ap)->address > (*bp)->address ? 1 : -1);
 }
 
 void leaky::ReadSharedLibrarySymbols()
 {
   LoadMapEntry* lme = loadMap;
-  while (NULL != lme) {
+  while (nullptr != lme) {
     ReadSymbols(lme->name, lme->address);
     lme = lme->next;
   }
 }
 
 void leaky::setupSymbols(const char *fileName)
 {
   if (usefulSymbols == 0) {
@@ -521,17 +521,17 @@ int leaky::findSymbolIndex(u_long addr)
   return -1;
 }
 
 Symbol* leaky::findSymbol(u_long addr)
 {
   int idx = findSymbolIndex(addr);
 
   if(idx<0) {
-    return NULL;
+    return nullptr;
   } else {
     return externalSymbols[idx];
   }
 }
 
 //----------------------------------------------------------------------
 
 bool leaky::excluded(malloc_log_entry* lep)
--- a/tools/jprof/stub/libmalloc.cpp
+++ b/tools/jprof/stub/libmalloc.cpp
@@ -166,17 +166,17 @@ static void DumpAddressMap()
   {
     startSignalCounter(0);
   }
 
   int mfd = open(M_MAPFILE, O_CREAT|O_WRONLY|O_TRUNC, 0666);
   if (mfd >= 0) {
     malloc_map_entry mme;
     link_map* map = _r_debug.r_map;
-    while (NULL != map) {
+    while (nullptr != map) {
       if (map->l_name && *map->l_name) {
 	mme.nameLen = strlen(map->l_name);
 	mme.address = map->l_addr;
 	write(mfd, &mme, sizeof(mme));
 	write(mfd, map->l_name, mme.nameLen);
 #if 0
 	write(1, map->l_name, mme.nameLen);
 	write(1, "\n", 1);
@@ -434,34 +434,34 @@ static void startSignalCounter(unsigned 
     struct itimerval tvalue;
 
     tvalue.it_interval.tv_sec = 0;
     tvalue.it_interval.tv_usec = 0;
     tvalue.it_value.tv_sec = millisec/1000;
     tvalue.it_value.tv_usec = (millisec%1000)*1000;
 
     if (realTime) {
-	setitimer(ITIMER_REAL, &tvalue, NULL);
+        setitimer(ITIMER_REAL, &tvalue, nullptr);
     } else {
-    	setitimer(ITIMER_PROF, &tvalue, NULL);
+        setitimer(ITIMER_PROF, &tvalue, nullptr);
     }
 }
 
 static long timerMilliSec = 50;
 
 #if defined(linux)
 static int setupRTCSignals(int hz, struct sigaction *sap)
 {
     /* global */ rtcFD = open("/dev/rtc", O_RDONLY);
     if (rtcFD < 0) {
         perror("JPROF_RTC setup: open(\"/dev/rtc\", O_RDONLY)");
         return 0;
     }
 
-    if (sigaction(SIGIO, sap, NULL) == -1) {
+    if (sigaction(SIGIO, sap, nullptr) == -1) {
         perror("JPROF_RTC setup: sigaction(SIGIO)");
         return 0;
     }
 
     if (ioctl(rtcFD, RTC_IRQP_SET, hz) == -1) {
         perror("JPROF_RTC setup: ioctl(/dev/rtc, RTC_IRQP_SET, $JPROF_RTC_HZ)");
         return 0;
     }
@@ -612,17 +612,17 @@ NS_EXPORT_(void) setupProfilingStuff(voi
 		startTimer = 0;
 	    }
 	    if(strstr(tst, "JP_START")) doNotStart = 0;
 	    if(strstr(tst, "JP_REALTIME")) realTime = 1;
 	    if(strstr(tst, "JP_APPEND")) append = O_APPEND;
 
 	    char *delay = strstr(tst,"JP_PERIOD=");
 	    if(delay) {
-                double tmp = strtod(delay+strlen("JP_PERIOD="), NULL);
+                double tmp = strtod(delay+strlen("JP_PERIOD="), nullptr);
                 if (tmp>=1e-3) {
 		    timerMilliSec = static_cast<unsigned long>(1000 * tmp);
                 } else {
                     fprintf(stderr,
                             "JP_PERIOD of %g less than 0.001 (1ms), using 1ms\n",
                             tmp);
                     timerMilliSec = 1;
                 }
@@ -703,56 +703,56 @@ NS_EXPORT_(void) setupProfilingStuff(voi
 
 		    main_thread = pthread_self();
                     //fprintf(stderr,"jprof: main_thread = %u\n",
                     //        (unsigned int)main_thread);
 
                     // FIX!  probably should block these against each other
                     // Very unlikely.
 		    sigemptyset(&mset);
-		    action.sa_handler = NULL;
+		    action.sa_handler = nullptr;
 		    action.sa_sigaction = StackHook;
 		    action.sa_mask  = mset;
 		    action.sa_flags = SA_RESTART | SA_SIGINFO;
 #if defined(linux)
                     if (rtcHz) {
                         if (!setupRTCSignals(rtcHz, &action)) {
                             fputs("jprof: Error initializing RTC, NOT "
                                   "profiling\n", stderr);
                             return;
                         }
                     }
 
                     if (!rtcHz || firstDelay != 0)
 #endif
                     {
                         if (realTime) {
-                            sigaction(SIGALRM, &action, NULL);
+                            sigaction(SIGALRM, &action, nullptr);
                         }
                     }
                     // enable PROF in all cases to simplify JP_DEFER/pause/restart
-                    sigaction(SIGPROF, &action, NULL);
+                    sigaction(SIGPROF, &action, nullptr);
 
 		    // make it so a SIGUSR1 will stop the profiling
 		    // Note:  It currently does not close the logfile.
 		    // This could be configurable (so that it could
 		    // later be reopened).
 
 		    struct sigaction stop_action;
 		    stop_action.sa_handler = EndProfilingHook;
 		    stop_action.sa_mask  = mset;
 		    stop_action.sa_flags = SA_RESTART;
-		    sigaction(SIGUSR1, &stop_action, NULL);
+		    sigaction(SIGUSR1, &stop_action, nullptr);
 
 		    // make it so a SIGUSR2 will clear the circular buffer
 
 		    stop_action.sa_handler = ClearProfilingHook;
 		    stop_action.sa_mask  = mset;
 		    stop_action.sa_flags = SA_RESTART;
-		    sigaction(SIGUSR2, &stop_action, NULL);
+		    sigaction(SIGUSR2, &stop_action, nullptr);
 
                     printf("Jprof: Initialized signal handler and set "
                            "timer for %lu %s, %d s "
                            "initial delay\n",
                            rtcHz ? rtcHz : timerMilliSec, 
                            rtcHz ? "Hz" : "ms",
                            firstDelay);
 
--- a/tools/trace-malloc/leaksoup.cpp
+++ b/tools/trace-malloc/leaksoup.cpp
@@ -97,17 +97,17 @@ int main(int argc, char **argv)
     if (argc != 2) {
         fprintf(stderr,
                 "Expected usage:  %s <sd-leak-file>\n"
                 "  sd-leak-file: Output of --shutdown-leaks=<file> option.\n",
                 argv[0]);
         return 1;
     }
 
-    NS_InitXPCOM2(NULL, NULL, NULL);
+    NS_InitXPCOM2(nullptr, nullptr, nullptr);
 
     ADLog log;
     if (!log.Read(argv[1])) {
         fprintf(stderr,
                 "%s: Error reading input file %s.\n", argv[0], argv[1]);
     }
 
     const size_t count = log.count();
@@ -396,12 +396,12 @@ int main(int argc, char **argv)
         }
         printf("</body>\n"
                "</html>\n");
     }
 
     delete [] sorted_nodes;
     delete [] nodes;
 
-    NS_ShutdownXPCOM(NULL);
+    NS_ShutdownXPCOM(nullptr);
 
     return 0;
 }
--- a/widget/TouchEvents.h
+++ b/widget/TouchEvents.h
@@ -125,16 +125,26 @@ class WidgetTouchEvent : public WidgetIn
 {
 public:
   virtual WidgetTouchEvent* AsTouchEvent() MOZ_OVERRIDE { return this; }
 
   WidgetTouchEvent()
   {
   }
 
+  WidgetTouchEvent(const WidgetTouchEvent& aOther) :
+    WidgetInputEvent(aOther.mFlags.mIsTrusted, aOther.message, aOther.widget,
+                     NS_TOUCH_EVENT)
+  {
+    modifiers = aOther.modifiers;
+    time = aOther.time;
+    touches.AppendElements(aOther.touches);
+    MOZ_COUNT_CTOR(WidgetTouchEvent);
+  }
+
   WidgetTouchEvent(bool aIsTrusted, WidgetTouchEvent* aEvent) :
     WidgetInputEvent(aIsTrusted, aEvent->message, aEvent->widget,
                      NS_TOUCH_EVENT)
   {
     modifiers = aEvent->modifiers;
     time = aEvent->time;
     touches.AppendElements(aEvent->touches);
     MOZ_COUNT_CTOR(WidgetTouchEvent);
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -159,17 +159,17 @@ AndroidBridge::Init(JNIEnv *jEnv)
 {
     ALOG_BRIDGE("AndroidBridge::Init");
     jEnv->GetJavaVM(&mJavaVM);
 
     AutoLocalJNIFrame jniFrame(jEnv);
 
     mJNIEnv = nullptr;
     mThread = -1;
-    mGLControllerObj = NULL;
+    mGLControllerObj = nullptr;
     mOpenedGraphicsLibraries = false;
     mHasNativeBitmapAccess = false;
     mHasNativeWindowAccess = false;
     mHasNativeWindowFallback = false;
 
     initInit();
 
 #ifdef MOZ_WEBSMS_BACKEND
@@ -264,34 +264,34 @@ jstring AndroidBridge::NewJavaString(Aut
 jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const nsACString& string) {
     return NewJavaString(frame, NS_ConvertUTF8toUTF16(string));
 }
 
 extern "C" {
     __attribute__ ((visibility("default")))
     JNIEnv * GetJNIForThread()
     {
-        JNIEnv *jEnv = NULL;
+        JNIEnv *jEnv = nullptr;
         JavaVM *jVm  = mozilla::AndroidBridge::GetVM();
         if (!jVm) {
             __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "Returned a null VM");
-            return NULL;
+            return nullptr;
         }
         jEnv = static_cast<JNIEnv*>(PR_GetThreadPrivate(sJavaEnvThreadIndex));
 
         if (jEnv)
             return jEnv;
 
         int status = jVm->GetEnv((void**) &jEnv, JNI_VERSION_1_2);
         if (status) {
 
-            status = jVm->AttachCurrentThread(&jEnv, NULL);
+            status = jVm->AttachCurrentThread(&jEnv, nullptr);
             if (status) {
                 __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread",  "Could not attach");
-                return NULL;
+                return nullptr;
             }
 
             PR_SetThreadPrivate(sJavaEnvThreadIndex, jEnv);
         }
         if (!jEnv) {
             __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "returning NULL");
         }
         return jEnv;
@@ -299,32 +299,34 @@ extern "C" {
 }
 
 void AutoGlobalWrappedJavaObject::Dispose() {
     if (isNull()) {
         return;
     }
 
     GetJNIForThread()->DeleteGlobalRef(wrapped_obj);
-    wrapped_obj = NULL;
+    wrapped_obj = nullptr;
 }
 
 AutoGlobalWrappedJavaObject::~AutoGlobalWrappedJavaObject() {
     Dispose();
 }
 
 static void
 getHandlersFromStringArray(JNIEnv *aJNIEnv, jobjectArray jArr, jsize aLen,
                            nsIMutableArray *aHandlersArray,
                            nsIHandlerApp **aDefaultApp,
                            const nsAString& aAction = EmptyString(),
                            const nsACString& aMimeType = EmptyCString())
 {
     nsString empty = EmptyString();
     for (jsize i = 0; i < aLen; i+=4) {
+
+        AutoLocalJNIFrame jniFrame(aJNIEnv, 4);
         nsJNIString name(
             static_cast<jstring>(aJNIEnv->GetObjectArrayElement(jArr, i)), aJNIEnv);
         nsJNIString isDefault(
             static_cast<jstring>(aJNIEnv->GetObjectArrayElement(jArr, i + 1)), aJNIEnv);
         nsJNIString packageName(
             static_cast<jstring>(aJNIEnv->GetObjectArrayElement(jArr, i + 2)), aJNIEnv);
         nsJNIString className(
             static_cast<jstring>(aJNIEnv->GetObjectArrayElement(jArr, i + 3)), aJNIEnv);
@@ -345,116 +347,111 @@ AndroidBridge::GetHandlersForMimeType(co
                                       const nsAString& aAction)
 {
     ALOG_BRIDGE("AndroidBridge::GetHandlersForMimeType");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
+    AutoLocalJNIFrame jniFrame(env, 1);
     jobjectArray arr = GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction);
     if (!arr)
         return false;
 
     jsize len = env->GetArrayLength(arr);
 
     if (!aHandlersArray)
         return len > 0;
 
     getHandlersFromStringArray(env, arr, len, aHandlersArray,
                                aDefaultApp, aAction,
                                NS_ConvertUTF16toUTF8(aMimeType));
-
-    env->DeleteLocalRef(arr);
     return true;
 }
 
 bool
 AndroidBridge::GetHandlersForURL(const nsAString& aURL,
                                  nsIMutableArray* aHandlersArray,
                                  nsIHandlerApp **aDefaultApp,
                                  const nsAString& aAction)
 {
     ALOG_BRIDGE("AndroidBridge::GetHandlersForURL");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
+    AutoLocalJNIFrame jniFrame(env, 1);
     jobjectArray arr = GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction);
     if (!arr)
         return false;
 
     jsize len = env->GetArrayLength(arr);
 
     if (!aHandlersArray)
         return len > 0;
 
     getHandlersFromStringArray(env, arr, len, aHandlersArray,
                                aDefaultApp, aAction);
-
-    env->DeleteLocalRef(arr);
     return true;
 }
 
 void
 AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType)
 {
     ALOG_BRIDGE("AndroidBridge::GetMimeTypeFromExtensions");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
+    AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstrType = GeckoAppShell::GetMimeTypeFromExtensionsWrapper(NS_ConvertUTF8toUTF16(aFileExt));
     if (!jstrType) {
         return;
     }
     nsJNIString jniStr(jstrType, env);
     CopyUTF16toUTF8(jniStr.get(), aMimeType);
-
-    env->DeleteLocalRef(jstrType);
 }
 
 void
 AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt)
 {
     ALOG_BRIDGE("AndroidBridge::GetExtensionFromMimeType");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
+    AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstrExt = GeckoAppShell::GetExtensionFromMimeTypeWrapper(NS_ConvertUTF8toUTF16(aMimeType));
     if (!jstrExt) {
         return;
     }
     nsJNIString jniStr(jstrExt, env);
     CopyUTF16toUTF8(jniStr.get(), aFileExt);
-
-    env->DeleteLocalRef(jstrExt);
 }
 
 bool
 AndroidBridge::GetClipboardText(nsAString& aText)
 {
     ALOG_BRIDGE("AndroidBridge::GetClipboardText");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
+    AutoLocalJNIFrame jniFrame(env, 1);
     jstring result = Clipboard::GetClipboardTextWrapper();
     if (!result)
         return false;
 
     nsJNIString jniStr(result, env);
     aText.Assign(jniStr);
-
-    env->DeleteLocalRef(result);
     return true;
 }
 
 void
 AndroidBridge::ShowAlertNotification(const nsAString& aImageUrl,
                                      const nsAString& aAlertTitle,
                                      const nsAString& aAlertText,
                                      const nsAString& aAlertCookie,
@@ -506,39 +503,39 @@ AndroidBridge::GetScreenDepth()
 
 void
 AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
+    AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstr = GeckoAppShell::ShowFilePickerForExtensionsWrapper(aExtensions);
     if (jstr == nullptr) {
         return;
     }
 
     aFilePath.Assign(nsJNIString(jstr, env));
-    env->DeleteLocalRef(jstr);
 }
 
 void
 AndroidBridge::ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
+    AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstr = GeckoAppShell::ShowFilePickerForMimeTypeWrapper(aMimeType);
     if (jstr == nullptr) {
         return;
     }
 
     aFilePath.Assign(nsJNIString(jstr, env));
-    env->DeleteLocalRef(jstr);
 }
 
 void
 AndroidBridge::ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback)
 {
     callback->AddRef();
     GeckoAppShell::ShowFilePickerAsyncWrapper(aMimeType, (int64_t) callback);
 }
@@ -553,17 +550,17 @@ AndroidBridge::Vibrate(const nsTArray<ui
         ALOG_BRIDGE("  invalid 0-length array");
         return;
     }
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
 
     // It's clear if this worth special-casing, but it creates less
     // java junk, so dodges the GC.
     if (len == 1) {
         jlong d = aPattern[0];
         if (d < 0) {
             ALOG_BRIDGE("  invalid vibration duration < 0");
             return;
@@ -604,17 +601,17 @@ AndroidBridge::GetSystemColors(AndroidSy
     NS_ASSERTION(aColors != nullptr, "AndroidBridge::GetSystemColors: aColors is null!");
     if (!aColors)
         return;
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
 
     jintArray arr = GeckoAppShell::GetSystemColoursWrapper();
     if (!arr)
         return;
 
     uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
     jint *elements = env->GetIntArrayElements(arr, 0);
 
@@ -642,17 +639,17 @@ AndroidBridge::GetIconForExtension(const
     NS_ASSERTION(aBuf != nullptr, "AndroidBridge::GetIconForExtension: aBuf is null!");
     if (!aBuf)
         return;
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
 
     jbyteArray arr = GeckoAppShell::GetIconForExtensionWrapper(NS_ConvertUTF8toUTF16(aFileExt), aIconSize);
 
     NS_ASSERTION(arr != nullptr, "AndroidBridge::GetIconForExtension: Returned pixels array is null!");
     if (!arr)
         return;
 
     uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
@@ -689,17 +686,17 @@ AndroidBridge::SetLayerClient(JNIEnv* en
         // and we do that by setting the first-paint flag.
         nsWindow::ForceIsFirstPaint();
     }
 }
 
 void
 AndroidBridge::RegisterCompositor(JNIEnv *env)
 {
-    if (mGLControllerObj != NULL && !mGLControllerObj->isNull()) {
+    if (mGLControllerObj != nullptr && !mGLControllerObj->isNull()) {
         // we already have this set up, no need to do it again
         return;
     }
 
     jobject glController = LayerView::RegisterCompositorWrapper();
     if (!glController) {
         return;
     }
@@ -715,22 +712,22 @@ AndroidBridge::CreateEGLSurfaceForCompos
     }
     MOZ_ASSERT(mGLControllerObj, "AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref");
 
     JNIEnv* env = GetJNIForThread(); // called on the compositor thread
     if (!env) {
         return nullptr;
     }
 
+    AutoLocalJNIFrame jniFrame(env, 1);
     jobject eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper();
     if (!eglSurface)
         return nullptr;
 
     EGLSurface ret = reinterpret_cast<EGLSurface>(env->GetIntField(eglSurface, jEGLSurfacePointerField));
-    env->DeleteLocalRef(eglSurface);
     return ret;
 }
 
 bool
 AndroidBridge::GetStaticIntField(const char *className, const char *fieldName, int32_t* aInt, JNIEnv* jEnv /* = nullptr */)
 {
     ALOG_BRIDGE("AndroidBridge::GetStaticIntField %s", fieldName);
 
@@ -761,32 +758,32 @@ AndroidBridge::GetStaticStringField(cons
     ALOG_BRIDGE("AndroidBridge::GetStaticStringField %s", fieldName);
 
     if (!jEnv) {
         jEnv = GetJNIEnv();
         if (!jEnv)
             return false;
     }
 
+    AutoLocalJNIFrame jniFrame(jEnv, 1);
     initInit();
     getClassGlobalRef(className);
     jfieldID field = getStaticField(fieldName, "Ljava/lang/String;");
 
     if (!field) {
         jEnv->DeleteGlobalRef(jClass);
         return false;
     }
 
     jstring jstr = (jstring) jEnv->GetStaticObjectField(jClass, field);
     jEnv->DeleteGlobalRef(jClass);
     if (!jstr)
         return false;
 
     result.Assign(nsJNIString(jstr, jEnv));
-    jEnv->DeleteLocalRef(jstr);
     return true;
 }
 
 // Available for places elsewhere in the code to link to.
 bool
 mozilla_AndroidBridge_SetMainThread(pthread_t thr)
 {
     return AndroidBridge::Bridge()->SetMainThread(thr);
@@ -982,17 +979,17 @@ AndroidBridge::ValidateBitmap(jobject bi
 
 bool
 AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
     jintArray arr = GeckoAppShell::InitCameraWrapper(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) width, (int32_t) height);
 
     if (!arr)
         return false;
 
     jint *elements = env->GetIntArrayElements(arr, 0);
 
     *width = elements[1];
@@ -1010,17 +1007,17 @@ void
 AndroidBridge::GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
 {
     ALOG_BRIDGE("AndroidBridge::GetCurrentBatteryInformation");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
 
     // To prevent calling too many methods through JNI, the Java method returns
     // an array of double even if we actually want a double and a boolean.
     jdoubleArray arr = GeckoAppShell::GetCurrentBatteryInformationWrapper();
     if (!arr || env->GetArrayLength(arr) != 3) {
         return;
     }
 
@@ -1037,17 +1034,17 @@ void
 AndroidBridge::HandleGeckoMessage(const nsAString &aMessage, nsAString &aRet)
 {
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
     jstring returnMessage = GeckoAppShell::HandleGeckoMessageWrapper(aMessage);
 
     if (!returnMessage)
         return;
 
     nsJNIString jniStr(returnMessage, env);
     aRet.Assign(jniStr);
     ALOG_BRIDGE("leaving %s", __PRETTY_FUNCTION__);
@@ -1067,17 +1064,17 @@ AndroidBridge::GetSegmentInfoForText(con
     data.segments() = 0;
     data.charsPerSegment() = 0;
     data.charsAvailableInLastSegment() = 0;
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return NS_ERROR_FAILURE;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 2);
     jstring jText = NewJavaString(&jniFrame, aText);
     jobject obj = env->CallStaticObjectMethod(mAndroidSmsMessageClass,
                                               jCalculateLength, jText, JNI_FALSE);
     if (jniFrame.CheckForException())
         return NS_ERROR_FAILURE;
 
     jintArray arr = static_cast<jintArray>(obj);
     if (!arr || env->GetArrayLength(arr) != 4)
@@ -1146,26 +1143,27 @@ AndroidBridge::CreateMessageList(const d
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 2);
 
     jobjectArray numbers =
         (jobjectArray)env->NewObjectArray(aFilter.numbers().Length(),
                                           jStringClass,
                                           NewJavaString(&jniFrame, EmptyString()));
 
     for (uint32_t i = 0; i < aFilter.numbers().Length(); ++i) {
-        env->SetObjectArrayElement(numbers, i,
-                                   NewJavaString(&jniFrame, aFilter.numbers()[i]));
+        jstring elem = NewJavaString(&jniFrame, aFilter.numbers()[i]);
+        env->SetObjectArrayElement(numbers, i, elem);
+        env->DeleteLocalRef(elem);
     }
 
     GeckoAppShell::CreateMessageListWrapper(aFilter.startDate(), aFilter.endDate(),
                              numbers, aFilter.numbers().Length(),
                              aFilter.delivery(), aReverse, requestId);
 }
 
 void
@@ -1219,17 +1217,17 @@ void
 AndroidBridge::GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo)
 {
     ALOG_BRIDGE("AndroidBridge::GetCurrentNetworkInformation");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
 
     // To prevent calling too many methods through JNI, the Java method returns
     // an array of double even if we actually want a double, two booleans, and an integer.
 
     jdoubleArray arr = GeckoAppShell::GetCurrentNetworkInformationWrapper();
     if (!arr || env->GetArrayLength(arr) != 4) {
         return;
     }
@@ -1246,17 +1244,17 @@ AndroidBridge::GetCurrentNetworkInformat
 
 void *
 AndroidBridge::LockBitmap(jobject bitmap)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return nullptr;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 0);
 
     int err;
     void *buf;
 
     if ((err = AndroidBitmap_lockPixels(env, bitmap, &buf)) != 0) {
         ALOG_BRIDGE("AndroidBitmap_lockPixels failed! (error %d)", err);
         buf = nullptr;
     }
@@ -1266,17 +1264,17 @@ AndroidBridge::LockBitmap(jobject bitmap
 
 void
 AndroidBridge::UnlockBitmap(jobject bitmap)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 0);
 
     int err;
 
     if ((err = AndroidBitmap_unlockPixels(env, bitmap)) != 0)
         ALOG_BRIDGE("AndroidBitmap_unlockPixels failed! (error %d)", err);
 }
 
 
@@ -1647,17 +1645,17 @@ AndroidBridge::GetProxyForURI(const nsAC
                               const nsACString & aHost,
                               const int32_t      aPort,
                               nsACString & aResult)
 {
     JNIEnv* env = GetJNIEnv();
     if (!env)
         return NS_ERROR_FAILURE;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
     jstring jstrRet = GeckoAppShell::GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec),
                                             NS_ConvertUTF8toUTF16(aScheme),
                                             NS_ConvertUTF8toUTF16(aHost),
                                             aPort);
 
     if (!jstrRet)
         return NS_ERROR_FAILURE;
 
@@ -1699,17 +1697,17 @@ Java_org_mozilla_gecko_GeckoAppShell_all
 
 bool
 AndroidBridge::GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult)
 {
     JNIEnv* env = GetJNIForThread();
     if (!env)
         return false;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
 
     jstring jstrThreadName = GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId);
 
     if (!jstrThreadName)
         return false;
 
     nsJNIString jniStr(jstrThreadName, env);
     CopyUTF16toUTF8(jniStr.get(), aResult);
@@ -1719,26 +1717,25 @@ AndroidBridge::GetThreadNameJavaProfilin
 bool
 AndroidBridge::GetFrameNameJavaProfiling(uint32_t aThreadId, uint32_t aSampleId,
                                           uint32_t aFrameId, nsCString & aResult)
 {
     JNIEnv* env = GetJNIForThread();
     if (!env)
         return false;
 
-    AutoLocalJNIFrame jniFrame(env);
+    AutoLocalJNIFrame jniFrame(env, 1);
 
     jstring jstrSampleName = GeckoJavaSampler::GetFrameNameJavaProfilingWrapper(aThreadId, aSampleId, aFrameId);
 
     if (!jstrSampleName)
         return false;
 
     nsJNIString jniStr(jstrSampleName, env);
     CopyUTF16toUTF8(jniStr.get(), aResult);
-    env->DeleteLocalRef(jstrSampleName);
     return true;
 }
 
 nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jobject buffer)
 {
     nsresult rv;
     float scale = 1.0;
 
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -906,17 +906,17 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject instance)
 {
     if (!AndroidBridge::Bridge()) {
         return;
     }
 
-    NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(NULL);
+    NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(nullptr);
     if (!oldRef || oldRef->isNull()) {
         MOZ_ASSERT(false, "Clearing a non-existent NPZC");
     } else {
         delete oldRef;
     }
 }
 
 NS_EXPORT void JNICALL
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -62,61 +62,61 @@ public:
 private:
     int32_t mRefCnt;
     jobject mObject;
 };
 
 class WrappedJavaObject {
 public:
     WrappedJavaObject() :
-        wrapped_obj(NULL)
+        wrapped_obj(nullptr)
     { }
 
-    WrappedJavaObject(jobject jobj) : wrapped_obj(NULL) {
+    WrappedJavaObject(jobject jobj) : wrapped_obj(nullptr) {
         Init(jobj);
     }
 
     void Init(jobject jobj) {
         wrapped_obj = jobj;
     }
 
     bool isNull() const {
-        return wrapped_obj == NULL;
+        return wrapped_obj == nullptr;
     }
 
     jobject wrappedObject() const {
         return wrapped_obj;
     }
 
 protected:
     jobject wrapped_obj;
 };
 
 class AutoGlobalWrappedJavaObject : protected WrappedJavaObject{
 public:
     AutoGlobalWrappedJavaObject() :
-        wrapped_obj(NULL)
+        wrapped_obj(nullptr)
     { }
 
-    AutoGlobalWrappedJavaObject(jobject jobj, JNIEnv* env) : wrapped_obj(NULL) {
+    AutoGlobalWrappedJavaObject(jobject jobj, JNIEnv* env) : wrapped_obj(nullptr) {
         Init(jobj, env);
     }
 
     virtual ~AutoGlobalWrappedJavaObject();
     void Dispose();
 
     void Init(jobject jobj, JNIEnv* env) {
         if (!isNull()) {
             env->DeleteGlobalRef(wrapped_obj);
         }
         wrapped_obj = env->NewGlobalRef(jobj);
     }
 
     bool isNull() const {
-        return wrapped_obj == NULL;
+        return wrapped_obj == nullptr;
     }
 
     jobject wrappedObject() const {
         return wrapped_obj;
     }
 
 protected:
     jobject wrapped_obj;
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -499,17 +499,17 @@ class nsIWidget : public nsISupports {
     {
       ClearNativeTouchSequence();
     }
 
         
     /**
      * Create and initialize a widget. 
      *
-     * All the arguments can be NULL in which case a top level window
+     * All the arguments can be null in which case a top level window
      * with size 0 is created. The event callback function has to be
      * provided only if the caller wants to deal with the events this
      * widget receives.  The event callback is basically a preprocess
      * hook called synchronously. The return value determines whether
      * the event goes to the default window procedure or it is hidden
      * to the os. The assumption is that if the event handler returns
      * false the widget does not see the event. The widget should not 
      * automatically clear the window to the background color. The 
--- a/widget/windows/winrt/MetroWidget.cpp
+++ b/widget/windows/winrt/MetroWidget.cpp
@@ -1610,12 +1610,13 @@ MetroWidget::Observe(nsISupports *subjec
 
     int reScan = swscanf(data, L"%d,%llu",
       &presShellId, &viewId);
     if (reScan != 2) {
       NS_WARNING("Malformed apzc-disable-zoom message");
     }
 
     ScrollableLayerGuid guid = ScrollableLayerGuid(mRootLayerTreeId, presShellId, viewId);
-    APZController::sAPZC->UpdateZoomConstraints(guid, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f));
+    APZController::sAPZC->UpdateZoomConstraints(guid,
+      ZoomConstraints(false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f)));
   }
   return NS_OK;
 }
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -207,17 +207,17 @@ ResidentFastDistinguishedAmount(int64_t*
 #include <libutil.h>
 #include <algorithm>
 
 static nsresult
 GetKinfoVmentrySelf(int64_t* prss, uint64_t* maxreg)
 {
     int cnt;
     struct kinfo_vmentry *vmmap, *kve;
-    if ((vmmap = kinfo_getvmmap(getpid(), &cnt)) == NULL)
+    if ((vmmap = kinfo_getvmmap(getpid(), &cnt)) == nullptr)
         return NS_ERROR_FAILURE;
 
     if (prss)
         *prss = 0;
     if (maxreg)
         *maxreg = 0;
 
     for (int i = 0; i < cnt; i++) {
@@ -233,28 +233,28 @@ GetKinfoVmentrySelf(int64_t* prss, uint6
     return NS_OK;
 }
 
 #define HAVE_PRIVATE_REPORTER
 static nsresult
 PrivateDistinguishedAmount(int64_t* aN)
 {
     int64_t priv;
-    nsresult rv = GetKinfoVmentrySelf(&priv, NULL);
+    nsresult rv = GetKinfoVmentrySelf(&priv, nullptr);
     NS_ENSURE_SUCCESS(rv, rv);
     *aN = priv * getpagesize();
     return NS_OK;
 }
 
 #define HAVE_VSIZE_MAX_CONTIGUOUS_REPORTER 1
 static nsresult
 VsizeMaxContiguousDistinguishedAmount(int64_t* aN)
 {
     uint64_t biggestRegion;
-    nsresult rv = GetKinfoVmentrySelf(NULL, &biggestRegion);
+    nsresult rv = GetKinfoVmentrySelf(nullptr, &biggestRegion);
     if (NS_SUCCEEDED(rv))
         *aN = biggestRegion;
 
     return NS_OK;
 }
 #endif // FreeBSD
 
 #elif defined(SOLARIS)
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -894,16 +894,34 @@ NS_IMETHODIMP _class::QueryInterface(REF
     NS_INTERFACE_TABLE_ENTRY(_class, _i7)                                     \
     NS_INTERFACE_TABLE_ENTRY(_class, _i8)                                     \
     NS_INTERFACE_TABLE_ENTRY(_class, _i9)                                     \
     NS_INTERFACE_TABLE_ENTRY(_class, _i10)                                    \
     NS_INTERFACE_TABLE_ENTRY(_class, _i11)                                    \
     NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1)              \
   NS_INTERFACE_TABLE_END
 
+#define NS_INTERFACE_TABLE12(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7,       \
+                             _i8, _i9, _i10, _i11, _i12)                      \
+  NS_INTERFACE_TABLE_BEGIN                                                    \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i1)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i2)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i3)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i4)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i5)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i6)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i7)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i8)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i9)                                     \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i10)                                    \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i11)                                    \
+    NS_INTERFACE_TABLE_ENTRY(_class, _i12)                                    \
+    NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsISupports, _i1)              \
+  NS_INTERFACE_TABLE_END
+
 #define NS_IMPL_QUERY_INTERFACE0(_class)                                      \
   NS_INTERFACE_TABLE_HEAD(_class)                                             \
   NS_INTERFACE_TABLE0(_class)                                                 \
   NS_INTERFACE_TABLE_TAIL
 
 #define NS_IMPL_QUERY_INTERFACE1(_class, _i1)                                 \
   NS_INTERFACE_TABLE_HEAD(_class)                                             \
   NS_INTERFACE_TABLE1(_class, _i1)                                            \
@@ -960,16 +978,23 @@ NS_IMETHODIMP _class::QueryInterface(REF
 
 #define NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6,       \
                                   _i7, _i8, _i9, _i10, _i11)                  \
   NS_INTERFACE_TABLE_HEAD(_class)                                             \
   NS_INTERFACE_TABLE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8,        \
                        _i9, _i10, _i11)                                       \
   NS_INTERFACE_TABLE_TAIL
 
+#define NS_IMPL_QUERY_INTERFACE12(_class, _i1, _i2, _i3, _i4, _i5, _i6,       \
+                                  _i7, _i8, _i9, _i10, _i11, _i12)            \
+  NS_INTERFACE_TABLE_HEAD(_class)                                             \
+  NS_INTERFACE_TABLE12(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8,        \
+                       _i9, _i10, _i11, _i12)                                 \
+  NS_INTERFACE_TABLE_TAIL
+
 
 /**
  * Declare that you're going to inherit from something that already
  * implements nsISupports, but also implements an additional interface, thus
  * causing an ambiguity. In this case you don't need another mRefCnt, you
  * just need to forward the definitions to the appropriate superclass. E.g.
  *
  * class Bar : public Foo, public nsIBar {  // both provide nsISupports
@@ -1283,16 +1308,23 @@ NS_IMETHODIMP_(nsrefcnt) Class::Release(
 
 #define NS_IMPL_ISUPPORTS11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8,   \
                             _i9, _i10, _i11)                                  \
   NS_IMPL_ADDREF(_class)                                                      \
   NS_IMPL_RELEASE(_class)                                                     \
   NS_IMPL_QUERY_INTERFACE11(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8,   \
                             _i9, _i10, _i11)
 
+#define NS_IMPL_ISUPPORTS12(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8,   \
+                            _i9, _i10, _i11, _i12)                            \
+  NS_IMPL_ADDREF(_class)                                                      \
+  NS_IMPL_RELEASE(_class)                                                     \
+  NS_IMPL_QUERY_INTERFACE12(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8,   \
+                            _i9, _i10, _i11, _i12)
+
 #define NS_IMPL_ISUPPORTS_INHERITED0(Class, Super)                            \
     NS_IMPL_QUERY_INTERFACE_INHERITED0(Class, Super)                          \
     NS_IMPL_ADDREF_INHERITED(Class, Super)                                    \
     NS_IMPL_RELEASE_INHERITED(Class, Super)                                   \
 
 #define NS_IMPL_ISUPPORTS_INHERITED1(Class, Super, i1)                        \
     NS_IMPL_QUERY_INTERFACE_INHERITED1(Class, Super, i1)                      \
     NS_IMPL_ADDREF_INHERITED(Class, Super)                                    \