Merge m-c to inbound a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 26 Aug 2014 17:49:52 -0700
changeset 223369 83289be2cd12f0256757598c08e8082c95fce24e
parent 223344 29faabfdb3b27980094dd5976dbe55bb64cb8ef7 (current diff)
parent 223368 7f0a45d29ac56098b8d6928f90c65fc8311ba66e (diff)
child 223370 0753f7b93ab78d8730677c5e094591a421078ca0
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone34.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 inbound a=merge
--- a/browser/base/content/aboutcerterror/aboutCertError.xhtml
+++ b/browser/base/content/aboutcerterror/aboutCertError.xhtml
@@ -75,26 +75,31 @@
           if (node.textContent == "#1")
             node.textContent = location.host;
           else
             for(var i = 0; i < node.childNodes.length; i++)
               replaceWithHost(node.childNodes[i]);
         };
         replaceWithHost(intro);
 
-        if (getCSSClass() == "expertBadCert") {
+        var cssClass = getCSSClass();
+        if (cssClass == "expertBadCert") {
           toggle('technicalContent');
           toggle('expertContent');
         }
 
         // Disallow overrides if this is a Strict-Transport-Security
         // host and the cert is bad (STS Spec section 7.3) or if the
         // certerror is in a frame (bug 633691).
-        if (getCSSClass() == "badStsCert" || window != top)
+        if (cssClass == "badStsCert" || window != top) {
           document.getElementById("expertContent").setAttribute("hidden", "true");
+        }
+        if (cssClass != "badStsCert") {
+          document.getElementById("badStsCertExplanation").setAttribute("hidden", "true");
+        }
 
         var tech = document.getElementById("technicalContentText");
         if (tech)
           tech.textContent = getDescription();
 
         addDomainErrorLink();
       }
 
@@ -209,16 +214,17 @@
           <p id="introContentP1">&certerror.introPara1;</p>
           <p>&certerror.introPara2;</p>
         </div>
 
         <div id="whatShouldIDoContent">
           <h2>&certerror.whatShouldIDo.heading;</h2>
           <div id="whatShouldIDoContentText">
             <p>&certerror.whatShouldIDo.content;</p>
+            <p id="badStsCertExplanation">&certerror.whatShouldIDo.badStsCertExplanation;</p>
             <button id='getMeOutOfHereButton'>&certerror.getMeOutOfHere.label;</button>
           </div>
         </div>
 
         <!-- The following sections can be unhidden by default by setting the
              "browser.xul.error_pages.expert_bad_cert" pref to true -->
         <h2 id="technicalContent" class="expander" collapsed="true">
           <button onclick="toggle('technicalContent');">&certerror.technical.heading;</button>
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -75,17 +75,33 @@ addEventListener("DOMAutoComplete", func
   LoginManagerContent.onUsernameInput(event);
 });
 addEventListener("blur", function(event) {
   LoginManagerContent.onUsernameInput(event);
 });
 
 if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
   addEventListener("contextmenu", function (event) {
-    sendSyncMessage("contextmenu", {}, { event: event });
+    let defaultPrevented = event.defaultPrevented;
+    if (!Services.prefs.getBoolPref("dom.event.contextmenu.enabled")) {
+      let plugin = null;
+      try {
+        plugin = event.target.QueryInterface(Ci.nsIObjectLoadingContent);
+      } catch (e) {}
+      if (plugin && plugin.displayedType == Ci.nsIObjectLoadingContent.TYPE_PLUGIN) {
+        // Don't open a context menu for plugins.
+        return;
+      }
+
+      defaultPrevented = false;
+    }
+
+    if (!defaultPrevented) {
+      sendSyncMessage("contextmenu", {}, { event: event });
+    }
   }, false);
 } else {
   addEventListener("mozUITour", function(event) {
     if (!Services.prefs.getBoolPref("browser.uitour.enabled"))
       return;
 
     let handled = UITour.onPageEvent(event);
     if (handled)
@@ -611,9 +627,9 @@ let DOMFullscreenHandler = {
     if (aEvent.type == "MozEnteredDomFullscreen") {
       this._fullscreenDoc = aEvent.target;
       sendAsyncMessage("MozEnteredDomFullscreen", {
         origin: this._fullscreenDoc.nodePrincipal.origin,
       });
     }
   }
 };
-DOMFullscreenHandler.init();
\ No newline at end of file
+DOMFullscreenHandler.init();
--- a/browser/locales/en-US/chrome/browser/aboutCertError.dtd
+++ b/browser/locales/en-US/chrome/browser/aboutCertError.dtd
@@ -21,16 +21,20 @@ securely to <b>#1</b>, but we can't conf
 <!ENTITY certerror.introPara2 "Normally, when you try to connect securely,
 sites will present trusted identification to prove that you are
 going to the right place. However, this site's identity can't be verified.">
 
 <!ENTITY certerror.whatShouldIDo.heading "What Should I Do?">
 <!ENTITY certerror.whatShouldIDo.content "If you usually connect to
 this site without problems, this error could mean that someone is
 trying to impersonate the site, and you shouldn't continue.">
+<!ENTITY certerror.whatShouldIDo.badStsCertExplanation "This site uses HTTP
+Strict Transport Security (HSTS) to specify that &brandShortName; only connect
+to it securely. As a result, it is not possible to add an exception for this
+certificate.">
 <!ENTITY certerror.getMeOutOfHere.label "Get me out of here!">
 
 <!ENTITY certerror.expert.heading "I Understand the Risks">
 <!ENTITY certerror.expert.content "If you understand what's going on, you
 can tell &brandShortName; to start trusting this site's identification.
 <b>Even if you trust the site, this error could mean that someone is
 tampering with your connection.</b>">
 <!ENTITY certerror.expert.contentPara2 "Don't add an exception unless
--- a/build/stlport/moz.build
+++ b/build/stlport/moz.build
@@ -55,9 +55,10 @@ LOCAL_INCLUDES += [
 DISABLE_STL_WRAPPING = True
 NO_VISIBILITY_FLAGS = True
 
 # Suppress warnings in third-party code.
 if CONFIG['GNU_CXX']:
     CXXFLAGS += [
         '-Wno-empty-body',
         '-Wno-type-limits',
+        '-Wno-unused-local-typedefs',
     ]
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -587,28 +587,31 @@ ContentChild::Init(MessageLoop* aIOLoop,
     InitProcessAttributes();
 
     return true;
 }
 
 void
 ContentChild::InitProcessAttributes()
 {
+#ifdef MOZ_WIDGET_GONK
 #ifdef MOZ_NUWA_PROCESS
     if (IsNuwaProcess()) {
         SetProcessName(NS_LITERAL_STRING("(Nuwa)"), false);
         return;
     }
 #endif
     if (mIsForApp && !mIsForBrowser) {
         SetProcessName(NS_LITERAL_STRING("(Preallocated app)"), false);
     } else {
         SetProcessName(NS_LITERAL_STRING("Browser"), false);
     }
-
+#else
+    SetProcessName(NS_LITERAL_STRING("Web Content"), true);
+#endif
 }
 
 void
 ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride)
 {
     if (!mCanOverrideProcessName) {
         return;
     }
--- a/dom/mobilemessage/src/android/MobileMessageDatabaseService.h
+++ b/dom/mobilemessage/src/android/MobileMessageDatabaseService.h
@@ -10,16 +10,19 @@
 #include "mozilla/Attributes.h"
 
 namespace mozilla {
 namespace dom {
 namespace mobilemessage {
 
 class MobileMessageDatabaseService MOZ_FINAL : public nsIMobileMessageDatabaseService
 {
+private:
+  ~MobileMessageDatabaseService() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMOBILEMESSAGEDATABASESERVICE
 };
 
 } // namespace mobilemessage
 } // namespace dom
 } // namespace mozilla
--- a/dom/mobilemessage/src/android/SmsService.h
+++ b/dom/mobilemessage/src/android/SmsService.h
@@ -9,16 +9,19 @@
 #include "nsISmsService.h"
 
 namespace mozilla {
 namespace dom {
 namespace mobilemessage {
 
 class SmsService MOZ_FINAL : public nsISmsService
 {
+private:
+  ~SmsService() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISMSSERVICE
 };
 
 } // namespace mobilemessage
 } // namespace dom
 } // namespace mozilla
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -179,17 +179,20 @@ PluginModuleChild::Init(const std::strin
     }
 
 #if defined(MOZ_X11)
     NS_NAMED_LITERAL_CSTRING(flash10Head, "Shockwave Flash 10.");
     if (StringBeginsWith(nsDependentCString(info.fDescription), flash10Head)) {
         AddQuirk(QUIRK_FLASH_EXPOSE_COORD_TRANSLATION);
     }
 #else // defined(OS_MACOSX)
-    mozilla::plugins::PluginUtilsOSX::SetProcessName(info.fName);
+    const char* namePrefix = "Plugin Content";
+    char nameBuffer[80];
+    snprintf(nameBuffer, sizeof(nameBuffer), "%s (%s)", namePrefix, info.fName);
+    mozilla::plugins::PluginUtilsOSX::SetProcessName(nameBuffer);
 #endif
 
     pluginFile.FreePluginInfo(info);
 
     if (!mLibrary)
 #endif
     {
         nsresult rv = pluginFile.LoadPlugin(&mLibrary);
--- a/dom/plugins/ipc/PluginUtilsOSX.mm
+++ b/dom/plugins/ipc/PluginUtilsOSX.mm
@@ -272,17 +272,17 @@ bool mozilla::plugins::PluginUtilsOSX::S
     return false;
   }
 
   NSString *currentName = [[[NSBundle mainBundle] localizedInfoDictionary] 
                               objectForKey:(NSString *)kCFBundleNameKey];
 
   char formattedName[1024];
   snprintf(formattedName, sizeof(formattedName), 
-      "%s (%s)", [currentName UTF8String], aProcessName);
+      "%s %s", [currentName UTF8String], aProcessName);
 
   aProcessName = formattedName;
 
   // This function is based on Chrome/Webkit's and relies on potentially dangerous SPI.
   typedef CFTypeRef (*LSGetASNType)();
   typedef OSStatus (*LSSetInformationItemType)(int, CFTypeRef,
                                                CFStringRef, 
                                                CFStringRef,
--- a/dom/src/storage/DOMStorageCache.cpp
+++ b/dom/src/storage/DOMStorageCache.cpp
@@ -346,18 +346,16 @@ DOMStorageCache::WaitForPreload(Telemetr
   // done before we've shut the DB down or when the DB could not start,
   // preload has not even be started.
   sDatabase->SyncPreload(this);
 }
 
 nsresult
 DOMStorageCache::GetLength(const DOMStorage* aStorage, uint32_t* aRetval)
 {
-  Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_GETLENGTH_MS> autoTimer;
-
   if (Persist(aStorage)) {
     WaitForPreload(Telemetry::LOCALDOMSTORAGE_GETLENGTH_BLOCKING_MS);
     if (NS_FAILED(mLoadResult)) {
       return mLoadResult;
     }
   }
 
   *aRetval = DataSet(aStorage).mKeys.Count();
@@ -396,18 +394,16 @@ FindKeyOrder(const nsAString& aKey, cons
 
 nsresult
 DOMStorageCache::GetKey(const DOMStorage* aStorage, uint32_t aIndex, nsAString& aRetval)
 {
   // XXX: This does a linear search for the key at index, which would
   // suck if there's a large numer of indexes. Do we care? If so,
   // maybe we need to have a lazily populated key array here or
   // something?
-  Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_GETKEY_MS> autoTimer;
-
   if (Persist(aStorage)) {
     WaitForPreload(Telemetry::LOCALDOMSTORAGE_GETKEY_BLOCKING_MS);
     if (NS_FAILED(mLoadResult)) {
       return mLoadResult;
     }
   }
 
   IndexFinderData data(aIndex, aRetval);
@@ -426,35 +422,31 @@ KeysArrayBuilder(const nsAString& aKey, 
   return PL_DHASH_NEXT;
 }
 
 } // anon
 
 void
 DOMStorageCache::GetKeys(const DOMStorage* aStorage, nsTArray<nsString>& aKeys)
 {
-  Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_GETALLKEYS_MS> autoTimer;
-
   if (Persist(aStorage)) {
     WaitForPreload(Telemetry::LOCALDOMSTORAGE_GETALLKEYS_BLOCKING_MS);
   }
 
   if (NS_FAILED(mLoadResult)) {
     return;
   }
 
   DataSet(aStorage).mKeys.EnumerateRead(KeysArrayBuilder, &aKeys);
 }
 
 nsresult
 DOMStorageCache::GetItem(const DOMStorage* aStorage, const nsAString& aKey,
                          nsAString& aRetval)
 {
-  Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_GETVALUE_MS> autoTimer;
-
   if (Persist(aStorage)) {
     WaitForPreload(Telemetry::LOCALDOMSTORAGE_GETVALUE_BLOCKING_MS);
     if (NS_FAILED(mLoadResult)) {
       return mLoadResult;
     }
   }
 
   // not using AutoString since we don't want to copy buffer to result
@@ -467,18 +459,16 @@ DOMStorageCache::GetItem(const DOMStorag
 
   return NS_OK;
 }
 
 nsresult
 DOMStorageCache::SetItem(const DOMStorage* aStorage, const nsAString& aKey,
                          const nsString& aValue, nsString& aOld)
 {
-  Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_SETVALUE_MS> autoTimer;
-
   if (Persist(aStorage)) {
     WaitForPreload(Telemetry::LOCALDOMSTORAGE_SETVALUE_BLOCKING_MS);
     if (NS_FAILED(mLoadResult)) {
       return mLoadResult;
     }
   }
 
   Data& data = DataSet(aStorage);
@@ -515,18 +505,16 @@ DOMStorageCache::SetItem(const DOMStorag
 
   return NS_OK;
 }
 
 nsresult
 DOMStorageCache::RemoveItem(const DOMStorage* aStorage, const nsAString& aKey,
                             nsString& aOld)
 {
-  Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_REMOVEKEY_MS> autoTimer;
-
   if (Persist(aStorage)) {
     WaitForPreload(Telemetry::LOCALDOMSTORAGE_REMOVEKEY_BLOCKING_MS);
     if (NS_FAILED(mLoadResult)) {
       return mLoadResult;
     }
   }
 
   Data& data = DataSet(aStorage);
@@ -551,18 +539,16 @@ DOMStorageCache::RemoveItem(const DOMSto
   }
 
   return NS_OK;
 }
 
 nsresult
 DOMStorageCache::Clear(const DOMStorage* aStorage)
 {
-  Telemetry::AutoTimer<Telemetry::LOCALDOMSTORAGE_CLEAR_MS> autoTimer;
-
   bool refresh = false;
   if (Persist(aStorage)) {
     // We need to preload all data (know the size) before we can proceeed
     // to correctly decrease cached usage number.
     // XXX as in case of unload, this is not technically needed now, but
     // after super-scope quota introduction we have to do this.  Get telemetry
     // right now.
     WaitForPreload(Telemetry::LOCALDOMSTORAGE_CLEAR_BLOCKING_MS);
--- a/dom/system/android/nsHapticFeedback.h
+++ b/dom/system/android/nsHapticFeedback.h
@@ -2,12 +2,15 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIHapticFeedback.h"
 
 class nsHapticFeedback MOZ_FINAL : public nsIHapticFeedback
 {
+private:
+  ~nsHapticFeedback() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIHAPTICFEEDBACK
 };
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -446,17 +446,17 @@ CompositorD3D11::CreateRenderTargetFromS
       static_cast<const CompositingRenderTargetD3D11*>(aSource);
 
     D3D11_BOX srcBox;
     srcBox.left = aSourcePoint.x;
     srcBox.top = aSourcePoint.y;
     srcBox.front = 0;
     srcBox.right = aSourcePoint.x + aRect.width;
     srcBox.bottom = aSourcePoint.y + aRect.height;
-    srcBox.back = 0;
+    srcBox.back = 1;
 
     const IntSize& srcSize = sourceD3D11->GetSize();
     MOZ_ASSERT(srcSize.width >= 0 && srcSize.height >= 0,
                "render targets should have nonnegative sizes");
     if (srcBox.right <= static_cast<uint32_t>(srcSize.width) &&
         srcBox.bottom <= static_cast<uint32_t>(srcSize.height)) {
       mContext->CopySubresourceRegion(texture, 0,
                                       0, 0, 0,
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -39,16 +39,19 @@ using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 static FT_Library gPlatformFTLibrary = nullptr;
 
 class FreetypeReporter MOZ_FINAL : public nsIMemoryReporter,
                                    public CountingAllocatorBase<FreetypeReporter>
 {
+private:
+    ~FreetypeReporter() {}
+
 public:
     NS_DECL_ISUPPORTS
 
     static void* Malloc(FT_Memory, long size)
     {
         return CountingMalloc(size);
     }
 
--- a/image/decoders/icon/android/nsIconChannel.h
+++ b/image/decoders/icon/android/nsIconChannel.h
@@ -20,25 +20,27 @@
  */
 class nsIconChannel MOZ_FINAL : public nsIChannel {
   public:
     NS_DECL_ISUPPORTS
     NS_FORWARD_NSIREQUEST(mRealChannel->)
     NS_FORWARD_NSICHANNEL(mRealChannel->)
 
     nsIconChannel() {}
-    ~nsIconChannel() {}
 
     /**
      * Called by nsIconProtocolHandler after it creates this channel.
      * Must be called before calling any other function on this object.
      * If this method fails, no other function must be called on this object.
      */
     nsresult Init(nsIURI* aURI);
+
   private:
+    ~nsIconChannel() {}
+
     /**
      * The channel to the temp icon file (e.g. to /tmp/2qy9wjqw.html).
      * Will always be non-null after a successful Init.
      */
     nsCOMPtr<nsIChannel> mRealChannel;
 };
 
 #endif
--- a/ipc/app/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
+++ b/ipc/app/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in
@@ -1,7 +1,7 @@
 /* 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/. */
 
 /* Localized versions of Info.plist keys */
 
-CFBundleName = "%APP_NAME% Plugin Process";
+CFBundleName = "%APP_NAME%";
new file mode 100644
--- /dev/null
+++ b/ipc/glue/ProcessUtils_mac.mm
@@ -0,0 +1,20 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ProcessUtils.h"
+
+#include "nsString.h"
+
+#include "mozilla/plugins/PluginUtilsOSX.h"
+
+namespace mozilla {
+namespace ipc {
+
+void SetThisProcessName(const char *aName)
+{
+  mozilla::plugins::PluginUtilsOSX::SetProcessName(aName);
+}
+
+} // namespace ipc
+} // namespace mozilla
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -80,16 +80,20 @@ else:
 if CONFIG['OS_ARCH'] == 'Linux':
     UNIFIED_SOURCES += [
         'ProcessUtils_linux.cpp',
     ]
 elif CONFIG['OS_ARCH'] in ('DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD'):
     UNIFIED_SOURCES += [
         'ProcessUtils_bsd.cpp'
     ]
+elif CONFIG['OS_ARCH'] in ('Darwin'):
+    UNIFIED_SOURCES += [
+        'ProcessUtils_mac.mm'
+    ]
 else:
     UNIFIED_SOURCES += [
         'ProcessUtils_none.cpp',
     ]
 
 EXPORTS.ipc += [
     'IPCMessageUtils.h',
 ]
--- a/js/public/ProfilingFrameIterator.h
+++ b/js/public/ProfilingFrameIterator.h
@@ -10,35 +10,39 @@
 #include "mozilla/Alignment.h"
 
 #include <stdint.h>
 
 #include "js/Utility.h"
 
 class JSAtom;
 struct JSRuntime;
-namespace js { class AsmJSActivation; class AsmJSProfilingFrameIterator; }
+
+namespace js {
+    class Activation;
+    class AsmJSProfilingFrameIterator;
+}
 
 namespace JS {
 
 // This iterator can be used to walk the stack of a thread suspended at an
 // arbitrary pc. To provide acurate results, profiling must have been enabled
 // (via EnableRuntimeProfilingStack) before executing the callstack being
 // unwound.
 class JS_PUBLIC_API(ProfilingFrameIterator)
 {
-    js::AsmJSActivation *activation_;
+    js::Activation *activation_;
 
     static const unsigned StorageSpace = 6 * sizeof(void*);
     mozilla::AlignedStorage<StorageSpace> storage_;
-    js::AsmJSProfilingFrameIterator &iter() {
+    js::AsmJSProfilingFrameIterator &asmJSIter() {
         JS_ASSERT(!done());
         return *reinterpret_cast<js::AsmJSProfilingFrameIterator*>(storage_.addr());
     }
-    const js::AsmJSProfilingFrameIterator &iter() const {
+    const js::AsmJSProfilingFrameIterator &asmJSIter() const {
         JS_ASSERT(!done());
         return *reinterpret_cast<const js::AsmJSProfilingFrameIterator*>(storage_.addr());
     }
 
     void settle();
 
   public:
     struct RegisterState
@@ -59,13 +63,19 @@ class JS_PUBLIC_API(ProfilingFrameIterat
     //  - is weakly monotonically increasing (may be equal for successive frames)
     //  - will compare greater than newer native and psuedo-stack frame addresses
     //    and less than older native and psuedo-stack frame addresses
     void *stackAddress() const;
 
     // Return a label suitable for regexp-matching as performed by
     // browser/devtools/profiler/cleopatra/js/parserWorker.js
     const char *label() const;
+
+  private:
+    void iteratorConstruct(const RegisterState &state);
+    void iteratorConstruct();
+    void iteratorDestroy();
+    bool iteratorDone();
 };
 
 } // namespace JS
 
 #endif  /* js_ProfilingFrameIterator_h */
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -2,16 +2,17 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * 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 ds_LifoAlloc_h
 #define ds_LifoAlloc_h
 
+#include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/MemoryChecking.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/TemplateLib.h"
 #include "mozilla/TypeTraits.h"
 
@@ -142,17 +143,17 @@ class BumpChunk
     }
 
     static BumpChunk *new_(size_t chunkSize);
     static void delete_(BumpChunk *chunk);
 };
 
 } // namespace detail
 
-void
+MOZ_NORETURN void
 CrashAtUnhandlableOOM(const char *reason);
 
 // LIFO bump allocator: used for phase-oriented and fast LIFO allocations.
 //
 // Note: |latest| is not necessary "last". We leave BumpChunks latent in the
 // chain after they've been released to avoid thrashing before a GC.
 class LifoAlloc
 {
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -374,23 +374,23 @@ class MinorCollectionTracer : public JST
             ArrayBufferObject::restoreArrayBufferLists(liveArrayBuffers);
     }
 };
 
 } /* namespace gc */
 } /* namespace js */
 
 static AllocKind
-GetObjectAllocKindForCopy(JSRuntime *rt, JSObject *obj)
+GetObjectAllocKindForCopy(const Nursery &nursery, JSObject *obj)
 {
     if (obj->is<ArrayObject>()) {
         JS_ASSERT(obj->numFixedSlots() == 0);
 
         /* Use minimal size object if we are just going to copy the pointer. */
-        if (!rt->gc.nursery.isInside(obj->getElementsHeader()))
+        if (!nursery.isInside(obj->getElementsHeader()))
             return FINALIZE_OBJECT0_BACKGROUND;
 
         size_t nelements = obj->getDenseCapacity();
         return GetBackgroundAllocKind(GetGCArrayKind(nelements));
     }
 
     if (obj->is<JSFunction>())
         return obj->as<JSFunction>().getAllocKind();
@@ -405,17 +405,17 @@ GetObjectAllocKindForCopy(JSRuntime *rt,
     }
 
     AllocKind kind = GetGCObjectFixedSlotsKind(obj->numFixedSlots());
     JS_ASSERT(!IsBackgroundFinalized(kind));
     JS_ASSERT(CanBeFinalizedInBackground(kind, obj->getClass()));
     return GetBackgroundAllocKind(kind);
 }
 
-void *
+MOZ_ALWAYS_INLINE void *
 js::Nursery::allocateFromTenured(Zone *zone, AllocKind thingKind)
 {
     void *t = zone->allocator.arenas.allocateFromFreeList(thingKind, Arena::thingSize(thingKind));
     if (t)
         return t;
     zone->allocator.arenas.checkEmptyFreeList(thingKind);
     return zone->allocator.arenas.allocateFromArena(zone, thingKind);
 }
@@ -515,17 +515,18 @@ js::Nursery::collectToFixedPoint(MinorCo
 
 MOZ_ALWAYS_INLINE void
 js::Nursery::traceObject(MinorCollectionTracer *trc, JSObject *obj)
 {
     const Class *clasp = obj->getClass();
     if (clasp->trace)
         clasp->trace(trc, obj);
 
-    if (!obj->isNative())
+    MOZ_ASSERT(obj->isNative() == clasp->isNative());
+    if (!clasp->isNative())
         return;
 
     // Note: the contents of copy on write elements pointers are filled in
     // during parsing and cannot contain nursery pointers.
     if (!obj->hasEmptyElements() && !obj->denseElementsAreCopyOnWrite())
         markSlots(trc, obj->getDenseElements(), obj->getDenseInitializedLength());
 
     HeapSlot *fixedStart, *fixedEnd, *dynStart, *dynEnd;
@@ -564,33 +565,33 @@ js::Nursery::markSlot(MinorCollectionTra
 
     JSObject *tenured = static_cast<JSObject*>(moveToTenured(trc, obj));
     slotp->unsafeGet()->setObject(*tenured);
 }
 
 void *
 js::Nursery::moveToTenured(MinorCollectionTracer *trc, JSObject *src)
 {
+    AllocKind dstKind = GetObjectAllocKindForCopy(*this, src);
     Zone *zone = src->zone();
-    AllocKind dstKind = GetObjectAllocKindForCopy(trc->runtime(), src);
     JSObject *dst = static_cast<JSObject *>(allocateFromTenured(zone, dstKind));
     if (!dst)
         CrashAtUnhandlableOOM("Failed to allocate object while tenuring.");
 
     trc->tenuredSize += moveObjectToTenured(dst, src, dstKind);
 
     RelocationOverlay *overlay = reinterpret_cast<RelocationOverlay *>(src);
     overlay->forwardTo(dst);
     trc->insertIntoFixupList(overlay);
 
     TracePromoteToTenured(src, dst);
     return static_cast<void *>(dst);
 }
 
-size_t
+MOZ_ALWAYS_INLINE size_t
 js::Nursery::moveObjectToTenured(JSObject *dst, JSObject *src, AllocKind dstKind)
 {
     size_t srcSize = Arena::thingSize(dstKind);
     size_t tenuredSize = srcSize;
 
     /*
      * Arrays do not necessarily have the same AllocKind between src and dst.
      * We deal with this by copying elements manually, possibly re-inlining
@@ -641,17 +642,17 @@ js::Nursery::forwardTypedArrayPointers(J
      * least one.
      */
     size_t nslots = 1;
     setSlotsForwardingPointer(reinterpret_cast<HeapSlot*>(srcData),
                               reinterpret_cast<HeapSlot*>(dstData),
                               nslots);
 }
 
-size_t
+MOZ_ALWAYS_INLINE size_t
 js::Nursery::moveSlotsToTenured(JSObject *dst, JSObject *src, AllocKind dstKind)
 {
     /* Fixed slots have already been copied over. */
     if (!src->hasDynamicSlots())
         return 0;
 
     if (!isInside(src->slots)) {
         hugeSlots.remove(src->slots);
@@ -663,17 +664,17 @@ js::Nursery::moveSlotsToTenured(JSObject
     dst->slots = zone->pod_malloc<HeapSlot>(count);
     if (!dst->slots)
         CrashAtUnhandlableOOM("Failed to allocate slots while tenuring.");
     PodCopy(dst->slots, src->slots, count);
     setSlotsForwardingPointer(src->slots, dst->slots, count);
     return count * sizeof(HeapSlot);
 }
 
-size_t
+MOZ_ALWAYS_INLINE size_t
 js::Nursery::moveElementsToTenured(JSObject *dst, JSObject *src, AllocKind dstKind)
 {
     if (src->hasEmptyElements() || src->denseElementsAreCopyOnWrite())
         return 0;
 
     Zone *zone = src->zone();
     ObjectElements *srcHeader = src->getElementsHeader();
     ObjectElements *dstHeader;
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -8,29 +8,30 @@
 #define gc_StoreBuffer_h
 
 #ifdef JSGC_GENERATIONAL
 
 #ifndef JSGC_USE_EXACT_ROOTING
 # error "Generational GC requires exact rooting."
 #endif
 
+#include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/ReentrancyGuard.h"
 
 #include "jsalloc.h"
 
 #include "ds/LifoAlloc.h"
 #include "gc/Nursery.h"
 #include "gc/Tracer.h"
 #include "js/MemoryMetrics.h"
 
 namespace js {
 
-void
+MOZ_NORETURN void
 CrashAtUnhandlableOOM(const char *reason);
 
 namespace gc {
 
 /*
  * BufferableRef represents an abstract reference for use in the generational
  * GC's remembered set. Entries in the store buffer that cannot be represented
  * with the simple pointer-to-a-pointer scheme must derive from this class and
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -7537,17 +7537,17 @@ IonBuilder::addTypedArrayLengthAndData(M
         void *data = tarr->viewData();
         // Bug 979449 - Optimistically embed the elements and use TI to
         //              invalidate if we move them.
 #ifdef JSGC_GENERATIONAL
         bool isTenured = !tarr->runtimeFromMainThread()->gc.nursery.isInside(data);
 #else
         bool isTenured = true;
 #endif
-        if (isTenured) {
+        if (isTenured && tarr->hasSingletonType()) {
             // The 'data' pointer can change in rare circumstances
             // (ArrayBufferObject::changeContents).
             types::TypeObjectKey *tarrType = types::TypeObjectKey::get(tarr);
             if (!tarrType->unknownProperties()) {
                 tarrType->watchStateChangeForTypedArrayData(constraints());
 
                 obj->setImplicitlyUsedUnchecked();
 
@@ -8672,16 +8672,20 @@ IonBuilder::storeSlot(MDefinition *obj, 
 
 bool
 IonBuilder::jsop_getprop(PropertyName *name)
 {
     bool emitted = false;
 
     MDefinition *obj = current->pop();
 
+    // Try to optimize to a specific constant.
+    if (!getPropTryInferredConstant(&emitted, obj, name) || emitted)
+        return emitted;
+
     // Try to optimize arguments.length.
     if (!getPropTryArgumentsLength(&emitted, obj) || emitted)
         return emitted;
 
     // Try to optimize arguments.callee.
     if (!getPropTryArgumentsCallee(&emitted, obj, name) || emitted)
         return emitted;
 
@@ -8762,16 +8766,38 @@ IonBuilder::checkIsDefinitelyOptimizedAr
         return true;
     }
 
     *isOptimizedArgs = true;
     return true;
 }
 
 bool
+IonBuilder::getPropTryInferredConstant(bool *emitted, MDefinition *obj, PropertyName *name)
+{
+    JS_ASSERT(*emitted == false);
+
+    // Need a result typeset to optimize.
+    types::TemporaryTypeSet *objTypes = obj->resultTypeSet();
+    if (!objTypes)
+        return true;
+
+    Value constVal = UndefinedValue();
+    if (objTypes->propertyIsConstant(constraints(), NameToId(name), &constVal)) {
+        spew("Optimized constant property");
+        obj->setImplicitlyUsedUnchecked();
+        if (!pushConstant(constVal))
+            return false;
+        *emitted = true;
+    }
+
+    return true;
+}
+
+bool
 IonBuilder::getPropTryArgumentsLength(bool *emitted, MDefinition *obj)
 {
     JS_ASSERT(*emitted == false);
 
     bool isOptimizedArgs = false;
     if (!checkIsDefinitelyOptimizedArguments(obj, &isOptimizedArgs))
         return false;
     if (!isOptimizedArgs)
@@ -9375,23 +9401,26 @@ IonBuilder::jsop_setprop(PropertyName *n
     types::TemporaryTypeSet *objTypes = obj->resultTypeSet();
     bool barrier = PropertyWriteNeedsTypeBarrier(alloc(), constraints(), current, &obj, name, &value,
                                                  /* canModify = */ true);
 
     // Try to emit stores to known binary data blocks
     if (!setPropTryTypedObject(&emitted, obj, name, value) || emitted)
         return emitted;
 
-    // Try to emit store from definite slots.
-    if (!setPropTryDefiniteSlot(&emitted, obj, name, value, barrier, objTypes) || emitted)
-        return emitted;
-
-    // Try to emit a monomorphic/polymorphic store based on baseline caches.
-    if (!setPropTryInlineAccess(&emitted, obj, name, value, barrier, objTypes) || emitted)
-        return emitted;
+    // Do not emit optimized stores to slots that may be constant.
+    if (objTypes && !objTypes->propertyMightBeConstant(constraints(), NameToId(name))) {
+        // Try to emit store from definite slots.
+        if (!setPropTryDefiniteSlot(&emitted, obj, name, value, barrier, objTypes) || emitted)
+            return emitted;
+
+        // Try to emit a monomorphic/polymorphic store based on baseline caches.
+        if (!setPropTryInlineAccess(&emitted, obj, name, value, barrier, objTypes) || emitted)
+            return emitted;
+    }
 
     // Emit a polymorphic cache.
     return setPropTryCache(&emitted, obj, name, value, barrier, objTypes);
 }
 
 bool
 IonBuilder::setPropTryCommonSetter(bool *emitted, MDefinition *obj,
                                    PropertyName *name, MDefinition *value)
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -394,16 +394,17 @@ class IonBuilder : public MIRGenerator
                    MIRType slotType = MIRType_None);
     bool storeSlot(MDefinition *obj, Shape *shape, MDefinition *value, bool needsBarrier,
                    MIRType slotType = MIRType_None);
 
     MDefinition *tryInnerizeWindow(MDefinition *obj);
 
     // jsop_getprop() helpers.
     bool checkIsDefinitelyOptimizedArguments(MDefinition *obj, bool *isOptimizedArgs);
+    bool getPropTryInferredConstant(bool *emitted, MDefinition *obj, PropertyName *name);
     bool getPropTryArgumentsLength(bool *emitted, MDefinition *obj);
     bool getPropTryArgumentsCallee(bool *emitted, MDefinition *obj, PropertyName *name);
     bool getPropTryConstant(bool *emitted, MDefinition *obj, PropertyName *name,
                             types::TemporaryTypeSet *types);
     bool getPropTryDefiniteSlot(bool *emitted, MDefinition *obj, PropertyName *name,
                                 BarrierKind barrier, types::TemporaryTypeSet *types);
     bool getPropTryCommonGetter(bool *emitted, MDefinition *obj, PropertyName *name,
                                 types::TemporaryTypeSet *types);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1749,16 +1749,79 @@ HeapTypeSetKey::nonWritable(CompilerCons
     LifoAlloc *alloc = constraints->alloc();
 
     typedef CompilerConstraintInstance<ConstraintDataFreezePropertyState> T;
     constraints->add(alloc->new_<T>(alloc, *this,
                                     ConstraintDataFreezePropertyState(ConstraintDataFreezePropertyState::NON_WRITABLE)));
     return false;
 }
 
+namespace {
+
+class ConstraintDataConstantProperty
+{
+  public:
+    explicit ConstraintDataConstantProperty() {}
+
+    const char *kind() { return "constantProperty"; }
+
+    bool invalidateOnNewType(Type type) { return false; }
+    bool invalidateOnNewPropertyState(TypeSet *property) {
+        return property->nonConstantProperty();
+    }
+    bool invalidateOnNewObjectState(TypeObject *object) { return false; }
+
+    bool constraintHolds(JSContext *cx,
+                         const HeapTypeSetKey &property, TemporaryTypeSet *expected)
+    {
+        return !invalidateOnNewPropertyState(property.maybeTypes());
+    }
+
+    bool shouldSweep() { return false; }
+};
+
+} /* anonymous namespace */
+
+bool
+HeapTypeSetKey::constant(CompilerConstraintList *constraints, Value *valOut)
+{
+    if (nonData(constraints))
+        return false;
+
+    if (!maybeTypes())
+        return false;
+
+    if (maybeTypes()->nonConstantProperty())
+        return false;
+
+    // Only singleton object properties can be marked as constants.
+    JS_ASSERT(object()->singleton());
+
+    // Get the current value of the property.
+    Shape *shape = object()->singleton()->nativeLookupPure(id());
+    if (!shape)
+        return false;
+    Value val = object()->singleton()->nativeGetSlot(shape->slot());
+
+    // If the value is a pointer to an object in the nursery, don't optimize.
+    if (val.isGCThing() && IsInsideNursery(val.toGCThing()))
+        return false;
+
+    // If the value is a string that's not atomic, don't optimize.
+    if (val.isString() && !val.toString()->isAtom())
+        return false;
+
+    *valOut = val;
+
+    LifoAlloc *alloc = constraints->alloc();
+    typedef CompilerConstraintInstance<ConstraintDataConstantProperty> T;
+    constraints->add(alloc->new_<T>(alloc, *this, ConstraintDataConstantProperty()));
+    return true;
+}
+
 bool
 TemporaryTypeSet::filtersType(const TemporaryTypeSet *other, Type filteredType) const
 {
     if (other->unknown())
         return unknown();
 
     for (TypeFlags flag = 1; flag < TYPE_FLAG_ANYOBJECT; flag <<= 1) {
         Type type = Type::PrimitiveType(TypeFlagPrimitive(flag));
@@ -1776,16 +1839,105 @@ TemporaryTypeSet::filtersType(const Temp
             if (type != filteredType && !hasType(type))
                 return false;
         }
     }
 
     return true;
 }
 
+namespace {
+
+// A constraint that never triggers recompilation.
+class ConstraintDataInert
+{
+  public:
+    explicit ConstraintDataInert() {}
+
+    const char *kind() { return "inert"; }
+
+    bool invalidateOnNewType(Type type) { return false; }
+    bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
+    bool invalidateOnNewObjectState(TypeObject *object) { return false; }
+
+    bool constraintHolds(JSContext *cx,
+                         const HeapTypeSetKey &property, TemporaryTypeSet *expected)
+    {
+        return true;
+    }
+
+    bool shouldSweep() { return false; }
+};
+
+} /* anonymous namespace */
+
+bool
+TemporaryTypeSet::propertyMightBeConstant(CompilerConstraintList *constraints, jsid id)
+{
+    if (unknownObject())
+        return true;
+
+    for (size_t i = 0; i < getObjectCount(); i++) {
+        TypeObjectKey *type = getObject(i);
+
+        // Type sets are only marked as constants when they are lazily
+        // constructed from the properties of singleton typed objects. So watch
+        // for the cases when a property either already is or might be marked
+        // as constant in the future.
+
+        if (!type || !type->isSingleObject())
+            continue;
+
+        if (type->unknownProperties())
+            return true;
+
+        HeapTypeSetKey property = type->property(id);
+        if (!property.maybeTypes() || !property.maybeTypes()->nonConstantProperty())
+            return true;
+    }
+
+    // It is possible for a property that was not marked as constant to
+    // 'become' one, if we throw away the type property during a GC and
+    // regenerate it with the constant flag set. TypeObject::sweep only removes
+    // type properties if they have no constraints attached to them, so add
+    // inert constraints to pin these properties in place.
+
+    LifoAlloc *alloc = constraints->alloc();
+    for (size_t i = 0; i < getObjectCount(); i++) {
+        TypeObjectKey *type = getObject(i);
+
+        if (!type || !type->isSingleObject())
+            continue;
+
+        HeapTypeSetKey property = type->property(id);
+
+        typedef CompilerConstraintInstance<ConstraintDataInert> T;
+        constraints->add(alloc->new_<T>(alloc, property, ConstraintDataInert()));
+    }
+
+    return false;
+}
+
+bool
+TemporaryTypeSet::propertyIsConstant(CompilerConstraintList *constraints, jsid id, Value *valOut)
+{
+    JS_ASSERT(valOut);
+
+    JSObject *singleton = getSingleton();
+    if (!singleton)
+        return false;
+
+    TypeObjectKey *type = TypeObjectKey::get(singleton);
+    if (type->unknownProperties())
+        return false;
+
+    HeapTypeSetKey property = type->property(id);
+    return property.constant(constraints, valOut);
+}
+
 TemporaryTypeSet::DoubleConversion
 TemporaryTypeSet::convertDoubleElements(CompilerConstraintList *constraints)
 {
     if (unknownObject() || !getObjectCount())
         return AmbiguousDoubleConversion;
 
     bool alwaysConvert = true;
     bool maybeConvert = false;
@@ -2756,16 +2908,18 @@ TypeObject::setProto(JSContext *cx, Tagg
 
     setProtoUnchecked(proto);
 }
 
 static inline void
 UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, JSObject *obj, Shape *shape,
                    bool indexed)
 {
+    JS_ASSERT(obj->hasSingletonType() && !obj->hasLazyType());
+
     if (!shape->writable())
         types->setNonWritableProperty(cx);
 
     if (shape->hasGetterValue() || shape->hasSetterValue()) {
         types->setNonDataProperty(cx);
         types->TypeSet::addType(Type::UnknownType(), &cx->typeLifoAlloc());
     } else if (shape->hasDefaultGetter() && shape->hasSlot()) {
         if (!indexed && types->canSetDefinite(shape->slot()))
@@ -2777,28 +2931,38 @@ UpdatePropertyType(ExclusiveContext *cx,
          * Don't add initial undefined types for properties of global objects
          * that are not collated into the JSID_VOID property (see propertySet
          * comment).
          */
         if (indexed || !value.isUndefined() || !CanHaveEmptyPropertyTypesForOwnProperty(obj)) {
             Type type = GetValueType(value);
             types->TypeSet::addType(type, &cx->typeLifoAlloc());
         }
+
+        if (indexed || shape->hadOverwrite()) {
+            types->setNonConstantProperty(cx);
+        } else {
+            InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s - setConstant",
+                      InferSpewColor(types), types, InferSpewColorReset(),
+                      TypeObjectString(obj->type()), TypeIdString(shape->propid()));
+        }
     }
 }
 
 void
 TypeObject::updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *types)
 {
     InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
               InferSpewColor(types), types, InferSpewColorReset(),
               TypeObjectString(this), TypeIdString(id));
 
-    if (!singleton() || !singleton()->isNative())
+    if (!singleton() || !singleton()->isNative()) {
+        types->setNonConstantProperty(cx);
         return;
+    }
 
     /*
      * Fill the property in with any type the object already has in an own
      * property. We are only interested in plain native properties and
      * dense elements which don't go through a barrier when read by the VM
      * or jitcode.
      */
 
@@ -2890,17 +3054,27 @@ TypeObject::matchDefiniteProperties(Hand
 static inline void
 InlineAddTypeProperty(ExclusiveContext *cx, TypeObject *obj, jsid id, Type type)
 {
     JS_ASSERT(id == IdToTypeId(id));
 
     AutoEnterAnalysis enter(cx);
 
     HeapTypeSet *types = obj->getProperty(cx, id);
-    if (!types || types->hasType(type))
+    if (!types)
+        return;
+
+    // Clear any constant flag if it exists.
+    if (!types->nonConstantProperty()) {
+        InferSpew(ISpewOps, "constantMutated: %sT%p%s %s",
+                  InferSpewColor(types), types, InferSpewColorReset(), TypeString(type));
+        types->setNonConstantProperty(cx);
+    }
+
+    if (types->hasType(type))
         return;
 
     InferSpew(ISpewOps, "externalType: property %s %s: %s",
               TypeObjectString(obj), TypeIdString(id), TypeString(type));
     types->addType(cx, type);
 }
 
 void
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -353,17 +353,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 its configuration changed.
+     * property as having changed somehow.
      */
     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.
      */
@@ -412,27 +412,30 @@ enum MOZ_ENUM_TYPE(uint32_t) {
      * differently from a plain data property, other than making the property
      * non-writable.
      */
     TYPE_FLAG_NON_DATA_PROPERTY = 0x00008000,
 
     /* Whether the property has ever been made non-writable. */
     TYPE_FLAG_NON_WRITABLE_PROPERTY = 0x00010000,
 
+    /* Whether the property might not be constant. */
+    TYPE_FLAG_NON_CONSTANT_PROPERTY = 0x00020000,
+
     /*
      * 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       = 0xfffc0000,
+    TYPE_FLAG_DEFINITE_SHIFT      = 18
 };
 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,
 
@@ -553,16 +556,19 @@ class TypeSet
     }
 
     bool nonDataProperty() const {
         return flags & TYPE_FLAG_NON_DATA_PROPERTY;
     }
     bool nonWritableProperty() const {
         return flags & TYPE_FLAG_NON_WRITABLE_PROPERTY;
     }
+    bool nonConstantProperty() const {
+        return flags & TYPE_FLAG_NON_CONSTANT_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. */
     static TemporaryTypeSet *unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc);
@@ -671,16 +677,19 @@ class HeapTypeSet : public ConstraintTyp
 
   public:
     /* Mark this type set as representing a non-data property. */
     inline void setNonDataProperty(ExclusiveContext *cx);
     inline void setNonDataPropertyIgnoringConstraints(); // Variant for use during GC.
 
     /* Mark this type set as representing a non-writable property. */
     inline void setNonWritableProperty(ExclusiveContext *cx);
+
+    // Mark this type set as being non-constant.
+    inline void setNonConstantProperty(ExclusiveContext *cx);
 };
 
 class CompilerConstraintList;
 
 CompilerConstraintList *
 NewCompilerConstraintList(jit::TempAllocator &alloc);
 
 class TemporaryTypeSet : public TypeSet
@@ -761,16 +770,20 @@ class TemporaryTypeSet : public TypeSet
     bool maybeEmulatesUndefined();
 
     /* Get the single value which can appear in this type set, otherwise nullptr. */
     JSObject *getSingleton();
 
     /* Whether any objects in the type set needs a barrier on id. */
     bool propertyNeedsBarrier(CompilerConstraintList *constraints, jsid id);
 
+    /* Whether any objects in the type set might treat id as a constant property. */
+    bool propertyMightBeConstant(CompilerConstraintList *constraints, jsid id);
+    bool propertyIsConstant(CompilerConstraintList *constraints, jsid id, Value *valOut);
+
     /*
      * Whether this set contains all types in other, except (possibly) the
      * specified type.
      */
     bool filtersType(const TemporaryTypeSet *other, Type type) const;
 
     enum DoubleConversion {
         /* All types in the set should use eager double conversion. */
@@ -1399,16 +1412,17 @@ class HeapTypeSetKey
     void freeze(CompilerConstraintList *constraints);
     jit::MIRType knownMIRType(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);
+    bool constant(CompilerConstraintList *constraints, Value *valOut);
 };
 
 /*
  * Information about the result of the compilation of a script.  This structure
  * stored in the TypeCompartment is indexed by the RecompileInfo. This
  * indirection enables the invalidation of all constraints related to the same
  * compilation.
  */
--- a/js/src/jsinferinlines.h
+++ b/js/src/jsinferinlines.h
@@ -1103,16 +1103,26 @@ HeapTypeSet::setNonWritableProperty(Excl
 {
     if (flags & TYPE_FLAG_NON_WRITABLE_PROPERTY)
         return;
 
     flags |= TYPE_FLAG_NON_WRITABLE_PROPERTY;
     newPropertyState(cx);
 }
 
+inline void
+HeapTypeSet::setNonConstantProperty(ExclusiveContext *cx)
+{
+    if (flags & TYPE_FLAG_NON_CONSTANT_PROPERTY)
+        return;
+
+    flags |= TYPE_FLAG_NON_CONSTANT_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;
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4051,20 +4051,20 @@ CallAddPropertyHookDense(typename Execut
 template <ExecutionMode mode>
 static bool
 UpdateShapeTypeAndValue(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
                         JSObject *obj, Shape *shape, const Value &value)
 {
     jsid id = shape->propid();
     if (shape->hasSlot()) {
         if (mode == ParallelExecution) {
-            if (!obj->nativeSetSlotIfHasType(shape, value))
+            if (!obj->nativeSetSlotIfHasType(shape, value, /* overwriting = */ false))
                 return false;
         } else {
-            obj->nativeSetSlotWithType(cx->asExclusiveContext(), shape, value);
+            obj->nativeSetSlotWithType(cx->asExclusiveContext(), shape, value, /* overwriting = */ false);
         }
     }
     if (!shape->hasSlot() || !shape->hasDefaultGetter() || !shape->hasDefaultSetter()) {
         if (mode == ParallelExecution) {
             if (!IsTypePropertyIdMarkedNonData(obj, id))
                 return false;
         } else {
             MarkTypePropertyNonData(cx->asExclusiveContext(), obj, id);
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -413,19 +413,20 @@ class JSObject : public js::ObjectImpl
                                    uint32_t slotSpan);
 
     void nativeSetSlot(uint32_t slot, const js::Value &value) {
         JS_ASSERT(isNative());
         JS_ASSERT(slot < slotSpan());
         return setSlot(slot, value);
     }
 
-    inline bool nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value);
+    inline bool nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value,
+                                       bool overwriting = true);
     inline void nativeSetSlotWithType(js::ExclusiveContext *cx, js::Shape *shape,
-                                      const js::Value &value);
+                                      const js::Value &value, bool overwriting = true);
 
     inline const js::Value &getReservedSlot(uint32_t index) const {
         JS_ASSERT(index < JSSLOT_FREE(getClass()));
         return getSlot(index);
     }
 
     const js::HeapSlot &getReservedSlotRef(uint32_t index) const {
         JS_ASSERT(index < JSSLOT_FREE(getClass()));
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -660,29 +660,37 @@ JSObject::hasProperty(JSContext *cx, js:
         *foundp = false;  /* initialize to shut GCC up */
         return false;
     }
     *foundp = !!prop;
     return true;
 }
 
 inline bool
-JSObject::nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value)
+JSObject::nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value, bool overwriting)
 {
     if (!js::types::HasTypePropertyId(this, shape->propid(), value))
         return false;
     nativeSetSlot(shape->slot(), value);
+
+    if (overwriting)
+        shape->setOverwritten();
+
     return true;
 }
 
 inline void
 JSObject::nativeSetSlotWithType(js::ExclusiveContext *cx, js::Shape *shape,
-                                const js::Value &value)
+                                const js::Value &value, bool overwriting)
 {
     nativeSetSlot(shape->slot(), value);
+
+    if (overwriting)
+        shape->setOverwritten();
+
     js::types::AddTypePropertyId(cx, this, shape->propid(), value);
 }
 
 /* static */ inline bool
 JSObject::getElement(JSContext *cx, js::HandleObject obj, js::HandleObject receiver,
                      uint32_t index, js::MutableHandleValue vp)
 {
     js::ElementIdOp op = obj->getOps()->getElement;
--- a/js/src/vm/ForkJoin.h
+++ b/js/src/vm/ForkJoin.h
@@ -262,16 +262,20 @@ class ForkJoinActivation : public Activa
     // join section, but the runtime/zone might still be marked as needing
     // barriers due to being in the middle of verifying barriers. Pause
     // verification during the fork join section.
     gc::AutoStopVerifyingBarriers av_;
 
   public:
     explicit ForkJoinActivation(JSContext *cx);
     ~ForkJoinActivation();
+
+    bool isProfiling() const {
+        return false;
+    }
 };
 
 class ForkJoinContext;
 
 bool ForkJoin(JSContext *cx, CallArgs &args);
 
 ///////////////////////////////////////////////////////////////////////////
 // Bailout tracking
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -73,16 +73,17 @@ PerThreadData::PerThreadData(JSRuntime *
     runtime_(runtime),
     jitTop(nullptr),
     jitJSContext(nullptr),
     jitStackLimit(0),
 #ifdef JS_TRACE_LOGGING
     traceLogger(nullptr),
 #endif
     activation_(nullptr),
+    profilingActivation_(nullptr),
     asmJSActivationStack_(nullptr),
     autoFlushICache_(nullptr),
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     simulator_(nullptr),
     simulatorStackLimit_(0),
 #endif
     dtoaState(nullptr),
     suppressGC(0),
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -562,16 +562,22 @@ class PerThreadData : public PerThreadDa
 #endif
 
     /*
      * Points to the most recent activation running on the thread.
      * See Activation comment in vm/Stack.h.
      */
     js::Activation *activation_;
 
+    /*
+     * Points to the most recent profiling activation running on the
+     * thread.  Protected by rt->interruptLock.
+     */
+    js::Activation * volatile profilingActivation_;
+
     /* See AsmJSActivation comment. Protected by rt->interruptLock. */
     js::AsmJSActivation * volatile asmJSActivationStack_;
 
     /* Pointer to the current AutoFlushICache. */
     js::jit::AutoFlushICache *autoFlushICache_;
 
 #if defined(JS_ARM_SIMULATOR) || defined(JS_MIPS_SIMULATOR)
     js::jit::Simulator *simulator_;
@@ -584,16 +590,20 @@ class PerThreadData : public PerThreadDa
     }
     static unsigned offsetOfAsmJSActivationStackReadOnly() {
         return offsetof(PerThreadData, asmJSActivationStack_);
     }
     static unsigned offsetOfActivation() {
         return offsetof(PerThreadData, activation_);
     }
 
+    js::Activation *profilingActivation() const {
+        return profilingActivation_;
+    }
+
     js::AsmJSActivation *asmJSActivationStack() const {
         return asmJSActivationStack_;
     }
     static js::AsmJSActivation *innermostAsmJSActivation() {
         PerThreadData *ptd = TlsPerThreadData.get();
         return ptd ? ptd->asmJSActivationStack_ : nullptr;
     }
 
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -818,17 +818,23 @@ class Shape : public gc::BarrieredCell<S
      */
     enum {
         /* Property is placeholder for a non-native class. */
         NON_NATIVE      = 0x01,
 
         /* Property stored in per-object dictionary, not shared property tree. */
         IN_DICTIONARY   = 0x02,
 
-        UNUSED_BITS     = 0x3C
+        /*
+         * Slotful property was stored to more than once. This is used as a
+         * hint for type inference.
+         */
+        OVERWRITTEN     = 0x04,
+
+        UNUSED_BITS     = 0x38
     };
 
     /* Get a shape identical to this one, without parent/kids information. */
     inline Shape(const StackShape &other, uint32_t nfixed);
 
     /* Used by EmptyShape (see jsscopeinlines.h). */
     inline Shape(UnownedBaseShape *base, uint32_t nfixed);
 
@@ -877,16 +883,23 @@ class Shape : public gc::BarrieredCell<S
     }
 
     Value setterOrUndefined() const {
         return (hasSetterValue() && base()->setterObj)
                ? ObjectValue(*base()->setterObj)
                : UndefinedValue();
     }
 
+    void setOverwritten() {
+        flags |= OVERWRITTEN;
+    }
+    bool hadOverwrite() const {
+        return flags & OVERWRITTEN;
+    }
+
     void update(PropertyOp getter, StrictPropertyOp setter, uint8_t attrs);
 
     bool matches(const Shape *other) const {
         return propid_.get() == other->propid_.get() &&
                matchesParamsAfterId(other->base(), other->maybeSlot(), other->attrs, other->flags);
     }
 
     inline bool matches(const StackShape &other) const;
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -733,28 +733,60 @@ AbstractFramePtr::popWith(JSContext *cx)
     }
     asBaselineFrame()->popWith(cx);
 }
 
 Activation::Activation(ThreadSafeContext *cx, Kind kind)
   : cx_(cx),
     compartment_(cx->compartment_),
     prev_(cx->perThreadData->activation_),
+    prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
     savedFrameChain_(0),
     hideScriptedCallerCount_(0),
     kind_(kind)
 {
     cx->perThreadData->activation_ = this;
+
+    // Link the activation into the list of profiling activations if needed.
+    if (isProfiling())
+        registerProfiling();
 }
 
 Activation::~Activation()
 {
     JS_ASSERT(cx_->perThreadData->activation_ == this);
     JS_ASSERT(hideScriptedCallerCount_ == 0);
     cx_->perThreadData->activation_ = prev_;
+
+    if (isProfiling())
+        unregisterProfiling();
+}
+
+bool
+Activation::isProfiling() const
+{
+    if (isInterpreter())
+        return asInterpreter()->isProfiling();
+
+    if (isJit())
+        return asJit()->isProfiling();
+
+    if (isForkJoin())
+        return asForkJoin()->isProfiling();
+
+    JS_ASSERT(isAsmJS());
+    return asAsmJS()->isProfiling();
+}
+
+Activation *
+Activation::mostRecentProfiling()
+{
+    if (isProfiling())
+        return this;
+    return prevProfiling_;
 }
 
 InterpreterActivation::InterpreterActivation(RunState &state, JSContext *cx,
                                              InterpreterFrame *entryFrame)
   : Activation(cx, Interpreter),
     state_(state),
     entryFrame_(entryFrame),
     opMask_(0)
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -1613,16 +1613,33 @@ InterpreterFrameIterator::operator++()
     } else {
         pc_ = nullptr;
         sp_ = nullptr;
         fp_ = nullptr;
     }
     return *this;
 }
 
+void
+Activation::registerProfiling()
+{
+    JS_ASSERT(isProfiling());
+    JSRuntime::AutoLockForInterrupt lock(cx_->asJSContext()->runtime());
+    cx_->perThreadData->profilingActivation_ = this;
+}
+
+void
+Activation::unregisterProfiling()
+{
+    JS_ASSERT(isProfiling());
+    JSRuntime::AutoLockForInterrupt lock(cx_->asJSContext()->runtime());
+    JS_ASSERT(cx_->perThreadData->profilingActivation_ == this);
+    cx_->perThreadData->profilingActivation_ = prevProfiling_;
+}
+
 ActivationIterator::ActivationIterator(JSRuntime *rt)
   : jitTop_(rt->mainThread.jitTop),
     activation_(rt->mainThread.activation_)
 {
     settle();
 }
 
 ActivationIterator::ActivationIterator(PerThreadData *perThreadData)
@@ -1648,55 +1665,104 @@ ActivationIterator::settle()
 {
     // Stop at the next active activation. No need to update jitTop_, since
     // we don't iterate over an active jit activation.
     while (!done() && activation_->isJit() && !activation_->asJit()->isActive())
         activation_ = activation_->prev();
 }
 
 JS::ProfilingFrameIterator::ProfilingFrameIterator(JSRuntime *rt, const RegisterState &state)
-  : activation_(rt->mainThread.asmJSActivationStack())
+  : activation_(rt->mainThread.profilingActivation())
 {
     if (!activation_)
         return;
 
+    JS_ASSERT(activation_->isProfiling());
+
     static_assert(sizeof(AsmJSProfilingFrameIterator) <= StorageSpace, "Need to increase storage");
-    new (storage_.addr()) AsmJSProfilingFrameIterator(*activation_, state);
+
+    iteratorConstruct(state);
     settle();
 }
 
 JS::ProfilingFrameIterator::~ProfilingFrameIterator()
 {
-    if (!done())
-        iter().~AsmJSProfilingFrameIterator();
+    if (!done()) {
+        JS_ASSERT(activation_->isProfiling());
+        iteratorDestroy();
+    }
 }
 
 void
 JS::ProfilingFrameIterator::operator++()
 {
     JS_ASSERT(!done());
-    ++iter();
+
+    JS_ASSERT(activation_->isAsmJS());
+    ++asmJSIter();
     settle();
 }
 
 void
 JS::ProfilingFrameIterator::settle()
 {
-    while (iter().done()) {
-        iter().~AsmJSProfilingFrameIterator();
-        activation_ = activation_->prevAsmJS();
+    while (iteratorDone()) {
+        iteratorDestroy();
+        activation_ = activation_->prevProfiling();
         if (!activation_)
             return;
-        new (storage_.addr()) AsmJSProfilingFrameIterator(*activation_);
+        iteratorConstruct();
     }
 }
 
+void
+JS::ProfilingFrameIterator::iteratorConstruct(const RegisterState &state)
+{
+    JS_ASSERT(!done());
+
+    JS_ASSERT(activation_->isAsmJS());
+    new (storage_.addr()) AsmJSProfilingFrameIterator(*activation_->asAsmJS(), state);
+}
+
+void
+JS::ProfilingFrameIterator::iteratorConstruct()
+{
+    JS_ASSERT(!done());
+
+    JS_ASSERT(activation_->isAsmJS());
+    new (storage_.addr()) AsmJSProfilingFrameIterator(*activation_->asAsmJS());
+}
+
+void
+JS::ProfilingFrameIterator::iteratorDestroy()
+{
+    JS_ASSERT(!done());
+
+    JS_ASSERT(activation_->isAsmJS());
+    asmJSIter().~AsmJSProfilingFrameIterator();
+}
+
+bool
+JS::ProfilingFrameIterator::iteratorDone()
+{
+    JS_ASSERT(!done());
+
+    JS_ASSERT(activation_->isAsmJS());
+    return asmJSIter().done();
+}
+
 void *
 JS::ProfilingFrameIterator::stackAddress() const
 {
-    return iter().stackAddress();
+    JS_ASSERT(!done());
+
+    JS_ASSERT(activation_->isAsmJS());
+    return asmJSIter().stackAddress();
 }
 
 const char *
 JS::ProfilingFrameIterator::label() const
 {
-    return iter().label();
+    JS_ASSERT(!done());
+
+    JS_ASSERT(activation_->isAsmJS());
+    return asmJSIter().label();
 }
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1098,16 +1098,17 @@ namespace jit {
 };
 
 class Activation
 {
   protected:
     ThreadSafeContext *cx_;
     JSCompartment *compartment_;
     Activation *prev_;
+    Activation *prevProfiling_;
 
     // Counter incremented by JS_SaveFrameChain on the top-most activation and
     // decremented by JS_RestoreFrameChain. If > 0, ScriptFrameIter should stop
     // iterating when it reaches this activation (if GO_THROUGH_SAVED is not
     // set).
     size_t savedFrameChain_;
 
     // Counter incremented by JS::HideScriptedCaller and decremented by
@@ -1128,30 +1129,36 @@ class Activation
         return cx_;
     }
     JSCompartment *compartment() const {
         return compartment_;
     }
     Activation *prev() const {
         return prev_;
     }
+    Activation *prevProfiling() const { return prevProfiling_; }
+    inline Activation *mostRecentProfiling();
 
     bool isInterpreter() const {
         return kind_ == Interpreter;
     }
     bool isJit() const {
         return kind_ == Jit;
     }
     bool isForkJoin() const {
         return kind_ == ForkJoin;
     }
     bool isAsmJS() const {
         return kind_ == AsmJS;
     }
 
+    inline bool isProfiling() const;
+    void registerProfiling();
+    void unregisterProfiling();
+
     InterpreterActivation *asInterpreter() const {
         JS_ASSERT(isInterpreter());
         return (InterpreterActivation *)this;
     }
     jit::JitActivation *asJit() const {
         JS_ASSERT(isJit());
         return (jit::JitActivation *)this;
     }
@@ -1233,16 +1240,20 @@ class InterpreterActivation : public Act
     }
     InterpreterFrame *entryFrame() const {
         return entryFrame_;
     }
     size_t opMask() const {
         return opMask_;
     }
 
+    bool isProfiling() const {
+        return false;
+    }
+
     // If this js::Interpret frame is running |script|, enable interrupts.
     void enableInterruptsIfRunning(JSScript *script) {
         if (regs_.fp()->script() == script)
             enableInterruptsUnconditionally();
     }
     void enableInterruptsUnconditionally() {
         opMask_ = EnableInterruptsPseudoOpcode;
     }
@@ -1318,16 +1329,20 @@ class JitActivation : public Activation
     explicit JitActivation(ForkJoinContext *cx);
     ~JitActivation();
 
     bool isActive() const {
         return active_;
     }
     void setActive(JSContext *cx, bool active = true);
 
+    bool isProfiling() const {
+        return false;
+    }
+
     uint8_t *prevJitTop() const {
         return prevJitTop_;
     }
     bool firstFrameIsConstructing() const {
         return firstFrameIsConstructing_;
     }
     static size_t offsetOfPrevJitTop() {
         return offsetof(JitActivation, prevJitTop_);
@@ -1476,16 +1491,20 @@ class AsmJSActivation : public Activatio
   public:
     AsmJSActivation(JSContext *cx, AsmJSModule &module);
     ~AsmJSActivation();
 
     inline JSContext *cx();
     AsmJSModule &module() const { return module_; }
     AsmJSActivation *prevAsmJS() const { return prevAsmJS_; }
 
+    bool isProfiling() const {
+        return true;
+    }
+
     // Returns a pointer to the base of the innermost stack frame of asm.js code
     // in this activation.
     uint8_t *fp() const { return fp_; }
 
     // Returns the reason why asm.js code called out of asm.js code.
     AsmJSExit::Reason exitReason() const { return exitReason_; }
 
     // Read by JIT code:
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/blur-calc-negative-ref.html
@@ -0,0 +1,27 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Blur an HTML Element Using a Negative Calc Function Value</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-blur">
+  <link rel="match" href="blur-calc-negative-ref.html">
+  <meta name="assert"
+        content="Given a calc() value that evaluates to a negative result, the
+                 CSS blur filter function should not blur an HTML element.">
+  <style type="text/css">
+    #target {
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/blur-calc-negative.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Blur an HTML Element Using a Negative Calc Function Value</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-blur">
+  <link rel="match" href="blur-calc-negative-ref.html">
+  <meta name="assert"
+        content="Given a calc() value that evaluates to a negative result, the
+                 CSS blur filter function should not blur an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: blur(calc(-10px));
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/blur-calc-ref.html
@@ -0,0 +1,23 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Blur an HTML Element Using a Calc Function Value</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <style type="text/css">
+    #target {
+      filter: blur(10px);
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a blurred green square.</p>
+  <div id="target"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/svg/filters/css-filters/blur-calc.html
@@ -0,0 +1,28 @@
+<!--
+     Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE html>
+<html>
+<head>
+  <title>CSS Filters: Blur an HTML Element Using a Calc Function Value</title>
+  <link rel="author" title="Max Vujovic" href="mailto:mvujovic@adobe.com">
+  <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-blur">
+  <link rel="match" href="blur-calc-ref.html">
+  <meta name="assert"
+        content="Given a calc() value that evaluates to a positive result, the
+                 CSS blur filter function should blur an HTML element.">
+  <style type="text/css">
+    #target {
+      filter: blur(calc(2 * 5px));
+      background-color: #0f0;
+      width: 100px;
+      height: 100px;
+    }
+  </style>
+</head>
+<body>
+  <p>You should see a blurred green square.</p>
+  <div id="target"></div>
+</body>
+</html>
--- a/layout/reftests/svg/filters/css-filters/reftest.list
+++ b/layout/reftests/svg/filters/css-filters/reftest.list
@@ -1,15 +1,17 @@
 # These tests verify that CSS filters behave properly.
 # e.g. filter: blur(3px)
 
 default-preferences pref(layout.css.filters.enabled,true)
 
 == blur.html blur-ref.html
 == blur.svg blur-ref.svg
+== blur-calc.html blur-calc-ref.html
+== blur-calc-negative.html blur-calc-negative-ref.html
 == blur-zero-radius.html blur-zero-radius-ref.html
 == blur-zoomed-page.html blur-zoomed-page-ref.html
 == brightness.html brightness-ref.html
 == brightness-darken.html brightness-darken-ref.html
 == brightness-extreme.html brightness-extreme-ref.html
 == brightness-one.html brightness-one-ref.html
 == brightness-percent.html brightness-percent-ref.html
 == brightness-zero.html brightness-zero-ref.html
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -8703,17 +8703,19 @@ nsRuleNode::SetStyleFilterToCSSValue(nsS
       false,
       aCanStoreInRuleTree);
     aStyleFilter->SetDropShadow(shadowArray);
     return true;
   }
 
   int32_t mask = SETCOORD_PERCENT | SETCOORD_FACTOR;
   if (type == NS_STYLE_FILTER_BLUR) {
-    mask = SETCOORD_LENGTH | SETCOORD_STORE_CALC;
+    mask = SETCOORD_LENGTH |
+           SETCOORD_CALC_LENGTH_ONLY |
+           SETCOORD_CALC_CLAMP_NONNEGATIVE;
   } else if (type == NS_STYLE_FILTER_HUE_ROTATE) {
     mask = SETCOORD_ANGLE;
   }
 
   NS_ABORT_IF_FALSE(filterFunction->Count() == 2,
                     "all filter functions should have "
                     "exactly one argument");
 
--- a/mobile/android/base/mozglue/GeckoLoader.java.in
+++ b/mobile/android/base/mozglue/GeckoLoader.java.in
@@ -244,30 +244,30 @@ public final class GeckoLoader {
             if (sSQLiteLibsLoaded) {
                 return;
             }
             sSQLiteLibsLoaded = true;
         }
 
         loadMozGlue(context);
         loadLibsSetup(context);
-        loadSQLiteLibsNative(apkName, false);
+        loadSQLiteLibsNative(apkName);
     }
 
     public static void loadNSSLibs(final Context context, final String apkName) {
         synchronized (sLibLoadingLock) {
             if (sNSSLibsLoaded) {
                 return;
             }
             sNSSLibsLoaded = true;
         }
 
         loadMozGlue(context);
         loadLibsSetup(context);
-        loadNSSLibsNative(apkName, false);
+        loadNSSLibsNative(apkName);
     }
 
     /**
      * Copy a library out of our APK.
      *
      * @param context a Context.
      * @param lib the name of the library; e.g., "mozglue".
      * @param outDir the output directory for the .so. No trailing slash.
@@ -532,11 +532,11 @@ public final class GeckoLoader {
     }
 
     // These methods are implemented in mozglue/android/nsGeckoUtils.cpp
     private static native void putenv(String map);
 
     // These methods are implemented in mozglue/android/APKOpen.cpp
     public static native void nativeRun(String args);
     private static native void loadGeckoLibsNative(String apkName);
-    private static native void loadSQLiteLibsNative(String apkName, boolean shouldExtract);
-    private static native void loadNSSLibsNative(String apkName, boolean shouldExtract);
+    private static native void loadSQLiteLibsNative(String apkName);
+    private static native void loadNSSLibsNative(String apkName);
 }
--- a/mobile/android/components/build/nsShellService.h
+++ b/mobile/android/components/build/nsShellService.h
@@ -10,21 +10,20 @@
 
 class nsShellService MOZ_FINAL : public nsIShellService
 {
 public:
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISHELLSERVICE
 
-  nsShellService() {};
+  nsShellService() {}
 
 private:
-  ~nsShellService() {};
-
+  ~nsShellService() {}
 };
 
 #define nsShellService_CID                          \
 {0xae9ebe1c, 0x61e9, 0x45fa, {0x8f, 0x34, 0xc1, 0x07, 0x80, 0x3a, 0x5b, 0x44}}
 
 #define nsShellService_ContractID "@mozilla.org/browser/shell-service;1"
 
 #endif
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -312,21 +312,17 @@ Java_org_mozilla_gecko_mozglue_GeckoLoad
   int res = loadGeckoLibs(str);
   if (res != SUCCESS) {
     JNI_Throw(jenv, "java/lang/Exception", "Error loading gecko libraries");
   }
   jenv->ReleaseStringUTFChars(jApkName, str);
 }
 
 extern "C" NS_EXPORT void JNICALL
-Java_org_mozilla_gecko_mozglue_GeckoLoader_loadSQLiteLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName, jboolean jShouldExtract) {
-  if (jShouldExtract) {
-    putenv("MOZ_LINKER_EXTRACT=1");
-  }
-
+Java_org_mozilla_gecko_mozglue_GeckoLoader_loadSQLiteLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName) {
   const char* str;
   // XXX: java doesn't give us true UTF8, we should figure out something
   // better to do here
   str = jenv->GetStringUTFChars(jApkName, nullptr);
   if (str == nullptr)
     return;
 
   __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load sqlite start\n");
@@ -334,21 +330,17 @@ Java_org_mozilla_gecko_mozglue_GeckoLoad
   if (rv != SUCCESS) {
       JNI_Throw(jenv, "java/lang/Exception", "Error loading sqlite libraries");
   }
   __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load sqlite done\n");
   jenv->ReleaseStringUTFChars(jApkName, str);
 }
 
 extern "C" NS_EXPORT void JNICALL
-Java_org_mozilla_gecko_mozglue_GeckoLoader_loadNSSLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName, jboolean jShouldExtract) {
-  if (jShouldExtract) {
-    putenv("MOZ_LINKER_EXTRACT=1");
-  }
-
+Java_org_mozilla_gecko_mozglue_GeckoLoader_loadNSSLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName) {
   const char* str;
   // XXX: java doesn't give us true UTF8, we should figure out something
   // better to do here
   str = jenv->GetStringUTFChars(jApkName, nullptr);
   if (str == nullptr)
     return;
 
   __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Load nss start\n");
--- a/netwerk/base/src/Tickler.cpp
+++ b/netwerk/base/src/Tickler.cpp
@@ -220,19 +220,19 @@ class TicklerTimer MOZ_FINAL : public ns
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
   TicklerTimer(Tickler *aTickler)
   {
     mTickler = do_GetWeakReference(aTickler);
   }
 
-  ~TicklerTimer() {};
+private:
+  ~TicklerTimer() {}
 
-private:
   nsWeakPtr mTickler;
 };
 
 void Tickler::StartTickler()
 {
   mLock.AssertCurrentThreadOwns();
   MOZ_ASSERT(mThread == NS_GetCurrentThread());
   MOZ_ASSERT(!mActive);
--- a/netwerk/protocol/device/AndroidCaptureProvider.h
+++ b/netwerk/protocol/device/AndroidCaptureProvider.h
@@ -12,30 +12,34 @@
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "mozilla/net/CameraStreamImpl.h"
 #include "nsIEventTarget.h"
 #include "nsDeque.h"
 #include "mozilla/ReentrantMonitor.h"
 
 class AndroidCaptureProvider MOZ_FINAL : public nsDeviceCaptureProvider {
+  private:
+    ~AndroidCaptureProvider();
+
   public:
     AndroidCaptureProvider();
-    ~AndroidCaptureProvider();
 
     NS_DECL_THREADSAFE_ISUPPORTS
 
     nsresult Init(nsACString& aContentType, nsCaptureParams* aParams, nsIInputStream** aStream);
     static AndroidCaptureProvider* sInstance;
 };
 
 class AndroidCameraInputStream MOZ_FINAL : public nsIAsyncInputStream, mozilla::net::CameraStreamImpl::FrameCallback {
+  private:
+    ~AndroidCameraInputStream();
+
   public:
     AndroidCameraInputStream();
-    ~AndroidCameraInputStream();
 
     NS_IMETHODIMP Init(nsACString& aContentType, nsCaptureParams* aParams);
 
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIINPUTSTREAM
     NS_DECL_NSIASYNCINPUTSTREAM
 
     void ReceiveFrame(char* frame, uint32_t length);
--- a/netwerk/system/android/nsAndroidNetworkLinkService.h
+++ b/netwerk/system/android/nsAndroidNetworkLinkService.h
@@ -11,12 +11,14 @@
 
 class nsAndroidNetworkLinkService: public nsINetworkLinkService
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSINETWORKLINKSERVICE
 
   nsAndroidNetworkLinkService();
+
+private:
   virtual ~nsAndroidNetworkLinkService();
 };
 
 #endif /* NSANDROIDNETWORKLINKSERVICE_H_ */
--- a/profile/dirserviceprovider/ProfileUnlockerWin.cpp
+++ b/profile/dirserviceprovider/ProfileUnlockerWin.cpp
@@ -166,33 +166,43 @@ ProfileUnlockerWin::Unlock(uint32_t aSev
     info.SetLength(numEntriesNeeded);
     numEntries = numEntriesNeeded;
     error = mRmGetList(session.handle(), &numEntriesNeeded, &numEntries,
                        &info[0], &reason);
   }
   if (error != ERROR_SUCCESS) {
     return NS_ERROR_FAILURE;
   }
+  if (numEntries == 0) {
+    // Nobody else is locking the file; the other process must have terminated
+    return NS_OK;
+  }
 
-  nsresult rv;
+  nsresult rv = NS_ERROR_FAILURE;
   for (UINT i = 0; i < numEntries; ++i) {
     rv = TryToTerminate(info[i].Process);
     if (NS_SUCCEEDED(rv)) {
       return NS_OK;
     }
   }
 
   // If nothing could be unlocked then we return the error code of the last
   // failure that was returned.
   return rv;
 }
 
 nsresult
 ProfileUnlockerWin::TryToTerminate(RM_UNIQUE_PROCESS& aProcess)
 {
+  // Subtle: If the target process terminated before this call to OpenProcess,
+  // this call will still succeed. This is because the restart manager session
+  // internally retains a handle to the target process. The rules for Windows
+  // PIDs state that the PID of a terminated process remains valid as long as
+  // at least one handle to that process remains open, so when we reach this
+  // point the PID is still valid and the process will open successfully.
   DWORD accessRights = PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE;
   nsAutoHandle otherProcess(::OpenProcess(accessRights, FALSE,
                                           aProcess.dwProcessId));
   if (!otherProcess) {
     return NS_ERROR_FAILURE;
   }
 
   FILETIME creationTime, exitTime, kernelTime, userTime;
@@ -202,17 +212,29 @@ ProfileUnlockerWin::TryToTerminate(RM_UN
   }
   if (::CompareFileTime(&aProcess.ProcessStartTime, &creationTime)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   WCHAR imageName[MAX_PATH];
   DWORD imageNameLen = MAX_PATH;
   if (!mQueryFullProcessImageName(otherProcess, 0, imageName, &imageNameLen)) {
-    return NS_ERROR_FAILURE;
+    // The error codes for this function are not very descriptive. There are
+    // actually two failure cases here: Either the call failed because the
+    // process is no longer running, or it failed for some other reason. We
+    // need to know which case that is.
+    DWORD otherProcessExitCode;
+    if (!::GetExitCodeProcess(otherProcess, &otherProcessExitCode) ||
+        otherProcessExitCode == STILL_ACTIVE) {
+      // The other process is still running.
+      return NS_ERROR_FAILURE;
+    }
+    // The other process must have terminated. We should return NS_OK so that
+    // this process may proceed with startup.
+    return NS_OK;
   }
   nsCOMPtr<nsIFile> otherProcessImageName;
   if (NS_FAILED(NS_NewLocalFile(nsDependentString(imageName, imageNameLen),
                                 false, getter_AddRefs(otherProcessImageName)))) {
     return NS_ERROR_FAILURE;
   }
   nsAutoString otherProcessLeafName;
   if (NS_FAILED(otherProcessImageName->GetLeafName(otherProcessLeafName))) {
@@ -236,17 +258,21 @@ ProfileUnlockerWin::TryToTerminate(RM_UN
 
   // Make sure the image leaf names match
   if (_wcsicmp(otherProcessLeafName.get(), thisProcessLeafName.get())) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // We know that another process holds the lock and that it shares the same
   // image name as our process. Let's kill it.
-  if (!::TerminateProcess(otherProcess, 1)) {
+  // Subtle: TerminateProcess returning ERROR_ACCESS_DENIED is actually an
+  // indicator that the target process managed to shut down on its own. In that
+  // case we should return NS_OK since we may proceed with startup.
+  if (!::TerminateProcess(otherProcess, 1) &&
+      ::GetLastError() != ERROR_ACCESS_DENIED) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 } // namespace mozilla
 
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -1907,19 +1907,22 @@ class Mochitest(MochitestUtilsMixin):
         stackFixerFunction = lambda line: stackFixerModule.fixSymbols(line, self.symbolsPath)
 
       elif mozinfo.isLinux and self.perl:
         # Run logsource through fix-linux-stack.pl (uses addr2line)
         # This method is preferred for developer machines, so we don't have to run "make buildsymbols".
         stackFixerCommand = [self.perl, os.path.join(self.utilityPath, "fix-linux-stack.pl")]
         stackFixerProcess = subprocess.Popen(stackFixerCommand, stdin=subprocess.PIPE,
                                              stdout=subprocess.PIPE)
-        def fixFunc(line):
-          stackFixerProcess.stdin.write(line + '\n')
-          return stackFixerProcess.stdout.readline().rstrip()
+        def fixFunc(lines):
+          out = []
+          for line in lines.split('\n'):
+            stackFixerProcess.stdin.write(line + '\n')
+            out.append(stackFixerProcess.stdout.readline().rstrip())
+          return '\n'.join(out)
 
         stackFixerFunction = fixFunc
 
       return (stackFixerFunction, stackFixerProcess)
 
     def finish(self, didTimeout):
       if self.stackFixerProcess:
         self.stackFixerProcess.communicate()
--- a/toolkit/components/aboutmemory/tests/test_aboutmemory5.xul
+++ b/toolkit/components/aboutmemory/tests/test_aboutmemory5.xul
@@ -121,17 +121,20 @@
             let m1 = actual.match("anonymous") &&
                      actual.match("shared-libraries");
             ok(m1, "system-wide reporter")
             good = good && !!m1;
           }
 
           // Note: Match "vsize" but not "vsize-max-contiguous".
           let vsizes = actual.match(/vsize[^-]/g);
-          let endOfBrowsers  = actual.match(/End of Browser/g);
+          let endOfBrowsers = actual.match(/End of Browser/g);
+          if (endOfBrowsers == null) {
+            endOfBrowsers = actual.match(/End of Web Content/g);
+          }
           let m2 = (vsizes.length == 4 && endOfBrowsers.length == 3);
           ok(m2, "three child processes present in loaded data");
           good = good && !!m2;
 
           if (!good) {
             dump("*******ACTUAL*******\n");
             dump(actual);
             dump("********************\n");
--- a/toolkit/components/aboutmemory/tests/test_memoryReporters2.xul
+++ b/toolkit/components/aboutmemory/tests/test_memoryReporters2.xul
@@ -80,18 +80,18 @@
       let processes = Object.keys(residents);
       ok(processes.length == numRemotes + 1, "correct resident count");
 
       let numEmptyProcesses = 0, numNonEmptyProcesses = 0;
       for (let i = 0; i < processes.length; i++) {
         if (processes[i] == "") {
           numEmptyProcesses++;
         } else {
-          ok(processes[i].startsWith("Browser ("),
-             "correct non-empty process name prefix");
+          ok(processes[i].startsWith("Browser (") || processes[i].startsWith("Web Content ("),
+             "correct non-empty process name prefix: " + processes[i]);
           numNonEmptyProcesses++;
         }
       }
       ok(numEmptyProcesses == 1, "correct empty process name count");
       ok(numNonEmptyProcesses == numRemotes,
                                  "correct non-empty process name count");
 
       SimpleTest.finish();
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -4051,120 +4051,64 @@
     "extended_statistics_ok": true,
     "description": "Time to flush and close the localStorage database (ms)"
   },
   "LOCALDOMSTORAGE_PRELOAD_PENDING_ON_FIRST_ACCESS": {
     "expires_in_version": "never",
     "kind": "boolean",
     "description": "True when we had to wait for a pending preload on first access to localStorage data, false otherwise"
   },
-  "LOCALDOMSTORAGE_GETALLKEYS_MS": {
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "high": "3000",
-    "n_buckets": 10,
-    "extended_statistics_ok": true,
-    "description": "Time to return a list of all keys in domain's LocalStorage (ms)"
-  },
   "LOCALDOMSTORAGE_GETALLKEYS_BLOCKING_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 10,
     "extended_statistics_ok": true,
     "description": "Time to block before we return a list of all keys in domain's LocalStorage (ms)"
   },
-  "LOCALDOMSTORAGE_GETKEY_MS": {
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "high": "3000",
-    "n_buckets": 10,
-    "extended_statistics_ok": true,
-    "description": "Time to return a key name in domain's LocalStorage (ms)"
-  },
   "LOCALDOMSTORAGE_GETKEY_BLOCKING_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 10,
     "extended_statistics_ok": true,
     "description": "Time to block before we return a key name in domain's LocalStorage (ms)"
   },
-  "LOCALDOMSTORAGE_GETLENGTH_MS": {
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "high": "3000",
-    "n_buckets": 10,
-    "extended_statistics_ok": true,
-    "description": "Time to return number of keys in domain's LocalStorage (ms)"
-  },
   "LOCALDOMSTORAGE_GETLENGTH_BLOCKING_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 10,
     "extended_statistics_ok": true,
     "description": "Time to block before we return number of keys in domain's LocalStorage (ms)"
   },
-  "LOCALDOMSTORAGE_GETVALUE_MS": {
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "high": "3000",
-    "n_buckets": 10,
-    "extended_statistics_ok": true,
-    "description": "Time to return a value for a key in LocalStorage (ms)"
-  },
   "LOCALDOMSTORAGE_GETVALUE_BLOCKING_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 10,
     "extended_statistics_ok": true,
     "description": "Time to block before we return a value for a key in LocalStorage (ms)"
   },
-  "LOCALDOMSTORAGE_SETVALUE_MS": {
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "high": "3000",
-    "n_buckets": 10,
-    "extended_statistics_ok": true,
-    "description": "Time to set a single key's value in LocalStorage (ms)"
-  },
   "LOCALDOMSTORAGE_SETVALUE_BLOCKING_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 10,
     "extended_statistics_ok": true,
     "description": "Time to block before we set a single key's value in LocalStorage (ms)"
   },
-  "LOCALDOMSTORAGE_REMOVEKEY_MS": {
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "high": "3000",
-    "n_buckets": 10,
-    "extended_statistics_ok": true,
-    "description": "Time to remove a single key from LocalStorage (ms)"
-  },
   "LOCALDOMSTORAGE_REMOVEKEY_BLOCKING_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 10,
     "extended_statistics_ok": true,
     "description": "Time to block before we remove a single key from LocalStorage (ms)"
   },
-  "LOCALDOMSTORAGE_CLEAR_MS": {
-    "expires_in_version": "never",
-    "kind": "exponential",
-    "high": "3000",
-    "n_buckets": 10,
-    "extended_statistics_ok": true,
-    "description": "Time to clear LocalStorage for all domains (ms)"
-  },
   "LOCALDOMSTORAGE_CLEAR_BLOCKING_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "3000",
     "n_buckets": 10,
     "extended_statistics_ok": true,
     "description": "Time to block before we clear LocalStorage for all domains (ms)"
   },
--- a/toolkit/system/androidproxy/nsAndroidSystemProxySettings.cpp
+++ b/toolkit/system/androidproxy/nsAndroidSystemProxySettings.cpp
@@ -21,17 +21,17 @@ class nsAndroidSystemProxySettings : pub
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSISYSTEMPROXYSETTINGS
 
     nsAndroidSystemProxySettings() {};
     nsresult Init();
 
 private:
-    ~nsAndroidSystemProxySettings() {};
+    virtual ~nsAndroidSystemProxySettings() {}
 };
 
 NS_IMPL_ISUPPORTS(nsAndroidSystemProxySettings, nsISystemProxySettings)
 
 NS_IMETHODIMP
 nsAndroidSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly)
 {
   *aMainThreadOnly = true;
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1682,17 +1682,51 @@ static nsresult LaunchChild(nsINativeApp
 #endif // MOZ_WIDGET_ANDROID
 
   return NS_ERROR_LAUNCHED_CHILD_PROCESS;
 }
 
 static const char kProfileProperties[] =
   "chrome://mozapps/locale/profile/profileSelection.properties";
 
-static nsresult
+namespace {
+
+/**
+ * This class, instead of a raw nsresult, should be the return type of any
+ * function called by SelectProfile that initializes XPCOM.
+ */
+class ReturnAbortOnError
+{
+public:
+  MOZ_IMPLICIT ReturnAbortOnError(nsresult aRv)
+  {
+    mRv = ConvertRv(aRv);
+  }
+
+  operator nsresult()
+  {
+    return mRv;
+  }
+
+private:
+  inline nsresult
+  ConvertRv(nsresult aRv)
+  {
+    if (NS_SUCCEEDED(aRv) || aRv == NS_ERROR_LAUNCHED_CHILD_PROCESS) {
+      return aRv;
+    }
+    return NS_ERROR_ABORT;
+  }
+
+  nsresult mRv;
+};
+
+} // anonymous namespace
+
+static ReturnAbortOnError
 ProfileLockedDialog(nsIFile* aProfileDir, nsIFile* aProfileLocalDir,
                     nsIProfileUnlocker* aUnlocker,
                     nsINativeAppSupport* aNative, nsIProfileLock* *aResult)
 {
   nsresult rv;
 
   ScopedXPCOMStartup xpcom;
   rv = xpcom.Initialize();
@@ -1852,17 +1886,17 @@ ProfileLockedDialog(nsIToolkitProfile* a
 
   return ProfileLockedDialog(profileDir, profileLocalDir, aUnlocker, aNative,
                              aResult);
 }
 
 static const char kProfileManagerURL[] =
   "chrome://mozapps/content/profile/profileSelection.xul";
 
-static nsresult
+static ReturnAbortOnError
 ShowProfileManager(nsIToolkitProfileService* aProfileSvc,
                    nsINativeAppSupport* aNative)
 {
   if (!CanShowProfileManager()) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
   nsresult rv;
--- a/uriloader/exthandler/android/nsAndroidHandlerApp.h
+++ b/uriloader/exthandler/android/nsAndroidHandlerApp.h
@@ -10,24 +10,24 @@
 #include "nsIExternalSharingAppService.h"
 
 class nsAndroidHandlerApp : public nsISharingHandlerApp {
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIHANDLERAPP
     NS_DECL_NSISHARINGHANDLERAPP
 
-    public:
     nsAndroidHandlerApp(const nsAString& aName, const nsAString& aDescription,
                         const nsAString& aPackageName, 
                         const nsAString& aClassName, 
                         const nsACString& aMimeType, const nsAString& aAction);
+
+private:
     virtual ~nsAndroidHandlerApp();
 
-private:
     nsString mName;
     nsString mDescription;
     nsString mPackageName;
     nsString mClassName;
     nsCString mMimeType;
     nsString mAction;
 };
 #endif
--- a/uriloader/exthandler/android/nsMIMEInfoAndroid.h
+++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.h
@@ -25,32 +25,36 @@ public:
                     nsIHandlerInfo **info);
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMIMEINFO
   NS_DECL_NSIHANDLERINFO
 
   nsMIMEInfoAndroid(const nsACString& aMIMEType);
 
-protected:
+private:
+  ~nsMIMEInfoAndroid() {}
+
   virtual nsresult LaunchDefaultWithFile(nsIFile* aFile);
   virtual nsresult LoadUriInternal(nsIURI *aURI);
   nsCOMPtr<nsIMutableArray> mHandlerApps;
   nsCString mType;
   nsTArray<nsCString> mExtensions;
   bool mAlwaysAsk;
   nsHandlerInfoAction mPrefAction;
   nsString mDescription;
   nsCOMPtr<nsIHandlerApp> mPrefApp;
-  
+
+public:
   class SystemChooser MOZ_FINAL : public nsIHandlerApp {
   public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSIHANDLERAPP
-    SystemChooser(nsMIMEInfoAndroid* aOuter): mOuter(aOuter) {};
-    
+    SystemChooser(nsMIMEInfoAndroid* aOuter): mOuter(aOuter) {}
+
   private:
+    ~SystemChooser() {}
+
     nsMIMEInfoAndroid* mOuter;
-    
   };
 };
 
 #endif /* nsMIMEInfoAndroid_h */
--- a/widget/android/APZCCallbackHandler.cpp
+++ b/widget/android/APZCCallbackHandler.cpp
@@ -117,39 +117,42 @@ APZCCallbackHandler::AcknowledgeScrollUp
     APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
 }
 
 void
 APZCCallbackHandler::HandleDoubleTap(const CSSPoint& aPoint,
                                      int32_t aModifiers,
                                      const mozilla::layers::ScrollableLayerGuid& aGuid)
 {
-    nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", aPoint.x, aPoint.y);
+    CSSIntPoint point = RoundedToInt(aPoint);
+    nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", point.x, point.y);
     nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeBroadcastEvent(
             NS_LITERAL_CSTRING("Gesture:DoubleTap"), data));
 }
 
 void
 APZCCallbackHandler::HandleSingleTap(const CSSPoint& aPoint,
                                      int32_t aModifiers,
                                      const mozilla::layers::ScrollableLayerGuid& aGuid)
 {
     // FIXME Send the modifier data to Gecko for use in mouse events.
-    nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", aPoint.x, aPoint.y);
+    CSSIntPoint point = RoundedToInt(aPoint);
+    nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", point.x, point.y);
     nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeBroadcastEvent(
             NS_LITERAL_CSTRING("Gesture:SingleTap"), data));
 }
 
 void
 APZCCallbackHandler::HandleLongTap(const CSSPoint& aPoint,
                                    int32_t aModifiers,
                                    const mozilla::layers::ScrollableLayerGuid& aGuid)
 {
     // TODO send content response back to APZC
-    nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", aPoint.x, aPoint.y);
+    CSSIntPoint point = RoundedToInt(aPoint);
+    nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", point.x, point.y);
     nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeBroadcastEvent(
             NS_LITERAL_CSTRING("Gesture:LongPress"), data));
 }
 
 void
 APZCCallbackHandler::HandleLongTapUp(const CSSPoint& aPoint,
                                      int32_t aModifiers,
                                      const mozilla::layers::ScrollableLayerGuid& aGuid)
--- a/widget/android/GfxInfo.cpp
+++ b/widget/android/GfxInfo.cpp
@@ -110,16 +110,20 @@ NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, Gfx
 #endif
 
 GfxInfo::GfxInfo()
   : mInitialized(false)
   , mGLStrings(new GLStrings)
 {
 }
 
+GfxInfo::~GfxInfo()
+{
+}
+
 /* GetD2DEnabled and GetDwriteEnabled shouldn't be called until after gfxPlatform initialization
  * has occurred because they depend on it for information. (See bug 591561) */
 nsresult
 GfxInfo::GetD2DEnabled(bool *aEnabled)
 {
   return NS_ERROR_FAILURE;
 }
 
--- a/widget/android/GfxInfo.h
+++ b/widget/android/GfxInfo.h
@@ -19,16 +19,19 @@ namespace mozilla {
 namespace gl {
 class GLContext;
 }
 
 namespace widget {
 
 class GfxInfo : public GfxInfoBase
 {
+private:
+  ~GfxInfo();
+
 public:
   GfxInfo();
 
   // We only declare the subset of nsIGfxInfo that we actually implement. The
   // rest is brought forward from GfxInfoBase.
   NS_IMETHOD GetD2DEnabled(bool *aD2DEnabled);
   NS_IMETHOD GetDWriteEnabled(bool *aDWriteEnabled);
   NS_IMETHOD GetDWriteVersion(nsAString & aDwriteVersion);
--- a/widget/android/nsAndroidProtocolHandler.cpp
+++ b/widget/android/nsAndroidProtocolHandler.cpp
@@ -20,21 +20,25 @@ using namespace mozilla::widget::android
 class AndroidInputStream : public nsIInputStream
 {
 public:
     AndroidInputStream(jobject connection) {
         JNIEnv *env = GetJNIForThread();
         mBridgeInputStream = env->NewGlobalRef(GeckoAppShell::CreateInputStream(connection));
         mBridgeChannel = env->NewGlobalRef(AndroidBridge::ChannelCreate(mBridgeInputStream));
     }
+
+private:
     virtual ~AndroidInputStream() {
         JNIEnv *env = GetJNIForThread();
         env->DeleteGlobalRef(mBridgeInputStream);
         env->DeleteGlobalRef(mBridgeChannel);
     }
+
+public:
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIINPUTSTREAM
 
     private:
     jobject mBridgeInputStream;
     jobject mBridgeChannel;
 };
 
--- a/widget/android/nsAndroidProtocolHandler.h
+++ b/widget/android/nsAndroidProtocolHandler.h
@@ -24,12 +24,14 @@ class nsAndroidProtocolHandler MOZ_FINAL
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
 
     // nsIProtocolHandler methods:
     NS_DECL_NSIPROTOCOLHANDLER
 
     // nsAndroidProtocolHandler methods:
     nsAndroidProtocolHandler() {}
+
+private:
     ~nsAndroidProtocolHandler() {}
 };
 
 #endif /* nsAndroidProtocolHandler_h___ */
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -106,17 +106,20 @@ public:
 private:
     nsCOMPtr<nsIAndroidBrowserApp> mBrowserApp;
     nsTArray<nsIntPoint> mPoints;
     int mTabId;
     nsRefPtr<RefCountedJavaObject> mBuffer;
 };
 
 class WakeLockListener MOZ_FINAL : public nsIDOMMozWakeLockListener {
- public:
+private:
+  ~WakeLockListener() {}
+
+public:
   NS_DECL_ISUPPORTS;
 
   nsresult Callback(const nsAString& topic, const nsAString& state) {
     mozilla::widget::android::GeckoAppShell::NotifyWakeLockChanged(topic, state);
     return NS_OK;
   }
 };
 
--- a/widget/android/nsClipboard.h
+++ b/widget/android/nsClipboard.h
@@ -5,16 +5,19 @@
 
 #ifndef NS_CLIPBOARD_H
 #define NS_CLIPBOARD_H
 
 #include "nsIClipboard.h"
 
 class nsClipboard MOZ_FINAL : public nsIClipboard
 {
+private:
+  ~nsClipboard() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICLIPBOARD
 
   nsClipboard();
 };
 
 #endif
--- a/widget/android/nsDeviceContextAndroid.h
+++ b/widget/android/nsDeviceContextAndroid.h
@@ -2,16 +2,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "nsIDeviceContextSpec.h"
 #include "nsCOMPtr.h"
 
 class nsDeviceContextSpecAndroid MOZ_FINAL : public nsIDeviceContextSpec
 {
+private:
+    ~nsDeviceContextSpecAndroid() {}
+
 public:
     NS_DECL_ISUPPORTS
 
     NS_IMETHOD GetSurfaceForPrinter(gfxASurface** surface);
 
     NS_IMETHOD Init(nsIWidget* aWidget,
                     nsIPrintSettings* aPS,
                     bool aIsPrintPreview);
--- a/widget/android/nsScreenManagerAndroid.h
+++ b/widget/android/nsScreenManagerAndroid.h
@@ -25,19 +25,21 @@ public:
     NS_IMETHOD GetColorDepth(int32_t* aColorDepth);
 
 protected:
     virtual void ApplyMinimumBrightness(uint32_t aBrightness) MOZ_OVERRIDE;
 };
 
 class nsScreenManagerAndroid MOZ_FINAL : public nsIScreenManager
 {
+private:
+    ~nsScreenManagerAndroid();
+
 public:
     nsScreenManagerAndroid();
-    ~nsScreenManagerAndroid();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCREENMANAGER
 
 protected:
     nsCOMPtr<nsIScreen> mOneScreen;
 };
 
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -82,16 +82,20 @@ static gfxIntSize gAndroidScreenBounds;
 
 class ContentCreationNotifier;
 static StaticRefPtr<ContentCreationNotifier> gContentCreationNotifier;
 
 // A helper class to send updates when content processes
 // are created. Currently an update for the screen size is sent.
 class ContentCreationNotifier MOZ_FINAL : public nsIObserver
 {
+private:
+    ~ContentCreationNotifier() {}
+
+public:
     NS_DECL_ISUPPORTS
 
     NS_IMETHOD Observe(nsISupports* aSubject,
                        const char* aTopic,
                        const char16_t* aData)
     {
         if (!strcmp(aTopic, "ipc:content-created")) {
             nsCOMPtr<nsIObserver> cpo = do_QueryInterface(aSubject);
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -27,21 +27,23 @@ namespace mozilla {
         class LayerManager;
         class APZCTreeManager;
     }
 }
 
 class nsWindow :
     public nsBaseWidget
 {
+private:
+    virtual ~nsWindow();
+
 public:
     using nsBaseWidget::GetLayerManager;
 
     nsWindow();
-    virtual ~nsWindow();
 
     NS_DECL_ISUPPORTS_INHERITED
 
     static void OnGlobalAndroidEvent(mozilla::AndroidGeckoEvent *ae);
     static gfxIntSize GetAndroidScreenBounds();
     static nsWindow* TopWindow();
 
     nsWindow* FindWindowForPoint(const nsIntPoint& pt);
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -982,27 +982,46 @@ nsNativeThemeCocoa::DrawMenuIcon(CGConte
   CGFloat paddingY = std::max(CGFloat(0.0), aRect.size.height - aIconSize.height);
   CGFloat paddingStartX = std::min(paddingX, kMenuIconIndent);
   CGFloat paddingEndX = std::max(CGFloat(0.0), paddingX - kMenuIconIndent);
   CGRect drawRect = CGRectMake(
     aRect.origin.x + (IsFrameRTL(aFrame) ? paddingEndX : paddingStartX),
     aRect.origin.y + ceil(paddingY / 2),
     aIconSize.width, aIconSize.height);
 
-  NSString* state = IsDisabled(aFrame, inState) ? @"disabled" :
-    (CheckBooleanAttr(aFrame, nsGkAtoms::menuactive) ? @"pressed" : @"normal");
+  BOOL isDisabled = IsDisabled(aFrame, inState);
+  BOOL isActive = CheckBooleanAttr(aFrame, nsGkAtoms::menuactive);
+
+  // On 10.6 and at least on 10.7.0, Apple doesn’t seem to have implemented all
+  // keys and values used on 10.7.5 and later. We can however draw menu icons
+  // on earlier OS versions by using different keys/values.
+  BOOL otherKeysAndValues = !nsCocoaFeatures::OnLionOrLater() ||
+                            (nsCocoaFeatures::OSXVersionMajor() == 10 &&
+                             nsCocoaFeatures::OSXVersionMinor() == 7 &&
+                             nsCocoaFeatures::OSXVersionBugFix() < 5);
+
+  // 2 states combined with 2 different backgroundTypeKeys on earlier versions.
+  NSString* state = isDisabled ? @"disabled" :
+    (isActive && !otherKeysAndValues) ? @"pressed" : @"normal";
+  NSString* backgroundTypeKey = !otherKeysAndValues ? @"kCUIBackgroundTypeMenu" :
+    !isDisabled && isActive ? @"backgroundTypeDark" : @"backgroundTypeLight";
+
+  NSMutableArray* keys = [NSMutableArray arrayWithObjects:@"backgroundTypeKey",
+    @"imageNameKey", @"state", @"widget", @"is.flipped", nil];
+  NSMutableArray* values = [NSMutableArray arrayWithObjects: backgroundTypeKey,
+    aImageName, state, @"image", [NSNumber numberWithBool:YES], nil];
+
+  if (otherKeysAndValues) { // Earlier versions used one more key-value pair.
+    [keys insertObject:@"imageIsGrayscaleKey" atIndex:1];
+    [values insertObject:[NSNumber numberWithBool:YES] atIndex:1];
+  }
 
   CUIDraw([NSWindow coreUIRenderer], drawRect, cgContext,
-          (CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
-            @"kCUIBackgroundTypeMenu", @"backgroundTypeKey",
-            aImageName, @"imageNameKey",
-            state, @"state",
-            @"image", @"widget",
-            [NSNumber numberWithBool:YES], @"is.flipped",
-            nil], nil);
+          (CFDictionaryRef)[NSDictionary dictionaryWithObjects:values
+                            forKeys:keys], nil);
 
 #if DRAW_IN_FRAME_DEBUG
   CGContextSetRGBFillColor(cgContext, 0.0, 0.0, 0.5, 0.25);
   CGContextFillRect(cgContext, drawRect);
 #endif
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }