merge from central to inbound r=merge a=merge on a CLOSED TREE
authorAttila Craciun <acraciun@mozilla.com>
Thu, 02 Nov 2017 11:57:12 +0200
changeset 440568 a86ac3dafdf5b4fc5e874dce2be0c1ab87a2ec72
parent 440567 b9c75d921ae0ee6336d727f0ba29117c4e3d3e0f (current diff)
parent 440556 b5a3b8ef6902998507fc881b6d628b055457fe31 (diff)
child 440569 725d13675a52e997870c98bee564f9e04cdc62c6
push id8114
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 16:33:21 +0000
treeherdermozilla-beta@73e0d89a540f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone58.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 from central to inbound r=merge a=merge on a CLOSED TREE
browser/components/customizableui/test/browser_932928_show_notice_when_palette_empty.js
browser/themes/linux/menuPanel-exit.png
browser/themes/linux/menuPanel-help.png
browser/themes/osx/menu-forward.png
browser/themes/osx/menuPanel-customize.png
browser/themes/osx/menuPanel-exit.png
browser/themes/osx/menuPanel-exit@2x.png
browser/themes/osx/menuPanel-help-yosemite.png
browser/themes/osx/menuPanel-help-yosemite@2x.png
browser/themes/osx/menuPanel-help.png
browser/themes/osx/menuPanel-help@2x.png
browser/themes/windows/menuPanel-customize.png
browser/themes/windows/menuPanel-exit.png
browser/themes/windows/menuPanel-help.png
--- a/Makefile.in
+++ b/Makefile.in
@@ -56,18 +56,17 @@ endif
 endif
 
 ifdef JS_STANDALONE
 .PHONY: CLOBBER
 CLOBBER:
 else
 CLOBBER: $(topsrcdir)/CLOBBER
 	@echo 'STOP!  The CLOBBER file has changed.'
-	@echo 'Please run the build through a sanctioned build wrapper, such as'
-	@echo '"mach build" or client.mk.'
+	@echo 'Please run the build through "mach build".'
 	@exit 1
 endif
 
 $(topsrcdir)/configure: $(topsrcdir)/configure.in $(topsrcdir)/old-configure.in
 $(topsrcdir)/js/src/configure: $(topsrcdir)/js/src/configure.in $(topsrcdir)/js/src/old-configure.in
 $(topsrcdir)/configure $(topsrcdir)/js/src/configure:
 	@echo 'STOP!  $? has changed, and your configure is out of date.'
 	@echo 'Please rerun autoconf and re-configure your build directory.'
--- a/browser/extensions/onboarding/OnboardingTelemetry.jsm
+++ b/browser/extensions/onboarding/OnboardingTelemetry.jsm
@@ -49,58 +49,59 @@ const EVENT_WHITELIST = {
   "overlay-nav-click": {topic: "firefox-onboarding-event", category: "overlay-interactions"},
   // track when the overlay is shown
   "overlay-session-begin": {topic: "internal"},
   // track when the overlay is closed
   "overlay-session-end": {topic: "firefox-onboarding-session", category: "overlay-interactions"},
   // track when click the overlay "skip tour" button
   "overlay-skip-tour": {topic: "firefox-onboarding-event", category: "overlay-interactions"},
 };
-const ONBOARDING_STATE_DEFAULT = "default";
 const ONBOARDING_ID = "onboarding";
 
 let OnboardingTelemetry = {
   sessionProbe: null,
   eventProbe: null,
   state: {
     sessions: {},
   },
 
   init(startupData) {
     this.sessionProbe = new PingCentre({topic: "firefox-onboarding-session"});
     this.eventProbe = new PingCentre({topic: "firefox-onboarding-event"});
     this.state.addon_version = startupData.version;
   },
 
   // register per tab session data
-  registerNewTelemetrySession(session_key, page) {
+  registerNewTelemetrySession(data) {
+    let { page, session_key, tour_type } = data;
     if (this.state.sessions[session_key]) {
       return;
     }
     // session_key and page url are must have
-    if (!session_key || !page) {
-      throw new Error("session_key and page url are required for onboarding-register-session");
+    if (!session_key || !page || !tour_type) {
+      throw new Error("session_key, page url, and tour_type are required for onboarding-register-session");
     }
     let session_id = gUUIDGenerator.generateUUID().toString();
     this.state.sessions[session_key] = {
+      page,
       session_id,
-      page,
+      tour_type,
     };
   },
 
   process(data) {
-    let { event, page, session_key } = data;
+    let { event, session_key } = data;
 
     let topic = EVENT_WHITELIST[event] && EVENT_WHITELIST[event].topic;
     if (!topic) {
       throw new Error(`ping-centre doesn't know ${event}, only knows ${Object.keys(EVENT_WHITELIST)}`);
     }
 
     if (event === "onboarding-register-session") {
-      this.registerNewTelemetrySession(session_key, page);
+      this.registerNewTelemetrySession(data);
     }
 
     if (!this.state.sessions[session_key]) {
       throw new Error(`should pass valid session_key`);
     }
 
     if (topic === "internal") {
       switch (event) {
@@ -130,18 +131,22 @@ let OnboardingTelemetry = {
       session_key,
     } = data;
     let {
       notification_session_begin,
       onboarding_session_begin,
       overlay_session_begin,
       page,
       session_id,
+      tour_type,
     } = this.state.sessions[session_key];
     let category = EVENT_WHITELIST[event].category;
+    // the field is used to identify how user open the overlay (through default logo or watermark),
+    // the number of open from notification can be retrieved via `notification-cta-click` event
+    let tour_source = Services.prefs.getStringPref("browser.onboarding.state", "default");
     let session_begin;
     switch (topic) {
       case "firefox-onboarding-session":
         switch (event) {
           case "onboarding-session-end":
             if (!onboarding_session_begin) {
               throw new Error(`should fire onboarding-session-begin event before ${event}`);
             }
@@ -160,42 +165,43 @@ let OnboardingTelemetry = {
             if (!notification_session_begin) {
               throw new Error(`should fire notification-session-begin event before ${event}`);
             }
             event = "notification-session";
             session_begin = notification_session_begin;
             break;
         }
 
-        // the field is used to identify how user open the overlay (through default logo or watermark),
-        // the number of open from notification can be retrieved via `notification-cta-click` event
-        const tour_source = Services.prefs.getStringPref("browser.onboarding.state",
-          ONBOARDING_STATE_DEFAULT);
-        const session_end = Date.now();
+        let session_end = Date.now();
         this.sessionProbe && this.sessionProbe.sendPing({
           addon_version,
           category,
           event,
           page,
           session_begin,
           session_end,
           session_id,
           tour_id,
           tour_source,
+          tour_type,
         }, {filter: ONBOARDING_ID});
         break;
       case "firefox-onboarding-event":
         let impression = (event === "notification-close-button-click" ||
           event === "notification-cta-click") ?
           Services.prefs.getIntPref("browser.onboarding.notification.prompt-count", 0) : -1;
+        let timestamp = Date.now();
         this.eventProbe && this.eventProbe.sendPing({
           addon_version,
           category,
           event,
           impression,
           page,
           session_id,
+          timestamp,
           tour_id,
+          tour_source,
+          tour_type,
         }, {filter: ONBOARDING_ID});
         break;
     }
   }
 };
--- a/browser/extensions/onboarding/content/onboarding.js
+++ b/browser/extensions/onboarding/content/onboarding.js
@@ -402,16 +402,17 @@ class Onboarding {
     this._window.addEventListener("unload", () => this.destroy());
 
     this.uiInitialized = false;
     this._resizeTimerId =
       this._window.requestIdleCallback(() => this._resizeUI());
     registerNewTelemetrySession({
       page: this._window.location.href,
       session_key: this._session_key,
+      tour_type: this._tourType,
     });
     telemetry({
       event: "onboarding-session-begin",
       session_key: this._session_key,
     });
   }
 
   _resizeUI() {
--- a/browser/extensions/onboarding/data_events.md
+++ b/browser/extensions/onboarding/data_events.md
@@ -19,40 +19,44 @@ For reference, Onyx is a Mozilla owned s
   "category": ["overlay-interactions"|"notification-interactions"],
   "client_id": "374dc4d8-0cb2-4ac5-a3cf-c5a9bc3c602e",
   "locale": "en-US",
   "event": ["onboarding_session" | "overlay_session" | "notification_session"],
   "page": ["about:newtab" | "about:home"],
   "session_begin": 1505440017018,
   "session_end": 1505440021992,
   "session_id": "{12dasd-213asda-213dkakj}",
+  "tour_id": ["onboarding-tour-private-browsing" | "onboarding-tour-addons"|...], // tour ids defined in 'onboardingTourset'
   "tour_source": ["default" | "watermark"],
-  "tour_id": ["onboarding-tour-private-browsing" | "onboarding-tour-addons"|...], // tour ids defined in 'onboardingTourset'
+  "tour_type" ["new" | "update"],
 
   // These fields are generated on the server
   "date": "2016-03-07",
   "ip": "10.192.171.13",
   "ua": "python-requests/2.9.1",
   "receive_at": 1457396660000
 }
 ```
 
 # Example Onboarding `event` Log
 
 ```js
 {
   "addon_version": "1.0.0",
   "category": ["overlay-interactions"|"notification-interactions"],
   "client_id": "374dc4d8-0cb2-4ac5-a3cf-c5a9bc3c602e",
+  "timestamp": 1505440017019,
   "event": ["notification-cta-click" | "overlay-cta-click" | "overlay-nav-click" | "overlay-skip-tour"],
   "impression": [0-8],
   "locale": "en-US",
   "page": ["about:newtab" | "about:home"],
   "session_id": "{12dasd-213asda-213dkakj}",
   "tour_id": ["onboarding-tour-private-browsing" | "onboarding-tour-addons"|...], // tour ids defined in 'onboardingTourset'
+  "tour_source": ["default" | "watermark"],
+  "tour_type" ["new" | "update"],
 
   // These fields are generated on the server
   "ip": "10.192.171.13",
   "ua": "python-requests/2.9.1",
   "receive_at": 1457396660000,
   "date": "2016-03-07",
 }
 ```
@@ -66,18 +70,20 @@ For reference, Onyx is a Mozilla owned s
 | `event` | [Required] The type of event. allowed event strings are defined in the below section | :one:
 | `impression` | [Optional] An integer to record how many times the current notification tour is shown to the user. Each Notification tour can show not more than 8 times. We put `-1` when this field is not relevant to this event | :one:
 | `ip` | [Auto populated by Onyx] The IP address of the client. Onyx does use (with the permission) the IP address to infer user's geo information so that it could prepare the corresponding tiles for the country she lives in. However, Ping-centre will NOT store IP address in the database, where only authorized Mozilla employees can access the telemetry data, and all the raw logs are being strictly managed by the Ops team and will expire according to the Mozilla's data retention policy.| :two:
 | `locale` | The browser chrome's language (eg. en-US). | :two:
 | `page` | [Required] One of ["about:newtab", "about:home"]| :one:
 | `session_begin` | Timestamp in (integer) milliseconds when onboarding/overlay/notification becoming visible. | :one:
 | `session_end` | Timestamp in (integer) milliseconds when onboarding/overlay/notification losing focus. | :one:
 | `session_id` | [Required] The unique identifier generated by `gUUIDGenerator` service to identify the specific user session when onboarding is inited/when overlay is opened/when notification is shown. | :one:
-| `tour_source` | Either ("default", "watermark") indicates the overlay is opened while in the default or the watermark state. Open from the notification bar is counted via 'notification-cta-click event'. | :two:
-| `tour_id` | id of the current tour. The number of open from notification can be retrieved via 'notification-cta-click event'. We put ` ` when this field is not relevant to this event | :two:
+| `timestamp` | Timestamp in (integer) milliseconds when the event triggered | :one:
+| `tour_id` | id of the current tour. The number of open from notification can be retrieved via 'notification-cta-click event'. We put ` ` when this field is not relevant to this event | :one:
+| `tour_source` | [Required] One of ["default", "watermark"] indicates the overlay is opened while in the default or the watermark state. Open from the notification bar is counted via 'notification-cta-click event'. | :one:
+| `tour_type` | [Required] One of ["new", "update"] indicates the user is a `new` user or the `update` user upgrade from the older version | :one:
 | `ua` | [Auto populated by Onyx] The user agent string. | :two:
 | `ver` | [Auto populated by Onyx] The version of the Onyx API the ping was sent to. | :one:
 
 **Where:**
 
 :one: Firefox data
 :two: HTTP protocol data
 
--- a/build/docs/pgo.rst
+++ b/build/docs/pgo.rst
@@ -7,26 +7,22 @@ Profile Guided Optimization
 :abbr:`PGO (Profile Guided Optimization)` is the process of adding
 probes to a compiled binary, running said binary, then using the
 run-time information to *recompile* the binary to (hopefully) make it
 faster.
 
 How PGO Builds Work
 ===================
 
-The supported interface for invoking a PGO build is to evaluate the
-*build* target of client.mk with *MOZ_PGO* defined. e.g.::
-
-    $ make -f client.mk MOZ_PGO=1
+The supported interface for invoking a PGO build is to invoke the build system
+with ``MOZ_PGO`` defined. e.g.::
 
-This is equivalent to::
+    $ MOZ_PGO=1 ./mach build
 
-    $ make -f client.mk profiledbuild
-
-Which is roughly equivalent to:
+This is roughly equivalent to::
 
 #. Perform a build with *MOZ_PROFILE_GENERATE=1* and *MOZ_PGO_INSTRUMENTED=1*
 #. Package with *MOZ_PGO_INSTRUMENTED=1*
 #. Performing a run of the instrumented binaries
 #. $ make maybe_clobber_profiledbuild
 #. Perform a build with *MOZ_PROFILE_USE=1*
 
 Differences between toolchains
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -52,16 +52,28 @@ yasm = check_prog('YASM', ['yasm'], allo
 def yasm_version(yasm):
     version = check_cmd_output(
         yasm, '--version',
         onerror=lambda: die('Failed to get yasm version.')
     ).splitlines()[0].split()[1]
     return Version(version)
 
 
+@depends(yasm_version)
+def yasm_major_version(yasm_version):
+    return str(yasm_version.major)
+
+
+@depends(yasm_version)
+def yasm_minor_version(yasm_version):
+    return str(yasm_version.minor)
+
+
+set_config('YASM_MAJOR_VERSION', yasm_major_version)
+set_config('YASM_MINOR_VERSION', yasm_minor_version)
 # Until we move all the yasm consumers out of old-configure.
 # bug 1257904
 add_old_configure_assignment('_YASM_MAJOR_VERSION',
                              yasm_version.major)
 add_old_configure_assignment('_YASM_MINOR_VERSION',
                              yasm_version.minor)
 
 
--- a/client.mk
+++ b/client.mk
@@ -1,30 +1,18 @@
 # -*- makefile -*-
 # vim:set ts=8 sw=8 sts=8 noet:
 # 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/.
 
-# Build a mozilla application.
+# Defines main targets for driving the Firefox build system.
 #
-# To build a tree,
-#    1. hg clone ssh://hg.mozilla.org/mozilla-central mozilla
-#    2. cd mozilla
-#    3. create your .mozconfig file with
-#       ac_add_options --enable-application=browser
-#    4. gmake -f client.mk
-#
-# Other targets (gmake -f client.mk [targets...]),
-#    build
-#    clean (realclean is now the same as clean)
-#    distclean
-#
-# See http://developer.mozilla.org/en/docs/Build_Documentation for 
-# more information.
+# This make file should not be invoked directly. Instead, use
+# `mach` (likely `mach build`) for invoking the build system.
 #
 # Options:
 #   MOZ_OBJDIR           - Destination object directory
 #   MOZ_MAKE_FLAGS       - Flags to pass to $(MAKE)
 #   MOZ_PREFLIGHT_ALL    - Makefiles to run before building.
 #   MOZ_POSTFLIGHT_ALL   - Makefiles to run after building.
 #
 #######################################################################
@@ -58,21 +46,17 @@ else
 TOPSRCDIR := $(CWD)
 endif
 endif
 
 SH := /bin/sh
 PERL ?= perl
 PYTHON ?= $(shell which python2.7 > /dev/null 2>&1 && echo python2.7 || echo python)
 
-CONFIG_GUESS_SCRIPT := $(wildcard $(TOPSRCDIR)/build/autoconf/config.guess)
-ifdef CONFIG_GUESS_SCRIPT
-  CONFIG_GUESS := $(shell $(CONFIG_GUESS_SCRIPT))
-endif
-
+CONFIG_GUESS := $(shell $(TOPSRCDIR)/build/autoconf/config.guess)
 
 ####################################
 # Sanity checks
 
 # Windows checks.
 ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
 
 # check for CRLF line endings
@@ -184,19 +168,16 @@ endif
 
 # Windows equivalents
 build_all: build
 clobber clobber_all: clean
 
 # helper target for mobile
 build_and_deploy: build package install
 
-# Do everything from scratch
-everything: clean build
-
 ####################################
 # Profile-Guided Optimization
 #  This is up here so that this is usable in multi-pass builds, where you
 # might not have a runnable application until all the build passes have run.
 profiledbuild::
 	$(call BUILDSTATUS,TIERS pgo_profile_generate pgo_package pgo_profile pgo_clobber pgo_profile_use)
 	$(call BUILDSTATUS,TIER_START pgo_profile_generate)
 	$(MAKE) -f $(TOPSRCDIR)/client.mk realbuild MOZ_PROFILE_GENERATE=1 MOZ_PGO_INSTRUMENTED=1 CREATE_MOZCONFIG_JSON=
@@ -226,17 +207,16 @@ realbuild preflight_all::
 	done
 endif
 
 ####################################
 # Configure
 
 MAKEFILE      = $(wildcard $(OBJDIR)/Makefile)
 CONFIG_STATUS = $(wildcard $(OBJDIR)/config.status)
-CONFIG_CACHE  = $(wildcard $(OBJDIR)/config.cache)
 
 EXTRA_CONFIG_DEPS := \
   $(TOPSRCDIR)/aclocal.m4 \
   $(TOPSRCDIR)/old-configure.in \
   $(wildcard $(TOPSRCDIR)/build/autoconf/*.m4) \
   $(TOPSRCDIR)/js/src/aclocal.m4 \
   $(TOPSRCDIR)/js/src/old-configure.in \
   $(NULL)
@@ -362,23 +342,19 @@ endif
 echo-variable-%:
 	@echo $($*)
 
 # This makefile doesn't support parallel execution. It does pass
 # MOZ_MAKE_FLAGS to sub-make processes, so they will correctly execute
 # in parallel.
 .NOTPARALLEL:
 
-.PHONY: checkout \
-    real_checkout \
+.PHONY: \
     realbuild \
     build \
     profiledbuild \
-    pull_all \
     build_all \
     clobber \
     clobber_all \
-    pull_and_build_all \
-    everything \
     configure \
     preflight_all \
     postflight_all \
     $(OBJDIR_TARGETS)
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -538,19 +538,16 @@ ifdef GNU_CC
 endif
 endif
 endif
 
 endif # NO_PROFILE_GUIDED_OPTIMIZE
 
 ##############################################
 
-checkout:
-	$(MAKE) -C $(topsrcdir) -f client.mk checkout
-
 clean clobber realclean clobber_all::
 	-$(RM) $(ALL_TRASH)
 	-$(RM) -r $(ALL_TRASH_DIRS)
 
 clean clobber realclean clobber_all distclean::
 	$(foreach dir,$(DIRS),-$(call SUBMAKE,$@,$(dir)))
 
 distclean::
@@ -1543,17 +1540,17 @@ endif
 # hundreds of built-in suffix rules for stuff we don't need.
 #
 .SUFFIXES:
 
 #
 # Fake targets.  Always run these rules, even if a file/directory with that
 # name already exists.
 #
-.PHONY: all alltags boot checkout chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) FORCE
+.PHONY: all alltags boot chrome realchrome clean clobber clobber_all export install libs makefiles realclean run_apprunner tools $(DIRS) FORCE
 
 # Used as a dependency to force targets to rebuild
 FORCE:
 
 # Delete target if error occurs when building target
 .DELETE_ON_ERROR:
 
 tags: TAGS
--- a/configure.py
+++ b/configure.py
@@ -92,17 +92,17 @@ def config_status(config):
 
     partial_config = PartialConfigEnvironment(config['TOPOBJDIR'])
     partial_config.write_vars(sanitized_config)
 
     # Write out a depfile so Make knows to re-run configure when relevant Python
     # changes.
     mk = Makefile()
     rule = mk.create_rule()
-    rule.add_targets(["$(OBJDIR)/config.status"])
+    rule.add_targets(["%s/config.status" % config['TOPOBJDIR']])
     rule.add_dependencies(itertools.chain(config['ALL_CONFIGURE_PATHS'],
                                           iter_modules_in_path(config['TOPOBJDIR'],
                                                                config['TOPSRCDIR'])))
     with open('configure.d', 'w') as fh:
         mk.dump(fh)
 
     # Other things than us are going to run this file, so we need to give it
     # executable permissions.
--- a/devtools/client/memory/components/SnapshotListItem.js
+++ b/devtools/client/memory/components/SnapshotListItem.js
@@ -84,19 +84,20 @@ module.exports = createClass({
       details = dom.span({ className: "snapshot-state" }, statusText);
     }
 
     let saveLink = !snapshot.path ? void 0 : dom.a({
       onClick: () => onSave(snapshot),
       className: "save",
     }, L10N.getStr("snapshot.io.save"));
 
-    let deleteButton = !snapshot.path ? void 0 : dom.button({
+    let deleteButton = !snapshot.path ? void 0 : dom.div({
       onClick: () => onDelete(snapshot),
-      className: "devtools-button delete",
+      className: "delete",
+      "aria-role": "button",
       title: L10N.getStr("snapshot.io.delete")
     });
 
     return (
       dom.li({ className, onClick },
         dom.span({
           className: `snapshot-title ${wantThrobber ? " devtools-throbber" : ""}`
         },
--- a/devtools/client/themes/memory.css
+++ b/devtools/client/themes/memory.css
@@ -209,23 +209,25 @@ html, body, #app, #memory-tool {
 
 .snapshot-list-item .delete {
   cursor: pointer;
   position: relative;
   min-height: 1em;
   min-width: 1.3em;
 }
 
-.snapshot-list-item.selected .delete::before {
-  filter: invert(1);
-}
-
 .snapshot-list-item .delete::before {
+  display: block;
+  width: 16px;
+  height: 16px;
+  content: "";
   background-image: url("chrome://devtools/skin/images/close.svg");
-  background-position: 0.2em 0;
+  background-repeat: no-repeat;
+  -moz-context-properties: fill;
+  fill: currentColor;
 }
 
 .snapshot-list-item > .snapshot-title {
   margin-bottom: 14px;
 }
 
 .snapshot-list-item > .snapshot-title > input[type=checkbox] {
   margin: 0;
--- a/dom/base/nsRange.cpp
+++ b/dom/base/nsRange.cpp
@@ -3207,31 +3207,36 @@ static void ExtractRectFromOffset(nsIFra
     aR->SetWidth(aR->XMost() - point.x);
     aR->x = point.x;
   }
 }
 
 static nsTextFrame*
 GetTextFrameForContent(nsIContent* aContent, bool aFlushLayout)
 {
-  nsIPresShell* presShell = aContent->OwnerDoc()->GetShell();
-  if (presShell) {
-    presShell->FrameConstructor()->EnsureFrameForTextNode(
-        static_cast<nsGenericDOMDataNode*>(aContent));
-
-    if (aFlushLayout) {
-      aContent->OwnerDoc()->FlushPendingNotifications(FlushType::Layout);
-    }
-
-    nsIFrame* frame = aContent->GetPrimaryFrame();
-    if (frame && frame->IsTextFrame()) {
-      return static_cast<nsTextFrame*>(frame);
-    }
+  nsIDocument* doc = aContent->OwnerDoc();
+  nsIPresShell* presShell = doc->GetShell();
+  if (!presShell) {
+    return nullptr;
   }
-  return nullptr;
+
+  const bool frameWillBeUnsuppressed =
+    presShell->FrameConstructor()->EnsureFrameForTextNodeIsCreatedAfterFlush(
+      static_cast<nsGenericDOMDataNode*>(aContent));
+  if (aFlushLayout) {
+    doc->FlushPendingNotifications(FlushType::Layout);
+  } else if (frameWillBeUnsuppressed) {
+    doc->FlushPendingNotifications(FlushType::Frames);
+  }
+
+  nsIFrame* frame = aContent->GetPrimaryFrame();
+  if (!frame || !frame->IsTextFrame()) {
+    return nullptr;
+  }
+  return static_cast<nsTextFrame*>(frame);
 }
 
 static nsresult GetPartialTextRect(nsLayoutUtils::RectCallback* aCallback,
                                    Sequence<nsString>* aTextList,
                                    nsIContent* aContent, int32_t aStartOffset,
                                    int32_t aEndOffset, bool aClampToEdge,
                                    bool aFlushLayout)
 {
--- a/dom/svg/SVGGeometryElement.cpp
+++ b/dom/svg/SVGGeometryElement.cpp
@@ -101,21 +101,20 @@ SVGGeometryElement::GetOrBuildPath(const
   // We only cache the path if it matches the backend used for screen painting:
   bool cacheable  = aDrawTarget.GetBackendType() ==
                     gfxPlatform::GetPlatform()->GetDefaultContentBackend();
 
   // Checking for and returning mCachedPath before checking the pref means
   // that the pref is only live on page reload (or app restart for SVG in
   // chrome). The benefit is that we avoid causing a CPU memory cache miss by
   // looking at the global variable that the pref's stored in.
-  if (cacheable && mCachedPath) {
-    if (aDrawTarget.GetBackendType() == mCachedPath->GetBackendType()) {
-      RefPtr<Path> path(mCachedPath);
-      return path.forget();
-    }
+  if (cacheable && mCachedPath && mCachedPath->GetFillRule() == aFillRule &&
+      aDrawTarget.GetBackendType() == mCachedPath->GetBackendType()) {
+    RefPtr<Path> path(mCachedPath);
+    return path.forget();
   }
   RefPtr<PathBuilder> builder = aDrawTarget.CreatePathBuilder(aFillRule);
   RefPtr<Path> path = BuildPath(builder);
   if (cacheable && NS_SVGPathCachingEnabled()) {
     mCachedPath = path;
   }
   return path.forget();
 }
--- a/gfx/2d/Rect.h
+++ b/gfx/2d/Rect.h
@@ -310,26 +310,38 @@ IntRectTyped<units> TruncatedToInt(const
 }
 
 template<class units>
 RectTyped<units> IntRectToRect(const IntRectTyped<units>& aRect)
 {
   return RectTyped<units>(aRect.x, aRect.y, aRect.Width(), aRect.Height());
 }
 
-// Convenience function for intersecting two rectangles wrapped in Maybes.
-template <typename T>
-Maybe<T>
-IntersectMaybeRects(const Maybe<T>& a, const Maybe<T>& b)
+// Convenience functions for intersecting and unioning two rectangles wrapped in Maybes.
+template <typename Rect>
+Maybe<Rect>
+IntersectMaybeRects(const Maybe<Rect>& a, const Maybe<Rect>& b)
 {
   if (!a) {
     return b;
   } else if (!b) {
     return a;
   } else {
     return Some(a->Intersect(*b));
   }
 }
+template <typename Rect>
+Maybe<Rect>
+UnionMaybeRects(const Maybe<Rect>& a, const Maybe<Rect>& b)
+{
+  if (!a) {
+    return b;
+  } else if (!b) {
+    return a;
+  } else {
+    return Some(a->Union(*b));
+  }
+}
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_RECT_H_ */
--- a/gfx/vr/ipc/PVRManager.ipdl
+++ b/gfx/vr/ipc/PVRManager.ipdl
@@ -62,19 +62,16 @@ parent:
 
   async NewButtonEventToMockController(uint32_t aDeviceID, long aButton,
                                        bool aPressed);
   async NewAxisMoveEventToMockController(uint32_t aDeviceID, long aAxis,
                                          double aValue);
   async NewPoseMoveToMockController(uint32_t aDeviceID, GamepadPoseState aPose);
 
 child:
-
-  async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
-
   // Notify children of updated VR display enumeration and details.  This will
   // be sent to all children when the parent receives RefreshDisplays, even
   // if no changes have been detected.  This ensures that Promises exposed
   // through DOM calls are always resolved.
   async UpdateDisplayInfo(VRDisplayInfo[] aDisplayUpdates);
 
   async DispatchSubmitFrameResult(uint32_t aDisplayID, VRSubmitFrameResultInfo aResult);
   async GamepadUpdate(GamepadChangeEvent aGamepadEvent);
--- a/gfx/vr/ipc/VRManagerChild.cpp
+++ b/gfx/vr/ipc/VRManagerChild.cpp
@@ -10,24 +10,21 @@
 #include "VRDisplayClient.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/layers/CompositorThread.h" // for CompositorThread
 #include "mozilla/dom/Navigator.h"
 #include "mozilla/dom/VREventObserver.h"
 #include "mozilla/dom/WindowBinding.h" // for FrameRequestCallback
 #include "mozilla/dom/ContentChild.h"
-#include "mozilla/layers/TextureClient.h"
 #include "nsContentUtils.h"
 #include "mozilla/dom/GamepadManager.h"
 #include "mozilla/dom/VRServiceTest.h"
 #include "mozilla/layers/SyncObject.h"
 
-using layers::TextureClient;
-
 namespace {
 const nsTArray<RefPtr<dom::VREventObserver>>::index_type kNoIndex =
   nsTArray<RefPtr<dom::VREventObserver> >::NoIndex;
 } // namespace
 
 namespace mozilla {
 namespace gfx {
 
@@ -148,18 +145,16 @@ VRManagerChild::ShutDown()
 VRManagerChild::DeferredDestroy(RefPtr<VRManagerChild> aVRManagerChild)
 {
   aVRManagerChild->Close();
 }
 
 void
 VRManagerChild::Destroy()
 {
-  mTexturesWaitingRecycled.Clear();
-
   // Keep ourselves alive until everything has been shut down
   RefPtr<VRManagerChild> selfRef = this;
 
   // The DeferredDestroyVRManager task takes ownership of
   // the VRManagerChild and will release it when it runs.
   MessageLoop::current()->PostTask(
              NewRunnableFunction(DeferredDestroy, selfRef));
 }
@@ -291,46 +286,16 @@ VRManagerChild::CreateVRServiceTestDispl
 void
 VRManagerChild::CreateVRServiceTestController(const nsCString& aID, dom::Promise* aPromise)
 {
   SendCreateVRServiceTestController(aID, mPromiseID);
   mPromiseList.Put(mPromiseID, aPromise);
   ++mPromiseID;
 }
 
-mozilla::ipc::IPCResult
-VRManagerChild::RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages)
-{
-  for (InfallibleTArray<AsyncParentMessageData>::index_type i = 0; i < aMessages.Length(); ++i) {
-    const AsyncParentMessageData& message = aMessages[i];
-
-    switch (message.type()) {
-      case AsyncParentMessageData::TOpNotifyNotUsed: {
-        const OpNotifyNotUsed& op = message.get_OpNotifyNotUsed();
-        NotifyNotUsed(op.TextureId(), op.fwdTransactionId());
-        break;
-      }
-      default:
-        NS_ERROR("unknown AsyncParentMessageData type");
-        return IPC_FAIL_NO_REASON(this);
-    }
-  }
-  return IPC_OK();
-}
-
-void
-VRManagerChild::NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId)
-{
-  RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
-  if (!client) {
-    return;
-  }
-  mTexturesWaitingRecycled.Remove(aTextureId);
-}
-
 PVRLayerChild*
 VRManagerChild::CreateVRLayer(uint32_t aDisplayID,
                               nsIEventTarget* aTarget,
                               uint32_t aGroup)
 {
   PVRLayerChild* vrLayerChild = AllocPVRLayerChild(aDisplayID, aGroup);
   // Do the DOM labeling.
   if (aTarget) {
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -20,17 +20,16 @@ class Promise;
 class GamepadManager;
 class Navigator;
 class VRDisplay;
 class VREventObserver;
 class VRMockDisplay;
 } // namespace dom
 namespace layers {
 class SyncObjectClient;
-class TextureClient;
 }
 namespace gfx {
 class VRLayerChild;
 class VRDisplayClient;
 
 class VRManagerChild : public PVRManagerChild
 {
 public:
@@ -87,18 +86,16 @@ protected:
   static void DeferredDestroy(RefPtr<VRManagerChild> aVRManagerChild);
 
   virtual PVRLayerChild* AllocPVRLayerChild(const uint32_t& aDisplayID,
                                             const uint32_t& aGroup) override;
   virtual bool DeallocPVRLayerChild(PVRLayerChild* actor) override;
 
   virtual mozilla::ipc::IPCResult RecvUpdateDisplayInfo(nsTArray<VRDisplayInfo>&& aDisplayUpdates) override;
 
-  virtual mozilla::ipc::IPCResult RecvParentAsyncMessages(InfallibleTArray<AsyncParentMessageData>&& aMessages) override;
-
   virtual mozilla::ipc::IPCResult RecvDispatchSubmitFrameResult(const uint32_t& aDisplayID, const VRSubmitFrameResultInfo& aResult) override;
   virtual mozilla::ipc::IPCResult RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override;
   virtual mozilla::ipc::IPCResult RecvReplyGamepadVibrateHaptic(const uint32_t& aPromiseID) override;
 
   virtual mozilla::ipc::IPCResult RecvReplyCreateVRServiceTestDisplay(const nsCString& aID,
                                                                       const uint32_t& aPromiseID,
                                                                       const uint32_t& aDeviceID) override;
   virtual mozilla::ipc::IPCResult RecvReplyCreateVRServiceTestController(const nsCString& aID,
@@ -110,21 +107,16 @@ protected:
   }
 private:
 
   void FireDOMVRDisplayMountedEventInternal(uint32_t aDisplayID);
   void FireDOMVRDisplayUnmountedEventInternal(uint32_t aDisplayID);
   void FireDOMVRDisplayConnectEventInternal(uint32_t aDisplayID);
   void FireDOMVRDisplayDisconnectEventInternal(uint32_t aDisplayID);
   void FireDOMVRDisplayPresentChangeEventInternal(uint32_t aDisplayID);
-  /**
-  * Notify id of Texture When host side end its use. Transaction id is used to
-  * make sure if there is no newer usage.
-  */
-  void NotifyNotUsed(uint64_t aTextureId, uint64_t aFwdTransactionId);
 
   nsTArray<RefPtr<VRDisplayClient> > mDisplays;
   bool mDisplaysInitialized;
   nsTArray<uint64_t> mNavigatorCallbacks;
 
   MessageLoop* mMessageLoop;
 
   struct FrameRequest;
@@ -133,22 +125,16 @@ private:
   /**
   * The current frame request callback handle
   */
   int32_t mFrameRequestCallbackCounter;
   mozilla::TimeStamp mStartTimeStamp;
 
   nsTArray<RefPtr<dom::VREventObserver>> mListeners;
 
-  /**
-  * Hold TextureClients refs until end of their usages on host side.
-  * It defer calling of TextureClient recycle callback.
-  */
-  nsDataHashtable<nsUint64HashKey, RefPtr<layers::TextureClient> > mTexturesWaitingRecycled;
-
   layers::LayersBackend mBackend;
   RefPtr<layers::SyncObjectClient> mSyncObject;
   nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mGamepadPromiseList; // TODO: check if it can merge into one list?
   uint32_t mPromiseID;
   nsRefPtrHashtable<nsUint32HashKey, dom::Promise> mPromiseList;
   RefPtr<dom::VRMockDisplay> mVRMockDisplay;
 
   DISALLOW_COPY_AND_ASSIGN(VRManagerChild);
--- a/js/src/devtools/rootAnalysis/build.js
+++ b/js/src/devtools/rootAnalysis/build.js
@@ -1,11 +1,11 @@
 #!/bin/sh
 
 set -e
 
 cd $SOURCE
-make -f client.mk configure
-make -C $ANALYZED_OBJDIR export
+./mach configure
+./mach build export
 ./mach build -X nsprpub mfbt memory memory/mozalloc modules/zlib mozglue js/src xpcom/glue js/ductwork/debugger js/ipc js/xpconnect/loader js/xpconnect/wrappers js/xpconnect/src
 status=$?
 echo "[[[[ build.js complete, exit code $status ]]]]"
 exit $status
--- a/js/src/frontend/NameAnalysisTypes.h
+++ b/js/src/frontend/NameAnalysisTypes.h
@@ -31,17 +31,17 @@ class EnvironmentCoordinate
 
   public:
     explicit inline EnvironmentCoordinate(jsbytecode* pc)
       : hops_(GET_ENVCOORD_HOPS(pc)), slot_(GET_ENVCOORD_SLOT(pc + ENVCOORD_HOPS_LEN))
     {
         MOZ_ASSERT(JOF_OPTYPE(JSOp(*pc)) == JOF_ENVCOORD);
     }
 
-    EnvironmentCoordinate() {}
+    EnvironmentCoordinate() = default;
 
     void setHops(uint32_t hops) {
         MOZ_ASSERT(hops < ENVCOORD_HOPS_LIMIT);
         hops_ = hops;
     }
 
     void setSlot(uint32_t slot) {
         MOZ_ASSERT(slot < ENVCOORD_SLOT_LIMIT);
--- a/layout/base/GeometryUtils.cpp
+++ b/layout/base/GeometryUtils.cpp
@@ -30,28 +30,28 @@ enum GeometryNodeType {
   GEOMETRY_NODE_TEXT,
   GEOMETRY_NODE_DOCUMENT
 };
 
 static nsIFrame*
 GetFrameForNode(nsINode* aNode, GeometryNodeType aType)
 {
   nsIDocument* doc = aNode->OwnerDoc();
+  if (aType == GEOMETRY_NODE_TEXT) {
+    if (nsIPresShell* shell = doc->GetShell()) {
+      shell->FrameConstructor()->EnsureFrameForTextNodeIsCreatedAfterFlush(
+          static_cast<nsGenericDOMDataNode*>(aNode));
+    }
+  }
   doc->FlushPendingNotifications(FlushType::Layout);
+
   switch (aType) {
+  case GEOMETRY_NODE_TEXT:
   case GEOMETRY_NODE_ELEMENT:
     return aNode->AsContent()->GetPrimaryFrame();
-  case GEOMETRY_NODE_TEXT: {
-    nsIPresShell* presShell = doc->GetShell();
-    if (presShell) {
-      return presShell->FrameConstructor()->EnsureFrameForTextNode(
-          static_cast<nsGenericDOMDataNode*>(aNode));
-    }
-    return nullptr;
-  }
   case GEOMETRY_NODE_DOCUMENT: {
     nsIPresShell* presShell = doc->GetShell();
     return presShell ? presShell->GetRootFrame() : nullptr;
   }
   default:
     MOZ_ASSERT(false, "Unknown GeometryNodeType");
     return nullptr;
   }
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/1382534.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <style>
+            .container {
+                position: absolute;
+                top: -1px;
+                bottom: -1px;
+                left: 0;
+                width: 100%;
+                clip: rect(0, auto, auto, 0);
+                clip-path: inset(0 0 0 0)
+            }
+            .picture {
+                position: fixed;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="container">
+            <div class="picture">
+                <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
+            </div>
+        </div>
+    </body>
+</html>
\ No newline at end of file
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -489,16 +489,17 @@ load 1308793.svg
 load 1308848-1.html
 load 1308848-2.html
 load 1338772-1.html
 load 1343937.html
 asserts(0-1) load 1343606.html # bug 1343948
 load 1352380.html
 load 1362423-1.html
 load 1381323.html
+load 1382534.html
 asserts-if(!stylo,1) load 1388625-1.html # bug 1389286
 load 1390389.html
 load 1391736.html
 load 1395591-1.html
 load 1395715-1.html
 load 1397398-1.html
 load 1397398-2.html
 load 1397398-3.html
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -8950,32 +8950,41 @@ InvalidateCanvasIfNeeded(nsIPresShell* p
   // root.  We might not need to invalidate in this case (eg we might be in
   // XHTML or something), but chances are we want to.  Play it safe.
   // Invalidate the viewport.
 
   nsIFrame* rootFrame = presShell->GetRootFrame();
   rootFrame->InvalidateFrameSubtree();
 }
 
-nsIFrame*
-nsCSSFrameConstructor::EnsureFrameForTextNode(nsGenericDOMDataNode* aContent)
-{
-  if (aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE) &&
-      !mAlwaysCreateFramesForIgnorableWhitespace) {
-    // Text frame may have been suppressed. Disable suppression and signal
-    // that a flush should be performed. We do this on a document-wide
-    // basis so that pages that repeatedly query metrics for
-    // collapsed-whitespace text nodes don't trigger pathological behavior.
-    mAlwaysCreateFramesForIgnorableWhitespace = true;
-    nsAutoScriptBlocker blocker;
-    BeginUpdate();
-    ReconstructDocElementHierarchy(InsertionKind::Sync);
-    EndUpdate();
-  }
-  return aContent->GetPrimaryFrame();
+bool
+nsCSSFrameConstructor::EnsureFrameForTextNodeIsCreatedAfterFlush(
+  nsGenericDOMDataNode* aContent)
+{
+  if (!aContent->HasFlag(NS_CREATE_FRAME_IF_NON_WHITESPACE)) {
+    return false;
+  }
+
+  if (mAlwaysCreateFramesForIgnorableWhitespace) {
+    return false;
+  }
+
+  // Text frame may have been suppressed. Disable suppression and signal that a
+  // flush should be performed. We do this on a document-wide basis so that
+  // pages that repeatedly query metrics for collapsed-whitespace text nodes
+  // don't trigger pathological behavior.
+  mAlwaysCreateFramesForIgnorableWhitespace = true;
+  Element* root = mDocument->GetRootElement();
+  if (!root) {
+    return false;
+  }
+
+  RestyleManager()->PostRestyleEvent(
+    root, nsRestyleHint(0), nsChangeHint_ReconstructFrame);
+  return true;
 }
 
 void
 nsCSSFrameConstructor::CharacterDataChanged(nsIContent* aContent,
                                             CharacterDataChangeInfo* aInfo)
 {
   AUTO_LAYOUT_PHASE_ENTRY_POINT(mPresShell->GetPresContext(), FrameC);
 
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -312,21 +312,22 @@ public:
                       nsIContent* aChild,
                       nsIContent* aOldNextSibling,
                       RemoveFlags aFlags);
 
   void CharacterDataChanged(nsIContent* aContent,
                             CharacterDataChangeInfo* aInfo);
 
   // If aContent is a text node that has been optimized away due to being
-  // whitespace next to a block boundary (or for some other reason), stop
-  // doing that and create a frame for it if it should have one. This recreates
-  // frames so be careful (although this should not change actual layout).
-  // Returns the frame for aContent if there is one.
-  nsIFrame* EnsureFrameForTextNode(nsGenericDOMDataNode* aContent);
+  // whitespace next to a block boundary (or for some other reason), ensure that
+  // a frame for it is created the next time frames are flushed, if it can
+  // possibly have a frame at all.
+  //
+  // Returns whether there are chances for the frame to be unsuppressed.
+  bool EnsureFrameForTextNodeIsCreatedAfterFlush(nsGenericDOMDataNode* aContent);
 
   // Generate the child frames and process bindings
   void GenerateChildFrames(nsContainerFrame* aFrame);
 
   // Should be called when a frame is going to be destroyed and
   // WillDestroyFrameTree hasn't been called yet.
   void NotifyDestroyingFrame(nsIFrame* aFrame);
 
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -85,16 +85,17 @@
 #include "gfxDrawable.h"
 #include "gfxEnv.h"
 #include "gfxUtils.h"
 #include "nsDataHashtable.h"
 #include "nsTableWrapperFrame.h"
 #include "nsTextFrame.h"
 #include "nsFontFaceList.h"
 #include "nsFontInflationData.h"
+#include "nsSVGIntegrationUtils.h"
 #include "nsSVGUtils.h"
 #include "SVGImageContext.h"
 #include "SVGTextFrame.h"
 #include "nsStyleStructInlines.h"
 #include "nsStyleTransformMatrix.h"
 #include "nsIFrameInlines.h"
 #include "ImageContainer.h"
 #include "nsComputedDOMStyle.h"
@@ -3651,17 +3652,21 @@ nsLayoutUtils::PaintFrame(gfxContext* aR
 
   Maybe<nsDisplayListBuilder> nonRetainedBuilder;
   Maybe<nsDisplayList> nonRetainedList;
   nsDisplayListBuilder* builderPtr = nullptr;
   nsDisplayList* listPtr = nullptr;
   RetainedDisplayListBuilder* retainedBuilder = nullptr;
 
   const bool buildCaret = !(aFlags & PaintFrameFlags::PAINT_HIDE_CARET);
-  const bool retainDisplayList = gfxPrefs::LayoutRetainDisplayList();
+
+  // Enable display list retaining if the pref is set and if we are in a
+  // content process.
+  const bool retainDisplayList =
+    gfxPrefs::LayoutRetainDisplayList() && XRE_IsContentProcess();
 
   if (retainDisplayList &&
       aBuilderMode == nsDisplayListBuilderMode::PAINTING &&
       (aFlags & PaintFrameFlags::PAINT_WIDGET_LAYERS)) {
     retainedBuilder = aFrame->GetProperty(RetainedDisplayListBuilder::Cached());
 
     if (!retainedBuilder) {
       retainedBuilder =
@@ -9802,18 +9807,18 @@ nsLayoutUtils::GetCumulativeApzCallbackT
 /* static */ nsRect
 nsLayoutUtils::ComputePartialPrerenderArea(const nsRect& aDirtyRect,
                                            const nsRect& aOverflow,
                                            const nsSize& aPrerenderSize)
 {
   // Simple calculation for now: center the pre-render area on the dirty rect,
   // and clamp to the overflow area. Later we can do more advanced things like
   // redistributing from one axis to another, or from one side to another.
-  nscoord xExcess = aPrerenderSize.width - aDirtyRect.width;
-  nscoord yExcess = aPrerenderSize.height - aDirtyRect.height;
+  nscoord xExcess = std::max(aPrerenderSize.width - aDirtyRect.width, 0);
+  nscoord yExcess = std::max(aPrerenderSize.height - aDirtyRect.height, 0);
   nsRect result = aDirtyRect;
   result.Inflate(xExcess / 2, yExcess / 2);
   return result.MoveInsideAndClamp(aOverflow);
 }
 
 static
 bool
 LineHasNonEmptyContentWorker(nsIFrame* aFrame)
@@ -10019,8 +10024,42 @@ nsLayoutUtils::ComputeGeometryBox(nsIFra
   // element, which does have an associated CSS layout box. In this case we
   // should still use ComputeHTMLReferenceRect for region computing.
   nsRect r = (aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)
              ? ComputeSVGReferenceRect(aFrame, aGeometryBox)
              : ComputeHTMLReferenceRect(aFrame, aGeometryBox);
 
   return r;
 }
+
+/* static */ nsPoint
+nsLayoutUtils::ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
+                                        nsIFrame* aFrame)
+{
+  nsPoint offsetToBoundingBox = aBuilder->ToReferenceFrame(aFrame) -
+                         nsSVGIntegrationUtils::GetOffsetToBoundingBox(aFrame);
+  if (!aFrame->IsFrameOfType(nsIFrame::eSVG)) {
+    // Snap the offset if the reference frame is not a SVG frame, since other
+    // frames will be snapped to pixel when rendering.
+    offsetToBoundingBox = nsPoint(
+      aFrame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.x),
+      aFrame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.y));
+  }
+
+  // During SVG painting, the offset computed here is applied to the gfxContext
+  // "ctx" used to paint the mask. After applying only "offsetToBoundingBox",
+  // "ctx" would have its origin at the top left corner of frame's bounding box
+  // (over all continuations).
+  // However, SVG painting needs the origin to be located at the origin of the
+  // SVG frame's "user space", i.e. the space in which, for example, the
+  // frame's BBox lives.
+  // SVG geometry frames and foreignObject frames apply their own offsets, so
+  // their position is relative to their user space. So for these frame types,
+  // if we want "ctx" to be in user space, we first need to subtract the
+  // frame's position so that SVG painting can later add it again and the
+  // frame is painted in the right place.
+  gfxPoint toUserSpaceGfx = nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(aFrame);
+  nsPoint toUserSpace =
+    nsPoint(nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.x)),
+            nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.y)));
+
+  return (offsetToBoundingBox - toUserSpace);
+}
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -3039,17 +3039,20 @@ public:
 
   /**
    * Compute a rect to pre-render in cases where we want to render more of
    * something than what is visible (usually to support async transformation).
    * @param aDirtyRect the area that's visible
    * @param aOverflow the total size of the thing we're rendering
    * @param aPrerenderSize how large of an area we're willing to render
    * @return A rectangle that includes |aDirtyRect|, is clamped to |aOverflow|,
-   *         and is no larger than |aPrerenderSize|.
+   *         and is no larger than |aPrerenderSize| (unless |aPrerenderSize|
+   *         is smaller than |aDirtyRect|, in which case the returned rect
+   *         will still include |aDirtyRect| and thus be larger than
+   *         |aPrerenderSize|).
    */
   static nsRect ComputePartialPrerenderArea(const nsRect& aDirtyRect,
                                             const nsRect& aOverflow,
                                             const nsSize& aPrerenderSize);
 
   /*
    * Checks whether a node is an invisible break.
    * If not, returns the first frame on the next line if such a next line exists.
@@ -3061,16 +3064,19 @@ public:
    * @param   aNextLineFrame  assigned to first frame on the next line if such a
    *                          next line exists, null otherwise.
    */
   static bool IsInvisibleBreak(nsINode* aNode, nsIFrame** aNextLineFrame = nullptr);
 
   static nsRect ComputeGeometryBox(nsIFrame* aFrame,
                                    StyleGeometryBox aGeometryBox);
 
+  static nsPoint ComputeOffsetToUserSpace(nsDisplayListBuilder* aBuilder,
+                                          nsIFrame* aFrame);
+
 private:
   static uint32_t sFontSizeInflationEmPerLine;
   static uint32_t sFontSizeInflationMinTwips;
   static uint32_t sFontSizeInflationLineThreshold;
   static int32_t  sFontSizeInflationMappingIntercept;
   static uint32_t sFontSizeInflationMaxRatio;
   static bool sFontSizeInflationForceEnabled;
   static bool sFontSizeInflationDisabledInMasterProcess;
--- a/layout/generic/StickyScrollContainer.cpp
+++ b/layout/generic/StickyScrollContainer.cpp
@@ -280,28 +280,28 @@ StickyScrollContainer::GetScrollRanges(n
   ComputeStickyLimits(firstCont, &stick, &contain);
 
   aOuter->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
   aInner->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
 
   const nsPoint normalPosition = firstCont->GetNormalPosition();
 
   // Bottom and top
-  if (stick.YMost() != nscoord_MAX/2) {
+  if (stick.YMost() != (nscoord_MAX + (nscoord_MIN/2))) {
     aOuter->SetTopEdge(contain.y - stick.YMost());
     aInner->SetTopEdge(normalPosition.y - stick.YMost());
   }
 
   if (stick.y != nscoord_MIN/2) {
     aInner->SetBottomEdge(normalPosition.y - stick.y);
     aOuter->SetBottomEdge(contain.YMost() - stick.y);
   }
 
   // Right and left
-  if (stick.XMost() != nscoord_MAX/2) {
+  if (stick.XMost() != (nscoord_MAX + (nscoord_MIN/2))) {
     aOuter->SetLeftEdge(contain.x - stick.XMost());
     aInner->SetLeftEdge(normalPosition.x - stick.XMost());
   }
 
   if (stick.x != nscoord_MIN/2) {
     aInner->SetRightEdge(normalPosition.x - stick.x);
     aOuter->SetRightEdge(contain.XMost() - stick.x);
   }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -48,16 +48,17 @@
 #include "mozilla/RestyleManagerInlines.h"
 #include "nsInlineFrame.h"
 #include "nsIDOMNode.h"
 #include "nsISelection.h"
 #include "nsISelectionPrivate.h"
 #include "nsFrameSelection.h"
 #include "nsGkAtoms.h"
 #include "nsCSSAnonBoxes.h"
+#include "nsCSSClipPathInstance.h"
 
 #include "nsFrameTraversal.h"
 #include "nsRange.h"
 #include "nsITextControlFrame.h"
 #include "nsNameSpaceManager.h"
 #include "nsIPercentBSizeObserver.h"
 #include "nsStyleStructInlines.h"
 #include "FrameLayerBuilder.h"
@@ -72,16 +73,17 @@
 #include "imgIRequest.h"
 #include "nsError.h"
 #include "nsContainerFrame.h"
 #include "nsBoxLayoutState.h"
 #include "nsBlockFrame.h"
 #include "nsDisplayList.h"
 #include "nsSVGIntegrationUtils.h"
 #include "SVGObserverUtils.h"
+#include "nsSVGMaskFrame.h"
 #include "nsChangeHint.h"
 #include "nsDeckFrame.h"
 #include "nsSubDocumentFrame.h"
 #include "SVGTextFrame.h"
 #include "RetainedDisplayListBuilder.h"
 
 #include "gfxContext.h"
 #include "nsAbsoluteContainingBlock.h"
@@ -2514,16 +2516,119 @@ WrapSeparatorTransform(nsDisplayListBuil
     nsDisplayTransform *sepIdItem =
       new (aBuilder) nsDisplayTransform(aBuilder, aFrame, aSource,
                                         aBuilder->GetVisibleRect(), Matrix4x4(), aIndex);
     sepIdItem->SetNoExtendContext();
     aTarget->AppendToTop(sepIdItem);
   }
 }
 
+// Try to compute a clip rect to bound the contents of the mask item
+// that will be built for |aMaskedFrame|. If we're not able to compute
+// one, return an empty Maybe.
+// The returned clip rect, if there is one, is relative to |aMaskedFrame|.
+static Maybe<nsRect>
+ComputeClipForMaskItem(nsDisplayListBuilder* aBuilder, nsIFrame* aMaskedFrame,
+                       bool aHandleOpacity)
+{
+  const nsStyleSVGReset* svgReset = aMaskedFrame->StyleSVGReset();
+
+  nsSVGUtils::MaskUsage maskUsage;
+  nsSVGUtils::DetermineMaskUsage(aMaskedFrame, aHandleOpacity, maskUsage);
+
+  nsPoint offsetToUserSpace = nsLayoutUtils::ComputeOffsetToUserSpace(aBuilder, aMaskedFrame);
+  int32_t devPixelRatio = aMaskedFrame->PresContext()->AppUnitsPerDevPixel();
+  gfxPoint devPixelOffsetToUserSpace = nsLayoutUtils::PointToGfxPoint(
+      offsetToUserSpace, devPixelRatio);
+  gfxMatrix cssToDevMatrix = nsSVGUtils::GetCSSPxToDevPxMatrix(aMaskedFrame);
+
+  nsPoint toReferenceFrame;
+  aBuilder->FindReferenceFrameFor(aMaskedFrame, &toReferenceFrame);
+
+  Maybe<gfxRect> combinedClip;
+  if (maskUsage.shouldApplyBasicShape) {
+    Rect result = nsCSSClipPathInstance::GetBoundingRectForBasicShapeClip(
+        aMaskedFrame, svgReset->mClipPath);
+    combinedClip = Some(ThebesRect(result));
+  } else if (maskUsage.shouldApplyClipPath) {
+    gfxRect result = nsSVGUtils::GetBBox(aMaskedFrame,
+        nsSVGUtils::eBBoxIncludeClipped |
+        nsSVGUtils::eBBoxIncludeFill |
+        nsSVGUtils::eBBoxIncludeMarkers);
+    combinedClip = Some(cssToDevMatrix.TransformBounds(result));
+  } else {
+    // The code for this case is adapted from ComputeMaskGeometry().
+
+    nsRect borderArea(toReferenceFrame, aMaskedFrame->GetSize());
+    borderArea -= offsetToUserSpace;
+
+    // Use an infinite dirty rect to pass into nsCSSRendering::
+    // GetImageLayerClip() because we don't have an actual dirty rect to
+    // pass in. This is fine because the only time GetImageLayerClip() will
+    // not intersect the incoming dirty rect with something is in the "NoClip"
+    // case, and we handle that specially.
+    nsRect dirtyRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX);
+
+    nsIFrame* firstFrame = nsLayoutUtils::FirstContinuationOrIBSplitSibling(aMaskedFrame);
+    SVGObserverUtils::EffectProperties effectProperties =
+        SVGObserverUtils::GetEffectProperties(firstFrame);
+    nsTArray<nsSVGMaskFrame*> maskFrames = effectProperties.GetMaskFrames();
+
+    for (uint32_t i = 0; i < maskFrames.Length(); ++i) {
+      gfxRect clipArea;
+      if (maskFrames[i]) {
+        clipArea = maskFrames[i]->GetMaskArea(aMaskedFrame);
+        clipArea = cssToDevMatrix.TransformBounds(clipArea);
+      } else {
+        const auto& layer = svgReset->mMask.mLayers[i];
+        if (layer.mClip == StyleGeometryBox::NoClip) {
+          return Nothing();
+        }
+
+        nsCSSRendering::ImageLayerClipState clipState;
+        nsCSSRendering::GetImageLayerClip(layer, aMaskedFrame,
+                                          *aMaskedFrame->StyleBorder(),
+                                          borderArea, dirtyRect,
+                                          false /* aWillPaintBorder */,
+                                          devPixelRatio, &clipState);
+        clipArea = clipState.mDirtyRectInDevPx;
+      }
+      combinedClip = UnionMaybeRects(combinedClip, Some(clipArea));
+    }
+  }
+  if (combinedClip) {
+    if (combinedClip->IsEmpty()) {
+      // *clipForMask might be empty if all mask references are not resolvable
+      // or the size of them are empty. We still need to create a transparent mask
+      // before bug 1276834 fixed, so don't clip ctx by an empty rectangle for for
+      // now.
+      return Nothing();
+    }
+
+    // Convert to user space.
+    *combinedClip += devPixelOffsetToUserSpace;
+
+    // Round the clip out. In FrameLayerBuilder we round clips to nearest
+    // pixels, and if we have a really thin clip here, that can cause the
+    // clip to become empty if we didn't round out here.
+    // The rounding happens in coordinates that are relative to the reference
+    // frame, which matches what FrameLayerBuilder does.
+    combinedClip->RoundOut();
+
+    // Convert to app units.
+    nsRect result = nsLayoutUtils::RoundGfxRectToAppRect(*combinedClip, devPixelRatio);
+
+    // The resulting clip is relative to the reference frame, but the caller
+    // expects it to be relative to the masked frame, so adjust it.
+    result -= toReferenceFrame;
+    return Some(result);
+  }
+  return Nothing();
+}
+
 void
 nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
                                              nsDisplayList*        aList,
                                              bool*                 aCreatedContainerItem) {
   if (GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
     return;
 
   // Replaced elements have their visibility handled here, because
@@ -2728,29 +2833,38 @@ nsIFrame::BuildDisplayListForStackingCon
   } else if (usingFilter) {
     clipCapturedBy = ContainerItemType::eFilter;
   }
 
   if (clipCapturedBy != ContainerItemType::eNone) {
     clipState.Clear();
   }
 
+  Maybe<nsRect> clipForMask;
+  if (usingMask) {
+    clipForMask = ComputeClipForMaskItem(aBuilder, this, !useOpacity);
+  }
+
   nsDisplayListCollection set(aBuilder);
   {
     DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
     nsDisplayListBuilder::AutoInTransformSetter
       inTransformSetter(aBuilder, inTransform);
     nsDisplayListBuilder::AutoSaveRestorePerspectiveIndex
       perspectiveIndex(aBuilder, this);
 
     CheckForApzAwareEventHandlers(aBuilder, this);
 
     Maybe<nsRect> contentClip =
       GetClipPropClipRect(disp, effects, GetSize());
 
+    if (usingMask) {
+      contentClip = IntersectMaybeRects(contentClip, clipForMask);
+    }
+
     if (contentClip) {
       aBuilder->IntersectDirtyRect(*contentClip);
       aBuilder->IntersectVisibleRect(*contentClip);
       nestedClipState.ClipContentDescendants(*contentClip +
                                              aBuilder->ToReferenceFrame(this));
     }
 
     // extend3DContext also guarantees that applyAbsPosClipping and usingSVGEffects are false
@@ -2949,20 +3063,32 @@ nsIFrame::BuildDisplayListForStackingCon
       resultList.AppendNewToTop(
         new (aBuilder) nsDisplayFilter(aBuilder, this, &resultList,
                                        handleOpacity));
     }
 
     if (usingMask) {
       DisplayListClipState::AutoSaveRestore maskClipState(aBuilder);
       maskClipState.ClearUpToASR(containerItemASR);
+      // The mask should move with aBuilder->CurrentActiveScrolledRoot(), so
+      // that's the ASR we prefer to use for the mask item. However, we can
+      // only do this if the mask if clipped with respect to that ASR, because
+      // an item always needs to have finite bounds with respect to its ASR.
+      // If we weren't able to compute a clip for the mask, we fall back to
+      // using containerItemASR, which is the lowest common ancestor clip of
+      // the mask's contents. That's not entirely crrect, but it satisfies
+      // the base requirement of the ASR system (that items have finite bounds
+      // wrt. their ASR).
+      const ActiveScrolledRoot* maskASR = clipForMask.isSome()
+                                        ? aBuilder->CurrentActiveScrolledRoot()
+                                        : containerItemASR;
       /* List now emptied, so add the new list to the top. */
       resultList.AppendNewToTop(
-          new (aBuilder) nsDisplayMask(aBuilder, this, &resultList,
-                                       !useOpacity, containerItemASR));
+          new (aBuilder) nsDisplayMask(aBuilder, this, &resultList, !useOpacity,
+                                       maskASR));
     }
 
     // Also add the hoisted scroll info items. We need those for APZ scrolling
     // because nsDisplayMask items can't build active layers.
     aBuilder->ExitSVGEffectsContents();
     resultList.AppendToTop(&hoistedScrollInfoItemsStorage);
     if (aCreatedContainerItem) {
       *aCreatedContainerItem = false;
--- a/layout/inspector/ServoStyleRuleMap.cpp
+++ b/layout/inspector/ServoStyleRuleMap.cpp
@@ -171,16 +171,13 @@ ServoStyleRuleMap::FillTableFromRuleList
     FillTableFromRule(aRuleList->GetRule(i));
   }
 }
 
 void
 ServoStyleRuleMap::FillTableFromStyleSheet(ServoStyleSheet* aSheet)
 {
   if (aSheet->IsComplete()) {
-    // XBL stylesheets are not expected to ever change, so it's a waste
-    // to make its inner unique.
-    FillTableFromRuleList(aSheet->GetCssRulesInternal(
-        /* aRequireUniqueInner = */ !mStyleSet->IsForXBL()));
+    FillTableFromRuleList(aSheet->GetCssRulesInternal());
   }
 }
 
 } // namespace mozilla
--- a/layout/painting/FrameLayerBuilder.cpp
+++ b/layout/painting/FrameLayerBuilder.cpp
@@ -3864,18 +3864,16 @@ SetCSSMaskLayerUserData(Layer* aMaskLaye
   aMaskLayer->SetUserData(&gCSSMaskLayerUserData,
                           new CSSMaskLayerUserData());
 }
 
 void
 ContainerState::SetupMaskLayerForCSSMask(Layer* aLayer,
                                          nsDisplayMask* aMaskItem)
 {
-  MOZ_ASSERT(mManager->IsCompositingCheap());
-
   RefPtr<ImageLayer> maskLayer =
     CreateOrRecycleMaskImageLayerFor(MaskLayerKey(aLayer, Nothing()),
                                      SetCSSMaskLayerUserData);
 
   CSSMaskLayerUserData* oldUserData =
     static_cast<CSSMaskLayerUserData*>(maskLayer->GetUserData(&gCSSMaskLayerUserData));
 
   bool snap;
@@ -4100,21 +4098,18 @@ ContainerState::ProcessDisplayItems(nsDi
     if (itemType == DisplayItemType::TYPE_LAYER_EVENT_REGIONS) {
       bounds = item->GetBounds(mBuilder, &dummy);
       if (itemClip.HasClip()) {
         bounds.IntersectRect(bounds, itemClip.GetClipRect());
       }
     }
     if (!bounds.IsEmpty()) {
       if (itemASR != mContainerASR) {
-        const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(item->GetClipChain(), mContainerASR);
-        MOZ_ASSERT(clip || gfxPrefs::LayoutUseContainersForRootFrames(),
-                   "the item should have finite bounds with respect to mContainerASR.");
-        if (clip) {
-          bounds = clip->GetClipRect();
+        if (Maybe<nsRect> clip = item->GetClipWithRespectToASR(mBuilder, mContainerASR)) {
+          bounds = clip.ref();
         }
       }
     }
     ((nsRect&)mAccumulatedChildBounds).UnionRect(mAccumulatedChildBounds, bounds);
 #endif
 
     nsIntRect itemVisibleRect = itemDrawRect;
     // We haven't computed visibility at this point, so item->GetVisibleRect()
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -2152,25 +2152,18 @@ nsDisplayList::GetBounds(nsDisplayListBu
 nsRect
 nsDisplayList::GetClippedBoundsWithRespectToASR(nsDisplayListBuilder* aBuilder,
                                                 const ActiveScrolledRoot* aASR,
                                                 nsRect* aVisibleRect) const {
   nsRect bounds;
   for (nsDisplayItem* i = GetBottom(); i != nullptr; i = i->GetAbove()) {
     nsRect r = i->GetClippedBounds(aBuilder);
     if (aASR != i->GetActiveScrolledRoot() && !r.IsEmpty()) {
-      const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(i->GetClipChain(), aASR);
-#ifdef DEBUG
-      if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
-        MOZ_ASSERT(clip,
-                   "Need to be clipped wrt aASR. Do not call this function with an ASR that our child items don't have finite bounds wrt.");
-      }
-#endif
-      if (clip) {
-        r = clip->GetClipRect();
+      if (Maybe<nsRect> clip = i->GetClipWithRespectToASR(aBuilder, aASR)) {
+        r = clip.ref();
       }
     }
     if (aVisibleRect) {
       aVisibleRect->UnionRect(*aVisibleRect, i->GetVisibleRect());
     }
     bounds.UnionRect(bounds, r);
   }
   return bounds;
@@ -2972,16 +2965,31 @@ nsDisplayItem::SetClipChain(const Displa
   mClip = DisplayItemClipChain::ClipForASR(aClipChain, mActiveScrolledRoot);
 
   if (aStore) {
     mState.mClipChain = mClipChain;
     mState.mClip = mClip;
   }
 }
 
+Maybe<nsRect>
+nsDisplayItem::GetClipWithRespectToASR(nsDisplayListBuilder* aBuilder,
+                                       const ActiveScrolledRoot* aASR) const
+{
+  if (const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(GetClipChain(), aASR)) {
+    return Some(clip->GetClipRect());
+  }
+#ifdef DEBUG
+  if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
+    MOZ_ASSERT(false, "item should have finite clip with respect to aASR");
+  }
+#endif
+  return Nothing();
+}
+
 void
 nsDisplayItem::FuseClipChainUpTo(nsDisplayListBuilder* aBuilder,
                                  const ActiveScrolledRoot* aASR)
 {
   const DisplayItemClipChain* sc = mClipChain;
   DisplayItemClip mergedClip;
   while (sc && ActiveScrolledRoot::PickDescendant(aASR, sc->mASR) == sc->mASR) {
     mergedClip.IntersectWith(sc->mClip);
@@ -7303,17 +7311,17 @@ nsDisplayStickyPosition::CreateWebRender
     wr::StickyOffsetBounds vBounds = { 0.0, 0.0 };
     wr::StickyOffsetBounds hBounds = { 0.0, 0.0 };
 
     nsRect outer;
     nsRect inner;
     stickyScrollContainer->GetScrollRanges(mFrame, &outer, &inner);
 
     nsIFrame* scrollFrame = do_QueryFrame(stickyScrollContainer->ScrollFrame());
-    nsPoint offset = scrollFrame->GetOffsetTo(ReferenceFrame());
+    nsPoint offset = scrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
 
     // Adjust the scrollPort coordinates to be relative to the reference frame,
     // so that it is in the same space as everything else.
     nsRect scrollPort = stickyScrollContainer->ScrollFrame()->GetScrollPortRect();
     scrollPort += offset;
 
     // The following computations make more sense upon understanding the
     // semantics of "inner" and "outer", which is explained in the comment on
@@ -9059,49 +9067,16 @@ ComputeClipExtsInDeviceSpace(gfxContext&
   IntRect result;
   ToRect(clippedFrameSurfaceRect).ToIntRect(&result);
   return mozilla::gfx::Factory::CheckSurfaceSize(result.Size()) ? result
                                                                 : IntRect();
 }
 
 typedef nsSVGIntegrationUtils::PaintFramesParams PaintFramesParams;
 
-static nsPoint
-ComputeOffsetToUserSpace(const PaintFramesParams& aParams)
-{
-  nsIFrame* frame = aParams.frame;
-  nsPoint offsetToBoundingBox = aParams.builder->ToReferenceFrame(frame) -
-                         nsSVGIntegrationUtils::GetOffsetToBoundingBox(frame);
-  if (!frame->IsFrameOfType(nsIFrame::eSVG)) {
-    // Snap the offset if the reference frame is not a SVG frame, since other
-    // frames will be snapped to pixel when rendering.
-    offsetToBoundingBox = nsPoint(
-      frame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.x),
-      frame->PresContext()->RoundAppUnitsToNearestDevPixels(offsetToBoundingBox.y));
-  }
-
-  // After applying only "offsetToBoundingBox", aParams.ctx would have its
-  // origin at the top left corner of frame's bounding box (over all
-  // continuations).
-  // However, SVG painting needs the origin to be located at the origin of the
-  // SVG frame's "user space", i.e. the space in which, for example, the
-  // frame's BBox lives.
-  // SVG geometry frames and foreignObject frames apply their own offsets, so
-  // their position is relative to their user space. So for these frame types,
-  // if we want aCtx to be in user space, we first need to subtract the
-  // frame's position so that SVG painting can later add it again and the
-  // frame is painted in the right place.
-  gfxPoint toUserSpaceGfx = nsSVGUtils::FrameSpaceInCSSPxToUserSpaceOffset(frame);
-  nsPoint toUserSpace =
-    nsPoint(nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.x)),
-            nsPresContext::CSSPixelsToAppUnits(float(toUserSpaceGfx.y)));
-
-  return (offsetToBoundingBox - toUserSpace);
-}
-
 static void
 ComputeMaskGeometry(PaintFramesParams& aParams)
 {
   // Properties are added lazily and may have been removed by a restyle, so
   // make sure all applicable ones are set again.
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(aParams.frame);
 
@@ -9113,17 +9088,19 @@ ComputeMaskGeometry(PaintFramesParams& a
 
   if (maskFrames.Length() == 0) {
     return;
   }
 
   gfxContext& ctx = aParams.ctx;
   nsIFrame* frame = aParams.frame;
 
-  nsPoint offsetToUserSpace = ComputeOffsetToUserSpace(aParams);
+  nsPoint offsetToUserSpace =
+      nsLayoutUtils::ComputeOffsetToUserSpace(aParams.builder, aParams.frame);
+
   gfxPoint devPixelOffsetToUserSpace =
     nsLayoutUtils::PointToGfxPoint(offsetToUserSpace,
                                    frame->PresContext()->AppUnitsPerDevPixel());
 
   gfxContextMatrixAutoSaveRestore matSR(&ctx);
   ctx.SetMatrix(ctx.CurrentMatrix().PreTranslate(devPixelOffsetToUserSpace));
 
   // Convert boaderArea and dirtyRect to user space.
@@ -9285,30 +9262,32 @@ nsDisplayMask::PaintMask(nsDisplayListBu
   return imgParmas.result == mozilla::image::DrawResult::SUCCESS;
 }
 
 LayerState
 nsDisplayMask::GetLayerState(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager,
                              const ContainerLayerParameters& aParameters)
 {
-  if (ShouldPaintOnMaskLayer(aManager)) {
-    return RequiredLayerStateForChildren(aBuilder, aManager, aParameters,
-                                         mList, GetAnimatedGeometryRoot());
+  if (CanPaintOnMaskLayer(aManager)) {
+    LayerState result = RequiredLayerStateForChildren(aBuilder, aManager,
+        aParameters, mList, GetAnimatedGeometryRoot());
+    // When we're not active, FrameLayerBuilder will call PaintAsLayer()
+    // on us during painting. In that case we don't want a mask layer to
+    // be created, because PaintAsLayer() takes care of applying the mask.
+    // So we return LAYER_SVG_EFFECTS instead of LAYER_INACTIVE so that
+    // FrameLayerBuilder doesn't set a mask layer on our layer.
+    return result == LAYER_INACTIVE ? LAYER_SVG_EFFECTS : result;
   }
 
   return LAYER_SVG_EFFECTS;
 }
 
-bool nsDisplayMask::ShouldPaintOnMaskLayer(LayerManager* aManager)
-{
-  if (!aManager->IsCompositingCheap()) {
-    return false;
-  }
-
+bool nsDisplayMask::CanPaintOnMaskLayer(LayerManager* aManager)
+{
   if (!nsSVGIntegrationUtils::IsMaskResourceReady(mFrame)) {
     return false;
   }
 
   if (gfxPrefs::DrawMaskLayer()) {
     return false;
   }
 
@@ -9316,18 +9295,17 @@ bool nsDisplayMask::ShouldPaintOnMaskLay
 }
 
 bool nsDisplayMask::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                       nsRegion* aVisibleRegion)
 {
   // Our children may be made translucent or arbitrarily deformed so we should
   // not allow them to subtract area from aVisibleRegion.
   nsRegion childrenVisible(mVisibleRect);
-  nsRect r = mVisibleRect.Intersect(
-    mList.GetClippedBoundsWithRespectToASR(aBuilder, mActiveScrolledRoot));
+  nsRect r = mVisibleRect.Intersect(mList.GetBounds(aBuilder));
   mList.ComputeVisibilityForSublist(aBuilder, &childrenVisible, r);
   return true;
 }
 
 void
 nsDisplayMask::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                          const nsDisplayItemGeometry* aGeometry,
                                          nsRegion* aInvalidRegion) const
@@ -9364,18 +9342,16 @@ nsDisplayMask::ComputeInvalidationRegion
   }
 }
 
 void
 nsDisplayMask::PaintAsLayer(nsDisplayListBuilder* aBuilder,
                             gfxContext* aCtx,
                             LayerManager* aManager)
 {
-  MOZ_ASSERT(!ShouldPaintOnMaskLayer(aManager));
-
   // Clip the drawing target by mVisibleRect, which contains the visible
   // region of the target frame and its out-of-flow and inflow descendants.
   gfxContext* context = aCtx;
 
   Rect bounds =
     NSRectToRect(mVisibleRect, mFrame->PresContext()->AppUnitsPerDevPixel());
   bounds.RoundOut();
   context->Clip(bounds);
@@ -9427,16 +9403,40 @@ nsDisplayMask::CreateWebRenderCommands(m
 
   if (mask) {
     aBuilder.PopClip(GetClipChain());
   }
 
   return true;
 }
 
+Maybe<nsRect>
+nsDisplayMask::GetClipWithRespectToASR(nsDisplayListBuilder* aBuilder,
+                                       const ActiveScrolledRoot* aASR) const
+{
+  if (const DisplayItemClip* clip = DisplayItemClipChain::ClipForASR(GetClipChain(), aASR)) {
+    return Some(clip->GetClipRect());
+  }
+  // This item does not have a clip with respect to |aASR|. However, we
+  // might still have finite bounds with respect to |aASR|. Check our
+  // children.
+  nsDisplayList* childList = GetSameCoordinateSystemChildren();
+  if (childList) {
+    return Some(childList->GetClippedBoundsWithRespectToASR(aBuilder, aASR));
+  }
+#ifdef DEBUG
+  if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
+    MOZ_ASSERT(false, "item should have finite clip with respect to aASR");
+  }
+#endif
+  return Nothing();
+}
+
+
+
 #ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayMask::PrintEffects(nsACString& aTo)
 {
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
   SVGObserverUtils::EffectProperties effectProperties =
     SVGObserverUtils::GetEffectProperties(firstFrame);
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -2623,16 +2623,20 @@ public:
 
   virtual bool CanBeReused() const { return true; }
 
   virtual nsIFrame* GetDependentFrame()
   {
     return nullptr;
   }
 
+  virtual mozilla::Maybe<nsRect> GetClipWithRespectToASR(
+      nsDisplayListBuilder* aBuilder,
+      const ActiveScrolledRoot* aASR) const;
+
 protected:
   nsDisplayItem() = delete;
 
   typedef bool (*PrefFunc)(void);
   bool ShouldUseAdvancedLayer(LayerManager* aManager, PrefFunc aFunc) const;
   bool CanUseAdvancedLayer(LayerManager* aManager) const;
 
   nsIFrame* mFrame;
@@ -5535,20 +5539,24 @@ public:
     return mDestRects;
   }
 
   virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
                                        mozilla::wr::IpcResourceUpdateQueue& aResources,
                                        const StackingContextHelper& aSc,
                                        mozilla::layers::WebRenderLayerManager* aManager,
                                        nsDisplayListBuilder* aDisplayListBuilder) override;
+
+  virtual mozilla::Maybe<nsRect> GetClipWithRespectToASR(
+      nsDisplayListBuilder* aBuilder,
+      const ActiveScrolledRoot* aASR) const override;
 private:
   // According to mask property and the capability of aManager, determine
-  // whether paint mask onto a dedicate mask layer.
-  bool ShouldPaintOnMaskLayer(LayerManager* aManager);
+  // whether we can paint the mask onto a dedicate mask layer.
+  bool CanPaintOnMaskLayer(LayerManager* aManager);
 
   nsTArray<nsRect> mDestRects;
 };
 
 /**
  * A display item to paint a stacking context with filter effects set by the
  * stacking context root frame's style.
  */
new file mode 100644
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-clip-path-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<style>
+  body {
+    height: 4000px;
+    margin: 0;
+    overflow: hidden;
+  }
+  #clip {
+    position: absolute;
+    top: 450px;
+    left: 300px;
+    background: red;
+    width: 400px;
+    height: 400px;
+    clip-path: inset(0);
+  }
+  #fixed {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: linear-gradient(green, blue);
+  }
+</style>
+<div id="clip">
+  <div id="fixed"></div>
+</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/async-scrolling/position-fixed-inside-clip-path.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+      reftest-displayport-x="0" reftest-displayport-y="0"
+      reftest-displayport-w="800" reftest-displayport-h="2000"
+      reftest-async-scroll-x="0" reftest-async-scroll-y="50">
+<style>
+  body {
+    height: 4000px;
+    margin: 0;
+    overflow: hidden;
+  }
+  #clip {
+    position: absolute;
+    top: 500px;
+    left: 300px;
+    background: red;
+    width: 400px;
+    height: 400px;
+    clip-path: inset(0);
+  }
+  #fixed {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: linear-gradient(green, blue);
+  }
+</style>
+<div id="clip">
+  <div id="fixed"></div>
+</div>
--- a/layout/reftests/async-scrolling/reftest.list
+++ b/layout/reftests/async-scrolling/reftest.list
@@ -28,16 +28,17 @@ fuzzy-if(skiaContent,2,240000) fuzzy-if(
 skip-if(!asyncPan) == sticky-pos-scrollable-1.html sticky-pos-scrollable-1-ref.html
 skip-if(!asyncPan) == sticky-pos-scrollable-2.html sticky-pos-scrollable-2-ref.html
 skip-if(!asyncPan) == sticky-pos-scrollable-3.html sticky-pos-scrollable-3-ref.html
 skip-if(!asyncPan) == fixed-pos-scrollable-1.html fixed-pos-scrollable-1-ref.html
 skip-if(!asyncPan) == culling-1.html culling-1-ref.html
 skip-if(!asyncPan) == position-fixed-iframe-1.html position-fixed-iframe-1-ref.html
 skip-if(!asyncPan) == position-fixed-iframe-2.html position-fixed-iframe-2-ref.html
 fuzzy-if(skiaContent,1,11300) skip-if(!asyncPan) == position-fixed-in-scroll-container.html position-fixed-in-scroll-container-ref.html
+skip-if(!asyncPan) == position-fixed-inside-clip-path.html position-fixed-inside-clip-path-ref.html
 skip-if(!asyncPan) == position-fixed-inside-sticky-1.html position-fixed-inside-sticky-1-ref.html
 skip-if(!asyncPan) == position-fixed-inside-sticky-2.html position-fixed-inside-sticky-2-ref.html
 fuzzy(1,60000) skip-if(!asyncPan) == group-opacity-surface-size-1.html group-opacity-surface-size-1-ref.html
 fuzzy-if(Android,1,197) skip-if(!asyncPan) == position-sticky-transformed.html position-sticky-transformed-ref.html
 skip-if(!asyncPan) == offscreen-prerendered-active-opacity.html offscreen-prerendered-active-opacity-ref.html
 fuzzy-if(Android,6,4) fuzzy-if(skiaContent&&!Android,1,34) skip-if(!asyncPan) == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-ref.html
 fuzzy-if(Android,6,4) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html
 fuzzy-if(Android,6,4) skip == offscreen-clipped-blendmode-3.html offscreen-clipped-blendmode-ref.html # bug 1251588 - wrong AGR on mix-blend-mode item
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/iframe-1-helper.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <style>
+            html, body {
+                margin: 0;
+                padding: 0;
+            }
+        </style>
+    </head>
+    <body>
+        <div style="overflow: auto; width: 150px; height: 200px">
+            <div style="position: sticky; top: 0; width: 100px; height: 100px; background-color: green"></div>
+            <div style="height: 300px; width: 100px"></div>
+        </div>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/iframe-1-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Sticky-positioned item inside a scrollframe inside an iframe</title>
+        <style>
+            html, body {
+                margin: 0;
+                padding: 0;
+            }
+        </style>
+    </head>
+    <body>
+        <div style="overflow: auto; margin-top: 100px; width: 150px; height: 200px">
+            <div style="width: 100px; height: 100px; background-color: green"></div>
+            <div style="height: 300px; width: 100px"></div>
+        </div>
+    </body>
+</html>
+    </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/position-sticky/iframe-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Sticky-positioned item inside a scrollframe inside an iframe</title>
+        <style>
+            html, body {
+                margin: 0;
+                padding: 0;
+            }
+        </style>
+    </head>
+    <body>
+        <iframe src="iframe-1-helper.html" style="margin-top: 100px; border: none; height: 300px"></iframe>
+    </body>
+</html>
--- a/layout/reftests/position-sticky/reftest.list
+++ b/layout/reftests/position-sticky/reftest.list
@@ -44,8 +44,9 @@ skip-if(!asyncPan) == inline-4.html inli
 fails == column-contain-1a.html column-contain-1-ref.html
 == column-contain-1b.html column-contain-1-ref.html
 == column-contain-2.html column-contain-2-ref.html
 == block-in-inline-1.html block-in-inline-1-ref.html
 fuzzy-if(skiaContent,1,22) fuzzy-if(winWidget&&!layersGPUAccelerated,116,1320) fuzzy-if(Android,8,1533) == block-in-inline-2.html block-in-inline-2-ref.html
 fuzzy-if(Android,8,630) fuzzy-if(OSX,1,11) fuzzy-if(skiaContent,1,220) fuzzy-if(winWidget&&!layersGPUAccelerated,116,1320) == block-in-inline-3.html block-in-inline-3-ref.html
 == block-in-inline-continuations.html block-in-inline-continuations-ref.html
 fuzzy-if(winWidget&&!layersGPUAccelerated,140,140) == inner-table-1.html inner-table-1-ref.html
+== iframe-1.html iframe-1-ref.html
--- a/layout/reftests/svg/clipPath-polygon-elementFromPoint-01.svg
+++ b/layout/reftests/svg/clipPath-polygon-elementFromPoint-01.svg
@@ -16,21 +16,21 @@
   <script>
     function testElementFromPoint() {
       let inCount = 0, outCount = 0, inElem, outElem;
       document.getElementById("in").style.fill = "red";
       document.getElementById("out").style.fill = "blue";
 
       inElem = document.elementFromPoint(100, 100);
       if (inElem.style.fill == "red") { ++inCount; }
-      inElem = document.elementFromPoint(150, 100);
+      inElem = document.elementFromPoint(149, 100);
       if (inElem.style.fill == "red") { ++inCount; }
-      inElem = document.elementFromPoint(150, 150);
+      inElem = document.elementFromPoint(149, 149);
       if (inElem.style.fill == "red") { ++inCount; }
-      inElem = document.elementFromPoint(100, 150);
+      inElem = document.elementFromPoint(100, 149);
       if (inElem.style.fill == "red") { ++inCount; }
       if (inCount == 4) { document.getElementById("in").style.fill = "lime"; }
 
       outElem = document.elementFromPoint(99, 100);
       if (outElem.style.fill == "blue") { ++outCount; }
       outElem = document.elementFromPoint(150, 99);
       if (outElem.style.fill == "blue") { ++outCount; }
       outElem = document.elementFromPoint(151, 150);
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -444,16 +444,17 @@ public:
 
   // Returns true if a restyle of the document is needed due to cloning
   // sheet inners.
   bool EnsureUniqueInnerOnCSSSheets();
 
   // Called by StyleSheet::EnsureUniqueInner to let us know it cloned
   // its inner.
   void SetNeedsRestyleAfterEnsureUniqueInner() {
+    MOZ_ASSERT(!IsForXBL(), "Should not be cloning things for XBL stylesheet");
     mNeedsRestyleAfterEnsureUniqueInner = true;
   }
 
   // Returns the style rule map.
   ServoStyleRuleMap* StyleRuleMap();
 
   // Return whether this is the last PresContext which uses this XBL styleset.
   bool IsPresContextChanged(nsPresContext* aPresContext) const {
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -388,25 +388,20 @@ ServoStyleSheet::Clone(StyleSheet* aClon
     static_cast<ServoStyleSheet*>(aCloneParent),
     aCloneOwnerRule,
     aCloneDocument,
     aCloneOwningNode);
   return clone.forget();
 }
 
 ServoCSSRuleList*
-ServoStyleSheet::GetCssRulesInternal(bool aRequireUniqueInner)
+ServoStyleSheet::GetCssRulesInternal()
 {
   if (!mRuleList) {
-    MOZ_ASSERT(aRequireUniqueInner || !mDocument,
-               "Not requiring unique inner for stylesheet associated "
-               "with document may have undesired behavior");
-    if (aRequireUniqueInner) {
-      EnsureUniqueInner();
-    }
+    EnsureUniqueInner();
 
     RefPtr<ServoCssRules> rawRules =
       Servo_StyleSheet_GetRules(Inner()->mContents).Consume();
     MOZ_ASSERT(rawRules);
     mRuleList = new ServoCSSRuleList(rawRules.forget(), this);
   }
   return mRuleList;
 }
--- a/layout/style/ServoStyleSheet.h
+++ b/layout/style/ServoStyleSheet.h
@@ -115,17 +115,17 @@ public:
     nsINode* aCloneOwningNode) const final;
 
   // nsICSSLoaderObserver interface
   NS_IMETHOD StyleSheetLoaded(StyleSheet* aSheet, bool aWasAlternate,
                               nsresult aStatus) final;
 
   // Internal GetCssRules method which do not have security check and
   // completelness check.
-  ServoCSSRuleList* GetCssRulesInternal(bool aRequireUniqueInner = true);
+  ServoCSSRuleList* GetCssRulesInternal();
 
   // Returns the stylesheet's Servo origin as an OriginFlags value.
   OriginFlags GetOrigin();
 
 protected:
   virtual ~ServoStyleSheet();
 
   void LastRelease();
--- a/layout/style/StyleSheet.cpp
+++ b/layout/style/StyleSheet.cpp
@@ -449,16 +449,27 @@ StyleSheet::EnsureUniqueInner()
   MOZ_ASSERT(mInner->mSheets.Length() != 0,
              "unexpected number of outers");
   mDirty = true;
 
   if (HasUniqueInner()) {
     // already unique
     return;
   }
+  // If this stylesheet is for XBL with Servo, don't bother cloning
+  // it, as it may break ServoStyleRuleMap. XBL stylesheets are not
+  // supposed to change anyway.
+  // The mDocument check is used as a fast reject path because no
+  // XBL stylesheets would have associated document, but in normal
+  // cases, content stylesheets should usually have one.
+  if (!mDocument && IsServo() &&
+      mStyleSets.Length() == 1 &&
+      mStyleSets[0]->AsServo()->IsForXBL()) {
+    return;
+  }
 
   StyleSheetInfo* clone = mInner->CloneFor(this);
   MOZ_ASSERT(clone);
   mInner->RemoveSheet(this);
   mInner = clone;
 
   if (CSSStyleSheet* geckoSheet = GetAsGecko()) {
     // Ensure we're using the new rules.
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1413361.html
@@ -0,0 +1,8 @@
+<script>
+function go() {
+  window.getSelection().selectAllChildren(document.body.firstChild);
+  document.createElement("body").aLink = "-moz-mac-menuselect";
+  window.getSelection().getRangeAt(0).getClientRects();
+}
+</script>
+<body onload=go()>
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -254,8 +254,9 @@ load 1404324-3.html
 load 1404057.html
 load 1409502.html
 load 1409931.html
 load 1410226-1.html
 load 1410226-2.html
 load 1411143.html
 load 1411478.html
 load 1413288.html
+load 1413361.html
--- a/layout/svg/SVGGeometryFrame.cpp
+++ b/layout/svg/SVGGeometryFrame.cpp
@@ -538,17 +538,20 @@ SVGGeometryFrame::GetBBoxContribution(co
     RefPtr<gfxASurface> refSurf =
       gfxPlatform::GetPlatform()->ScreenReferenceSurface();
     tmpDT = gfxPlatform::GetPlatform()->
       CreateDrawTargetForSurface(refSurf, IntSize(1, 1));
 #else
     tmpDT = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
 #endif
 
-    FillRule fillRule = nsSVGUtils::ToFillRule(StyleSVG()->mFillRule);
+    FillRule fillRule = nsSVGUtils::ToFillRule(
+        (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD)
+      ? StyleSVG()->mClipRule
+      : StyleSVG()->mFillRule);
     RefPtr<Path> pathInUserSpace = element->GetOrBuildPath(*tmpDT, fillRule);
     if (!pathInUserSpace) {
       return bbox;
     }
     RefPtr<Path> pathInBBoxSpace;
     if (aToBBoxUserspace.IsIdentity()) {
       pathInBBoxSpace = pathInUserSpace;
     } else {
--- a/layout/svg/nsCSSClipPathInstance.cpp
+++ b/layout/svg/nsCSSClipPathInstance.cpp
@@ -64,16 +64,31 @@ nsCSSClipPathInstance::HitTestBasicShape
   RefPtr<DrawTarget> drawTarget =
     gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
   RefPtr<Path> path = instance.CreateClipPath(drawTarget);
   float pixelRatio = float(nsPresContext::AppUnitsPerCSSPixel()) /
                      aFrame->PresContext()->AppUnitsPerDevPixel();
   return path->ContainsPoint(ToPoint(aPoint) * pixelRatio, Matrix());
 }
 
+/* static */ Rect
+nsCSSClipPathInstance::GetBoundingRectForBasicShapeClip(nsIFrame* aFrame,
+                                                        const StyleShapeSource& aClipPathStyle)
+{
+  MOZ_ASSERT(aClipPathStyle.GetType() == StyleShapeSourceType::Shape ||
+             aClipPathStyle.GetType() == StyleShapeSourceType::Box);
+
+  nsCSSClipPathInstance instance(aFrame, aClipPathStyle);
+
+  RefPtr<DrawTarget> drawTarget =
+    gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
+  RefPtr<Path> path = instance.CreateClipPath(drawTarget);
+  return path->GetBounds();
+}
+
 already_AddRefed<Path>
 nsCSSClipPathInstance::CreateClipPath(DrawTarget* aDrawTarget)
 {
   nsRect r =
     nsLayoutUtils::ComputeGeometryBox(mTargetFrame,
                                       mClipPathStyle.GetReferenceBox());
 
   if (mClipPathStyle.GetType() != StyleShapeSourceType::Shape) {
--- a/layout/svg/nsCSSClipPathInstance.h
+++ b/layout/svg/nsCSSClipPathInstance.h
@@ -15,23 +15,27 @@ class nsIFrame;
 class gfxContext;
 
 namespace mozilla {
 
 class nsCSSClipPathInstance
 {
   typedef mozilla::gfx::DrawTarget DrawTarget;
   typedef mozilla::gfx::Path Path;
+  typedef mozilla::gfx::Rect Rect;
 
 public:
   static void ApplyBasicShapeClip(gfxContext& aContext,
                                   nsIFrame* aFrame);
   // aPoint is in CSS pixels.
   static bool HitTestBasicShapeClip(nsIFrame* aFrame,
                                     const gfxPoint& aPoint);
+
+  static Rect GetBoundingRectForBasicShapeClip(nsIFrame* aFrame,
+                                               const StyleShapeSource& aClipPathStyle);
 private:
   explicit nsCSSClipPathInstance(nsIFrame* aFrame,
                                  const StyleShapeSource aClipPathStyle)
     : mTargetFrame(aFrame)
     , mClipPathStyle(aClipPathStyle)
   {
   }
 
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -475,22 +475,23 @@ nsSVGClipPathFrame::GetClipPathTransform
 
 SVGBBox
 nsSVGClipPathFrame::GetBBoxForClipPathFrame(const SVGBBox &aBBox,
                                             const gfxMatrix &aMatrix)
 {
   nsIContent* node = GetContent()->GetFirstChild();
   SVGBBox unionBBox, tmpBBox;
   for (; node; node = node->GetNextSibling()) {
-    nsIFrame *frame =
-      static_cast<nsSVGElement*>(node)->GetPrimaryFrame();
+    nsSVGElement* svgNode = static_cast<nsSVGElement*>(node);
+    nsIFrame* frame = svgNode->GetPrimaryFrame();
     if (frame) {
       nsSVGDisplayableFrame* svg = do_QueryFrame(frame);
       if (svg) {
-        tmpBBox = svg->GetBBoxContribution(mozilla::gfx::ToMatrix(aMatrix),
+        gfxMatrix matrix = svgNode->PrependLocalTransformsTo(aMatrix, eUserSpaceToParent);
+        tmpBBox = svg->GetBBoxContribution(mozilla::gfx::ToMatrix(matrix),
                                            nsSVGUtils::eBBoxIncludeFill);
         SVGObserverUtils::EffectProperties effectProperties =
                               SVGObserverUtils::GetEffectProperties(frame);
         if (effectProperties.HasNoOrValidClipPath()) {
           nsSVGClipPathFrame *clipPathFrame =
             effectProperties.GetClipPathFrame();
           if (clipPathFrame) {
             tmpBBox = clipPathFrame->GetBBoxForClipPathFrame(tmpBBox, aMatrix);
--- a/media/ffvpx/config_common.h
+++ b/media/ffvpx/config_common.h
@@ -1,4 +1,14 @@
 #ifndef MOZ_FFVPX_CONFIG_COMMON_H
 #define MOZ_FFVPX_CONFIG_COMMON_H
 #include "defaults_disabled.h"
+
+#ifdef YASM_MISSING_AVX2
+#undef HAVE_AVX2
+#undef HAVE_AVX2_INTERNAL
+#undef HAVE_AVX2_EXTERNAL
+#define HAVE_AVX2 0
+#define HAVE_AVX2_INTERNAL 0
+#define HAVE_AVX2_EXTERNAL 0
 #endif
+
+#endif
--- a/media/ffvpx/ffvpxcommon.mozbuild
+++ b/media/ffvpx/ffvpxcommon.mozbuild
@@ -5,16 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # Add assembler flags and includes
 ASFLAGS += CONFIG['FFVPX_ASFLAGS']
 ASFLAGS += ['-I%s/media/ffvpx' % TOPSRCDIR]
 
 if CONFIG['FFVPX_ASFLAGS']:
     USE_YASM = True
+
     if CONFIG['OS_ARCH'] == 'WINNT':
        # Fix inline symbols and math defines for windows.
         DEFINES['_USE_MATH_DEFINES'] = True
         DEFINES['inline'] = "__inline"
         # 32-bit windows need to prefix symbols with an underscore.
         if CONFIG['CPU_ARCH'] == 'x86':
             ASFLAGS += ['-DPREFIX']
             ASFLAGS += ['-Pconfig_win32.asm']
@@ -27,16 +28,25 @@ if CONFIG['FFVPX_ASFLAGS']:
             '-DPREFIX'
         ]
     else:
         # Default to unix, similar to how ASFLAGS setup works in configure.in
         ASFLAGS += ['-Pconfig_unix64.asm']
     # default disabled components
     ASFLAGS += ['-Pdefaults_disabled.asm']
 
+    if int(CONFIG['YASM_MAJOR_VERSION']) == 1 and int(CONFIG['YASM_MINOR_VERSION']) < 2:
+        DEFINES['YASM_MISSING_AVX2'] = True
+        ASFLAGS += [
+            '-DHAVE_AVX2=0',
+            '-DHAVE_AVX2_INTERNAL=0',
+            '-DHAVE_AVX2_EXTERNAL=0',
+        ]
+
+
 LOCAL_INCLUDES += ['/media/ffvpx']
 
 # We allow warnings for third-party code that can be updated from upstream.
 AllowCompilerWarnings()
 
 # Suppress warnings in third-party code.
 if CONFIG['GNU_CC']:
     CFLAGS += [
new file mode 100644
--- /dev/null
+++ b/memory/build/Makefile.in
@@ -0,0 +1,9 @@
+# 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/.
+
+# Workaround for alignment problems in gcov code. See
+# https://bugzilla.mozilla.org/show_bug.cgi?id=1413570#c2.
+ifeq ($(CPU_ARCH),x86)
+PROFILE_GEN_CFLAGS += -mno-sse2
+endif
--- a/memory/build/fallback.cpp
+++ b/memory/build/fallback.cpp
@@ -6,43 +6,43 @@
 
 #include "mozmemory.h"
 #include "mozjemalloc.h"
 #include <stdlib.h>
 
 #ifndef HAVE_MEMALIGN
 namespace {
 
-inline void* memalign(size_t aAlignment, size_t aSize)
+inline void*
+memalign(size_t aAlignment, size_t aSize)
 {
 #ifdef XP_WIN
   return _aligned_malloc(aSize, aAlignment);
 #else
   void* ret;
   if (posix_memalign(&ret, aAlignment, aSize) != 0) {
     return nullptr;
   }
   return ret;
 #endif
 }
-
 }
 #endif
 
-struct SystemMalloc {
-#define MALLOC_DECL(name, return_type, ...) \
-  static inline return_type \
-  name(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
-  { \
-    return ::name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
+struct SystemMalloc
+{
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  static inline return_type name(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__))       \
+  {                                                                            \
+    return ::name(ARGS_HELPER(ARGS, ##__VA_ARGS__));                           \
   }
 #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC_BASE
 #include "malloc_decls.h"
 };
 
-#define MALLOC_DECL(name, return_type, ...) \
-  MOZ_JEMALLOC_API return_type \
-  name(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
-  { \
-    return DummyArenaAllocator<SystemMalloc>::name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  MOZ_JEMALLOC_API return_type name(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__))    \
+  {                                                                            \
+    return DummyArenaAllocator<SystemMalloc>::name(                            \
+      ARGS_HELPER(ARGS, ##__VA_ARGS__));                                       \
   }
 #define MALLOC_FUNCS MALLOC_FUNCS_ARENA
 #include "malloc_decls.h"
--- a/memory/build/malloc_decls.h
+++ b/memory/build/malloc_decls.h
@@ -1,144 +1,131 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
+ * 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/. */
 
-/*
- * Helper header to declare all the supported malloc functions.
- * MALLOC_DECL arguments are:
- *   - function name
- *   - return type
- *   - argument types
- */
+// Helper header to declare all the supported malloc functions.
+// MALLOC_DECL arguments are:
+//   - function name
+//   - return type
+//   - argument types
 
 #ifndef malloc_decls_h
-#  define malloc_decls_h
+#define malloc_decls_h
 
-#  include "mozjemalloc_types.h"
+#include "mozjemalloc_types.h"
 
-#  define MALLOC_FUNCS_MALLOC_BASE 1
-#  define MALLOC_FUNCS_MALLOC_EXTRA 2
-#  define MALLOC_FUNCS_MALLOC (MALLOC_FUNCS_MALLOC_BASE | \
-                               MALLOC_FUNCS_MALLOC_EXTRA)
-#  define MALLOC_FUNCS_JEMALLOC 4
-#  define MALLOC_FUNCS_INIT 8
-#  define MALLOC_FUNCS_BRIDGE 16
-#  define MALLOC_FUNCS_ARENA_BASE 32
-#  define MALLOC_FUNCS_ARENA_ALLOC 64
-#  define MALLOC_FUNCS_ARENA (MALLOC_FUNCS_ARENA_BASE | \
-                              MALLOC_FUNCS_ARENA_ALLOC)
-#  define MALLOC_FUNCS_ALL (MALLOC_FUNCS_INIT | MALLOC_FUNCS_BRIDGE | \
-                            MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC | \
-                            MALLOC_FUNCS_ARENA)
+#define MALLOC_FUNCS_MALLOC_BASE 1
+#define MALLOC_FUNCS_MALLOC_EXTRA 2
+#define MALLOC_FUNCS_MALLOC                                                    \
+  (MALLOC_FUNCS_MALLOC_BASE | MALLOC_FUNCS_MALLOC_EXTRA)
+#define MALLOC_FUNCS_JEMALLOC 4
+#define MALLOC_FUNCS_INIT 8
+#define MALLOC_FUNCS_BRIDGE 16
+#define MALLOC_FUNCS_ARENA_BASE 32
+#define MALLOC_FUNCS_ARENA_ALLOC 64
+#define MALLOC_FUNCS_ARENA (MALLOC_FUNCS_ARENA_BASE | MALLOC_FUNCS_ARENA_ALLOC)
+#define MALLOC_FUNCS_ALL                                                       \
+  (MALLOC_FUNCS_INIT | MALLOC_FUNCS_BRIDGE | MALLOC_FUNCS_MALLOC |             \
+   MALLOC_FUNCS_JEMALLOC | MALLOC_FUNCS_ARENA)
 
-#endif /* malloc_decls_h */
+#endif // malloc_decls_h
 
 #ifndef MALLOC_FUNCS
-#  define MALLOC_FUNCS (MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC | \
-                        MALLOC_FUNCS_ARENA)
+#define MALLOC_FUNCS                                                           \
+  (MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC | MALLOC_FUNCS_ARENA)
 #endif
 
 #ifdef MALLOC_DECL
-#  if MALLOC_FUNCS & MALLOC_FUNCS_INIT
-MALLOC_DECL(init, void, const malloc_table_t *)
-#  endif
-#  if MALLOC_FUNCS & MALLOC_FUNCS_BRIDGE
+#if MALLOC_FUNCS & MALLOC_FUNCS_INIT
+MALLOC_DECL(init, void, const malloc_table_t*)
+#endif
+#if MALLOC_FUNCS & MALLOC_FUNCS_BRIDGE
 MALLOC_DECL(get_bridge, struct ReplaceMallocBridge*)
-#  endif
-#  if MALLOC_FUNCS & MALLOC_FUNCS_MALLOC_BASE
-MALLOC_DECL(malloc, void *, size_t)
-MALLOC_DECL(calloc, void *, size_t, size_t)
-MALLOC_DECL(realloc, void *, void *, size_t)
-MALLOC_DECL(free, void, void *)
-MALLOC_DECL(memalign, void *, size_t, size_t)
-#  endif
-#  if MALLOC_FUNCS & MALLOC_FUNCS_MALLOC_EXTRA
-MALLOC_DECL(posix_memalign, int, void **, size_t, size_t)
-MALLOC_DECL(aligned_alloc, void *, size_t, size_t)
-MALLOC_DECL(valloc, void *, size_t)
+#endif
+#if MALLOC_FUNCS & MALLOC_FUNCS_MALLOC_BASE
+MALLOC_DECL(malloc, void*, size_t)
+MALLOC_DECL(calloc, void*, size_t, size_t)
+MALLOC_DECL(realloc, void*, void*, size_t)
+MALLOC_DECL(free, void, void*)
+MALLOC_DECL(memalign, void*, size_t, size_t)
+#endif
+#if MALLOC_FUNCS & MALLOC_FUNCS_MALLOC_EXTRA
+MALLOC_DECL(posix_memalign, int, void**, size_t, size_t)
+MALLOC_DECL(aligned_alloc, void*, size_t, size_t)
+MALLOC_DECL(valloc, void*, size_t)
 MALLOC_DECL(malloc_usable_size, size_t, usable_ptr_t)
 MALLOC_DECL(malloc_good_size, size_t, size_t)
-#  endif
-#  if MALLOC_FUNCS & MALLOC_FUNCS_JEMALLOC
-MALLOC_DECL(jemalloc_stats, void, jemalloc_stats_t *)
-/*
- * On some operating systems (Mac), we use madvise(MADV_FREE) to hand pages
- * back to the operating system.  On Mac, the operating system doesn't take
- * this memory back immediately; instead, the OS takes it back only when the
- * machine is running out of physical memory.
- *
- * This is great from the standpoint of efficiency, but it makes measuring our
- * actual RSS difficult, because pages which we've MADV_FREE'd shouldn't count
- * against our RSS.
- *
- * This function explicitly purges any MADV_FREE'd pages from physical memory,
- * causing our reported RSS match the amount of memory we're actually using.
- *
- * Note that this call is expensive in two ways.  First, it may be slow to
- * execute, because it may make a number of slow syscalls to free memory.  This
- * function holds the big jemalloc locks, so basically all threads are blocked
- * while this function runs.
- *
- * This function is also expensive in that the next time we go to access a page
- * which we've just explicitly decommitted, the operating system has to attach
- * to it a physical page!  If we hadn't run this function, the OS would have
- * less work to do.
- *
- * If MALLOC_DOUBLE_PURGE is not defined, this function does nothing.
- */
+#endif
+#if MALLOC_FUNCS & MALLOC_FUNCS_JEMALLOC
+MALLOC_DECL(jemalloc_stats, void, jemalloc_stats_t*)
+
+// On some operating systems (Mac), we use madvise(MADV_FREE) to hand pages
+// back to the operating system.  On Mac, the operating system doesn't take
+// this memory back immediately; instead, the OS takes it back only when the
+// machine is running out of physical memory.
+//
+// This is great from the standpoint of efficiency, but it makes measuring our
+// actual RSS difficult, because pages which we've MADV_FREE'd shouldn't count
+// against our RSS.
+//
+// This function explicitly purges any MADV_FREE'd pages from physical memory,
+// causing our reported RSS match the amount of memory we're actually using.
+//
+// Note that this call is expensive in two ways.  First, it may be slow to
+// execute, because it may make a number of slow syscalls to free memory.  This
+// function holds the big jemalloc locks, so basically all threads are blocked
+// while this function runs.
+//
+// This function is also expensive in that the next time we go to access a page
+// which we've just explicitly decommitted, the operating system has to attach
+// to it a physical page!  If we hadn't run this function, the OS would have
+// less work to do.
+//
+// If MALLOC_DOUBLE_PURGE is not defined, this function does nothing.
 MALLOC_DECL(jemalloc_purge_freed_pages, void)
 
-/*
- * Free all unused dirty pages in all arenas. Calling this function will slow
- * down subsequent allocations so it is recommended to use it only when
- * memory needs to be reclaimed at all costs (see bug 805855). This function
- * provides functionality similar to mallctl("arenas.purge") in jemalloc 3.
- */
+// Free all unused dirty pages in all arenas. Calling this function will slow
+// down subsequent allocations so it is recommended to use it only when
+// memory needs to be reclaimed at all costs (see bug 805855). This function
+// provides functionality similar to mallctl("arenas.purge") in jemalloc 3.
 MALLOC_DECL(jemalloc_free_dirty_pages, void)
 
-/*
- * Opt in or out of a thread local arena (bool argument is whether to opt-in
- * (true) or out (false)).
- */
+// Opt in or out of a thread local arena (bool argument is whether to opt-in
+// (true) or out (false)).
 MALLOC_DECL(jemalloc_thread_local_arena, void, bool)
 
-/*
- * Provide information about any allocation enclosing the given address.
- */
+// Provide information about any allocation enclosing the given address.
 MALLOC_DECL(jemalloc_ptr_info, void, const void*, jemalloc_ptr_info_t*)
-#  endif
+#endif
 
-#  if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_BASE
-/*
- * Creates a separate arena, and returns its id, valid to use with moz_arena_*
- * functions.
- */
+#if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_BASE
+
+// Creates a separate arena, and returns its id, valid to use with moz_arena_*
+// functions.
 MALLOC_DECL(moz_create_arena, arena_id_t)
 
-/*
- * Dispose of the given arena. Subsequent uses of the arena will fail.
- */
+// Dispose of the given arena. Subsequent uses of the arena will fail.
 MALLOC_DECL(moz_dispose_arena, void, arena_id_t)
-#  endif
+#endif
 
-#  if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_ALLOC
-/*
- * Same as the functions without the moz_arena_ prefix, but using arenas
- * created with moz_create_arena.
- * The contract, even if not enforced at runtime in some configurations,
- * is that moz_arena_realloc and moz_arena_free will crash if the wrong
- * arena id is given. All functions will crash if the arena id is invalid.
- * Although discouraged, plain realloc and free can still be used on
- * pointers allocated with these functions. Realloc will properly keep
- * new pointers in the same arena as the original.
- */
+#if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_ALLOC
+// Same as the functions without the moz_arena_ prefix, but using arenas
+// created with moz_create_arena.
+// The contract, even if not enforced at runtime in some configurations,
+// is that moz_arena_realloc and moz_arena_free will crash if the wrong
+// arena id is given. All functions will crash if the arena id is invalid.
+// Although discouraged, plain realloc and free can still be used on
+// pointers allocated with these functions. Realloc will properly keep
+// new pointers in the same arena as the original.
 MALLOC_DECL(moz_arena_malloc, void*, arena_id_t, size_t)
 MALLOC_DECL(moz_arena_calloc, void*, arena_id_t, size_t, size_t)
 MALLOC_DECL(moz_arena_realloc, void*, arena_id_t, void*, size_t)
 MALLOC_DECL(moz_arena_free, void, arena_id_t, void*)
 MALLOC_DECL(moz_arena_memalign, void*, arena_id_t, size_t, size_t)
-#  endif
+#endif
 
-#endif /* MALLOC_DECL */
+#endif // MALLOC_DECL
 
 #undef MALLOC_DECL
 #undef MALLOC_FUNCS
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -1,10 +1,10 @@
-/* -*- Mode: C; tab-width: 8; c-basic-offset: 8; indent-tabs-mode: t -*- */
-/* vim:set softtabstop=8 shiftwidth=8 noet: */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 // Portions of this file were originally under the following license:
 //
 // Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
 // All rights reserved.
@@ -102,29 +102,55 @@
 //
 //   Huge : Each allocation is backed by a dedicated contiguous set of chunks.
 //          Metadata are stored in a separate red-black tree.
 //
 // *****************************************************************************
 
 #include "mozmemory_wrap.h"
 #include "mozjemalloc.h"
+#include "mozjemalloc_types.h"
+
+#include <cstring>
+#include <cerrno>
+#ifdef XP_WIN
+#include <io.h>
+#include <windows.h>
+#else
+#include <sys/mman.h>
+#include <unistd.h>
+#endif
+#ifdef XP_DARWIN
+#include <libkern/OSAtomic.h>
+#include <mach/mach_init.h>
+#include <mach/vm_map.h>
+#endif
+
 #include "mozilla/Atomics.h"
 #include "mozilla/Alignment.h"
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/DoublyLinkedList.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/Sprintf.h"
+// Note: MozTaggedAnonymousMmap() could call an LD_PRELOADed mmap
+// instead of the one defined here; use only MozTagAnonymousMemory().
+#include "mozilla/TaggedAnonymousMemory.h"
+#include "mozilla/ThreadLocal.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Unused.h"
 #include "mozilla/fallible.h"
+#include "rb.h"
 #include "Utils.h"
 
+using namespace mozilla;
+
 // On Linux, we use madvise(MADV_DONTNEED) to release memory back to the
 // operating system.  If we release 1MB of live pages with MADV_DONTNEED, our
 // RSS will decrease by 1MB (almost) immediately.
 //
 // On Mac, we use madvise(MADV_FREE).  Unlike MADV_DONTNEED on Linux, MADV_FREE
 // on Mac doesn't cause the OS to release the specified pages immediately; the
 // OS keeps them in our process until the machine comes under memory pressure.
 //
@@ -139,36 +165,21 @@
 //
 // The jemalloc_purge_freed_pages definition in memory/build/mozmemory.h needs
 // to be adjusted if MALLOC_DOUBLE_PURGE is ever enabled on Linux.
 
 #ifdef XP_DARWIN
 #define MALLOC_DOUBLE_PURGE
 #endif
 
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <algorithm>
-
-using namespace mozilla;
+#ifdef XP_WIN
+#define MALLOC_DECOMMIT
+#endif
 
 #ifdef XP_WIN
-
-// Some defines from the CRT internal headers that we need here.
-#define _CRT_SPINCOUNT 5000
-#include <io.h>
-#include <windows.h>
-#include <intrin.h>
-
 #define STDERR_FILENO 2
 
 // Implement getenv without using malloc.
 static char mozillaMallocOptionsBuf[64];
 
 #define getenv xgetenv
 static char*
 getenv(const char* name)
@@ -176,69 +187,23 @@ getenv(const char* name)
 
   if (GetEnvironmentVariableA(
         name, mozillaMallocOptionsBuf, sizeof(mozillaMallocOptionsBuf)) > 0) {
     return mozillaMallocOptionsBuf;
   }
 
   return nullptr;
 }
-
-#if defined(_WIN64)
-typedef long long ssize_t;
-#else
-typedef long ssize_t;
-#endif
-
-#define MALLOC_DECOMMIT
 #endif
 
 #ifndef XP_WIN
-#ifndef XP_SOLARIS
-#include <sys/cdefs.h>
-#endif
-#include <sys/mman.h>
 #ifndef MADV_FREE
 #define MADV_FREE MADV_DONTNEED
 #endif
-#ifndef MAP_NOSYNC
-#define MAP_NOSYNC 0
 #endif
-#include <sys/param.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#if !defined(XP_SOLARIS) && !defined(ANDROID)
-#include <sys/sysctl.h>
-#endif
-#include <sys/uio.h>
-
-#include <errno.h>
-#include <limits.h>
-#include <pthread.h>
-#include <sched.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifdef XP_DARWIN
-#include <libkern/OSAtomic.h>
-#include <mach/mach_error.h>
-#include <mach/mach_init.h>
-#include <mach/vm_map.h>
-#include <malloc/malloc.h>
-#endif
-
-#endif
-
-#include "mozilla/ThreadLocal.h"
-#include "mozjemalloc_types.h"
 
 // Some tools, such as /dev/dsp wrappers, LD_PRELOAD libraries that
 // happen to override mmap() and call dlsym() from their overridden
 // mmap(). The problem is that dlsym() calls malloc(), and this ends
 // up in a dead lock in jemalloc.
 // On these systems, we prefer to directly use the system call.
 // We do that for Linux systems and kfreebsd with GNU userland.
 // Note sanity checks are not done (alignment of offset, ...) because
@@ -278,29 +243,19 @@ static inline void*
 #endif
 #endif
 }
 #define mmap _mmap
 #define munmap(a, l) syscall(SYS_munmap, a, l)
 #endif
 #endif
 
-// Size of stack-allocated buffer passed to strerror_r().
-#define STRERROR_BUF 64
-
 // Minimum alignment of non-tiny allocations is 2^QUANTUM_2POW_MIN bytes.
 #define QUANTUM_2POW_MIN 4
 
-#include "rb.h"
-
-// sizeof(int) == (1U << SIZEOF_INT_2POW).
-#ifndef SIZEOF_INT_2POW
-#define SIZEOF_INT_2POW 2
-#endif
-
 // Size and alignment of memory chunks that are allocated by the OS's virtual
 // memory system.
 #define CHUNK_2POW_DEFAULT 20
 // Maximum number of dirty pages per arena.
 #define DIRTY_MAX_DEFAULT (1U << 8)
 
 static size_t opt_dirty_max = DIRTY_MAX_DEFAULT;
 
@@ -1060,17 +1015,18 @@ struct ArenaTreeTrait
 //   used by the standard API.
 class ArenaCollection
 {
 public:
   bool Init()
   {
     mArenas.Init();
     mPrivateArenas.Init();
-    mDefaultArena = mLock.Init() ? CreateArena(/* IsPrivate = */ false) : nullptr;
+    mDefaultArena =
+      mLock.Init() ? CreateArena(/* IsPrivate = */ false) : nullptr;
     if (mDefaultArena) {
       // arena_t constructor sets this to a lower value for thread local
       // arenas; Reset to the default value for the main arena.
       mDefaultArena->mMaxDirty = opt_dirty_max;
     }
     return bool(mDefaultArena);
   }
 
@@ -1097,27 +1053,24 @@ public:
     {
     }
 
     Item<Iterator> begin()
     {
       return Item<Iterator>(this, *Tree::Iterator::begin());
     }
 
-    Item<Iterator> end()
-    {
-      return Item<Iterator>(this, nullptr);
-    }
+    Item<Iterator> end() { return Item<Iterator>(this, nullptr); }
 
     Tree::TreeNode* Next()
     {
       Tree::TreeNode* result = Tree::Iterator::Next();
       if (!result && mNextTree) {
-	new (this) Iterator(mNextTree, nullptr);
-	result = reinterpret_cast<Tree::TreeNode*>(*Tree::Iterator::begin());
+        new (this) Iterator(mNextTree, nullptr);
+        result = reinterpret_cast<Tree::TreeNode*>(*Tree::Iterator::begin());
       }
       return result;
     }
 
   private:
     Tree* mNextTree;
   };
 
@@ -1282,22 +1235,16 @@ static void
 template<typename... Args>
 static void
 _malloc_message(const char* p, Args... args)
 {
   _malloc_message(p);
   _malloc_message(args...);
 }
 
-#include "mozilla/Assertions.h"
-#include "mozilla/Attributes.h"
-#include "mozilla/TaggedAnonymousMemory.h"
-  // Note: MozTaggedAnonymousMmap() could call an LD_PRELOADed mmap
-  // instead of the one defined here; use only MozTagAnonymousMemory().
-
 #ifdef ANDROID
 // Android's pthread.h does not declare pthread_atfork() until SDK 21.
 extern "C" MOZ_EXPORT int
 pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
 #endif
 
 // ***************************************************************************
 // Begin mutex.  We can't use normal pthread mutexes in all places, because
@@ -1305,17 +1252,17 @@ pthread_atfork(void (*)(void), void (*)(
 // cases. We also can't use constructors, because for statics, they would fire
 // after the first use of malloc, resetting the locks.
 
 // Initializes a mutex. Returns whether initialization succeeded.
 bool
 Mutex::Init()
 {
 #if defined(XP_WIN)
-  if (!InitializeCriticalSectionAndSpinCount(&mMutex, _CRT_SPINCOUNT)) {
+  if (!InitializeCriticalSectionAndSpinCount(&mMutex, 5000)) {
     return false;
   }
 #elif defined(XP_DARWIN)
   mMutex = OS_SPINLOCK_INIT;
 #elif defined(XP_LINUX) && !defined(ANDROID)
   pthread_mutexattr_t attr;
   if (pthread_mutexattr_init(&attr) != 0) {
     return false;
@@ -1588,17 +1535,17 @@ pages_unmap(void* aAddr, size_t aSize)
   }
 }
 #else
 
 static void
 pages_unmap(void* aAddr, size_t aSize)
 {
   if (munmap(aAddr, aSize) == -1) {
-    char buf[STRERROR_BUF];
+    char buf[64];
 
     if (strerror_r(errno, buf, sizeof(buf)) == 0) {
       _malloc_message(
         _getprogname(), ": (malloc) Error in munmap(): ", buf, "\n");
     }
   }
 }
 
@@ -2267,17 +2214,17 @@ arena_run_reg_alloc(arena_run_t* run, ar
   // be updated unconditionally, without the possibility of updating it
   // multiple times.
   i = run->regs_minelm;
   mask = run->regs_mask[i];
   if (mask != 0) {
     // Usable allocation found.
     bit = CountTrailingZeroes32(mask);
 
-    regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
+    regind = ((i << (LOG2(sizeof(int)) + 3)) + bit);
     MOZ_ASSERT(regind < bin->nregs);
     ret =
       (void*)(((uintptr_t)run) + bin->reg0_offset + (bin->reg_size * regind));
 
     // Clear bit.
     mask ^= (1U << bit);
     run->regs_mask[i] = mask;
 
@@ -2285,17 +2232,17 @@ arena_run_reg_alloc(arena_run_t* run, ar
   }
 
   for (i++; i < bin->regs_mask_nelms; i++) {
     mask = run->regs_mask[i];
     if (mask != 0) {
       // Usable allocation found.
       bit = CountTrailingZeroes32(mask);
 
-      regind = ((i << (SIZEOF_INT_2POW + 3)) + bit);
+      regind = ((i << (LOG2(sizeof(int)) + 3)) + bit);
       MOZ_ASSERT(regind < bin->nregs);
       ret =
         (void*)(((uintptr_t)run) + bin->reg0_offset + (bin->reg_size * regind));
 
       // Clear bit.
       mask ^= (1U << bit);
       run->regs_mask[i] = mask;
 
@@ -2393,21 +2340,21 @@ arena_run_reg_dalloc(arena_run_t* run, a
     // calculate regind using actual division.  This only happens
     // if the user increases small_max via the 'S' runtime
     // configuration option.
     regind = diff / size;
   };
   MOZ_DIAGNOSTIC_ASSERT(diff == regind * size);
   MOZ_DIAGNOSTIC_ASSERT(regind < bin->nregs);
 
-  elm = regind >> (SIZEOF_INT_2POW + 3);
+  elm = regind >> (LOG2(sizeof(int)) + 3);
   if (elm < run->regs_minelm) {
     run->regs_minelm = elm;
   }
-  bit = regind - (elm << (SIZEOF_INT_2POW + 3));
+  bit = regind - (elm << (LOG2(sizeof(int)) + 3));
   MOZ_DIAGNOSTIC_ASSERT((run->regs_mask[elm] & (1U << bit)) == 0);
   run->regs_mask[elm] |= (1U << bit);
 #undef SIZE_INV
 #undef SIZE_INV_SHIFT
 }
 
 bool
 arena_t::SplitRun(arena_run_t* aRun, size_t aSize, bool aLarge, bool aZero)
@@ -2904,23 +2851,23 @@ arena_t::GetNonFullBinRun(arena_bin_t* a
   }
 
   // Initialize run internals.
   run->bin = aBin;
 
   for (i = 0; i < aBin->regs_mask_nelms - 1; i++) {
     run->regs_mask[i] = UINT_MAX;
   }
-  remainder = aBin->nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1);
+  remainder = aBin->nregs & ((1U << (LOG2(sizeof(int)) + 3)) - 1);
   if (remainder == 0) {
     run->regs_mask[i] = UINT_MAX;
   } else {
     // The last element has spare bits that need to be unset.
     run->regs_mask[i] =
-      (UINT_MAX >> ((1U << (SIZEOF_INT_2POW + 3)) - remainder));
+      (UINT_MAX >> ((1U << (LOG2(sizeof(int)) + 3)) - remainder));
   }
 
   run->regs_minelm = 0;
 
   run->nfree = aBin->nregs;
 #if defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
   run->magic = ARENA_RUN_MAGIC;
 #endif
@@ -2987,18 +2934,18 @@ arena_bin_run_size_calc(arena_bin_t* bin
   // would be quite messy, since there is an interdependency between the
   // header's mask length and the number of regions.
   try_run_size = min_run_size;
   try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size) +
               1; // Counter-act try_nregs-- in loop.
   do {
     try_nregs--;
     try_mask_nelms =
-      (try_nregs >> (SIZEOF_INT_2POW + 3)) +
-      ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ? 1 : 0);
+      (try_nregs >> (LOG2(sizeof(int)) + 3)) +
+      ((try_nregs & ((1U << (LOG2(sizeof(int)) + 3)) - 1)) ? 1 : 0);
     try_reg0_offset = try_run_size - (try_nregs * bin->reg_size);
   } while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)) >
            try_reg0_offset);
 
   // run_size expansion loop.
   do {
     // Copy valid settings before trying more aggressive settings.
     good_run_size = try_run_size;
@@ -3008,28 +2955,28 @@ arena_bin_run_size_calc(arena_bin_t* bin
 
     // Try more aggressive settings.
     try_run_size += pagesize;
     try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size) +
                 1; // Counter-act try_nregs-- in loop.
     do {
       try_nregs--;
       try_mask_nelms =
-        (try_nregs >> (SIZEOF_INT_2POW + 3)) +
-        ((try_nregs & ((1U << (SIZEOF_INT_2POW + 3)) - 1)) ? 1 : 0);
+        (try_nregs >> (LOG2(sizeof(int)) + 3)) +
+        ((try_nregs & ((1U << (LOG2(sizeof(int)) + 3)) - 1)) ? 1 : 0);
       try_reg0_offset = try_run_size - (try_nregs * bin->reg_size);
     } while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)) >
              try_reg0_offset);
   } while (try_run_size <= arena_maxclass &&
            RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX &&
            (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size);
 
   MOZ_ASSERT(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1)) <=
              good_reg0_offset);
-  MOZ_ASSERT((good_mask_nelms << (SIZEOF_INT_2POW + 3)) >= good_nregs);
+  MOZ_ASSERT((good_mask_nelms << (LOG2(sizeof(int)) + 3)) >= good_nregs);
 
   // Copy final settings.
   bin->run_size = good_run_size;
   bin->nregs = good_nregs;
   bin->regs_mask_nelms = good_mask_nelms;
   bin->reg0_offset = good_reg0_offset;
 
   return good_run_size;
@@ -3493,18 +3440,18 @@ MozJemalloc::jemalloc_ptr_info(const voi
 
   // Position in the run.
   unsigned regind = ((uintptr_t)aPtr - reg0_addr) / size;
 
   // Pointer to the allocation's base address.
   void* addr = (void*)(reg0_addr + regind * size);
 
   // Check if the allocation has been freed.
-  unsigned elm = regind >> (SIZEOF_INT_2POW + 3);
-  unsigned bit = regind - (elm << (SIZEOF_INT_2POW + 3));
+  unsigned elm = regind >> (LOG2(sizeof(int)) + 3);
+  unsigned bit = regind - (elm << (LOG2(sizeof(int)) + 3));
   PtrInfoTag tag =
     ((run->regs_mask[elm] & (1U << bit))) ? TagFreedSmall : TagLiveSmall;
 
   *aInfo = { tag, addr, size };
 }
 
 namespace Debug {
 // Helper for debuggers. We don't want it to be inlined and optimized out.
@@ -4807,17 +4754,18 @@ MozJemalloc::moz_dispose_arena(arena_id_
   }
 }
 
 #define MALLOC_DECL(name, return_type, ...)                                    \
   template<>                                                                   \
   inline return_type MozJemalloc::moz_arena_##name(                            \
     arena_id_t aArenaId, ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__))               \
   {                                                                            \
-    BaseAllocator allocator(gArenas.GetById(aArenaId, /* IsPrivate = */ true));\
+    BaseAllocator allocator(                                                   \
+      gArenas.GetById(aArenaId, /* IsPrivate = */ true));                      \
     return allocator.name(ARGS_HELPER(ARGS, ##__VA_ARGS__));                   \
   }
 #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC_BASE
 #include "malloc_decls.h"
 
 #else
 
 #define MALLOC_DECL(name, return_type, ...)                                    \
--- a/memory/build/mozjemalloc.h
+++ b/memory/build/mozjemalloc.h
@@ -5,75 +5,80 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozjemalloc_h
 #define mozjemalloc_h
 
 #include "mozjemalloc_types.h"
 #include "mozilla/MacroArgs.h"
 
-/* Macro helpers */
+// Macro helpers
 
 #define MACRO_CALL(a, b) a b
-/* Can't use macros recursively, so we need another one doing the same as above. */
+// Can't use macros recursively, so we need another one doing the same as above.
 #define MACRO_CALL2(a, b) a b
 
-#define ARGS_HELPER(name, ...) MACRO_CALL2( \
-  MOZ_PASTE_PREFIX_AND_ARG_COUNT(name, ##__VA_ARGS__), \
-  (__VA_ARGS__))
+#define ARGS_HELPER(name, ...)                                                 \
+  MACRO_CALL2(MOZ_PASTE_PREFIX_AND_ARG_COUNT(name, ##__VA_ARGS__),             \
+              (__VA_ARGS__))
 #define TYPED_ARGS0()
 #define TYPED_ARGS1(t1) t1 arg1
 #define TYPED_ARGS2(t1, t2) TYPED_ARGS1(t1), t2 arg2
 #define TYPED_ARGS3(t1, t2, t3) TYPED_ARGS2(t1, t2), t3 arg3
 
 #define ARGS0()
 #define ARGS1(t1) arg1
 #define ARGS2(t1, t2) ARGS1(t1), arg2
 #define ARGS3(t1, t2, t3) ARGS2(t1, t2), arg3
 
 #ifdef MOZ_MEMORY
 
-/* Generic interface exposing the whole public allocator API
- * This facilitates the implementation of things like replace-malloc.
- * Note: compilers are expected to be able to optimize out `this`.
- */
-template <typename T>
-struct Allocator: public T {
-#define MALLOC_DECL(name, return_type, ...) \
+// Generic interface exposing the whole public allocator API
+// This facilitates the implementation of things like replace-malloc.
+// Note: compilers are expected to be able to optimize out `this`.
+template<typename T>
+struct Allocator : public T
+{
+#define MALLOC_DECL(name, return_type, ...)                                    \
   static return_type name(__VA_ARGS__);
 #include "malloc_decls.h"
 };
 
-/* The MozJemalloc allocator */
-struct MozJemallocBase {};
+// The MozJemalloc allocator
+struct MozJemallocBase
+{
+};
 typedef Allocator<MozJemallocBase> MozJemalloc;
 
 #ifdef MOZ_REPLACE_MALLOC
-/* The replace-malloc allocator */
-struct ReplaceMallocBase {};
+// The replace-malloc allocator
+struct ReplaceMallocBase
+{
+};
 typedef Allocator<ReplaceMallocBase> ReplaceMalloc;
 
 typedef ReplaceMalloc DefaultMalloc;
 #else
 typedef MozJemalloc DefaultMalloc;
 #endif
 
-#endif /* MOZ_MEMORY */
+#endif // MOZ_MEMORY
 
-/* Dummy implementation of the moz_arena_* API, falling back to a given
- * implementation of the base allocator. */
-template <typename T>
-struct DummyArenaAllocator {
+// Dummy implementation of the moz_arena_* API, falling back to a given
+// implementation of the base allocator.
+template<typename T>
+struct DummyArenaAllocator
+{
   static arena_id_t moz_create_arena(void) { return 0; }
 
-  static void moz_dispose_arena(arena_id_t) { }
+  static void moz_dispose_arena(arena_id_t) {}
 
-#define MALLOC_DECL(name, return_type, ...) \
-  static return_type \
-  moz_arena_ ## name(arena_id_t, ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
-  { \
-    return T::name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  static return_type moz_arena_##name(arena_id_t,                              \
+                                      ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__))  \
+  {                                                                            \
+    return T::name(ARGS_HELPER(ARGS, ##__VA_ARGS__));                          \
   }
 #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC_BASE
 #include "malloc_decls.h"
 };
 
 #endif
--- a/memory/build/mozjemalloc_types.h
+++ b/memory/build/mozjemalloc_types.h
@@ -1,43 +1,47 @@
-/* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */
-/* vim:set softtabstop=8 shiftwidth=8: */
-/*-
- * Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice(s), this list of conditions and the following disclaimer as
- *    the first lines of this file unmodified other than the possible
- *    addition of one or more copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice(s), this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+// Portions of this file were originally under the following license:
+//
+// Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice(s), this list of conditions and the following disclaimer as
+//    the first lines of this file unmodified other than the possible
+//    addition of one or more copyright notices.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice(s), this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef _JEMALLOC_TYPES_H_
 #define _JEMALLOC_TYPES_H_
 
-/* grab size_t */
+// grab size_t
 #ifdef _MSC_VER
 #include <crtdefs.h>
 #else
 #include <stddef.h>
 #endif
 #include <stdbool.h>
 
 #ifdef __cplusplus
@@ -47,51 +51,47 @@ extern "C" {
 #ifndef MALLOC_USABLE_SIZE_CONST_PTR
 #define MALLOC_USABLE_SIZE_CONST_PTR const
 #endif
 
 typedef MALLOC_USABLE_SIZE_CONST_PTR void* usable_ptr_t;
 
 typedef size_t arena_id_t;
 
-/*
- * jemalloc_stats() is not a stable interface.  When using jemalloc_stats_t, be
- * sure that the compiled results of jemalloc.c are in sync with this header
- * file.
- */
-typedef struct {
-	/*
-	 * Run-time configuration settings.
-	 */
-	bool	opt_junk;	/* Fill allocated memory with kAllocJunk? */
-	bool	opt_zero;	/* Fill allocated memory with 0x0? */
-	size_t	narenas;	/* Number of arenas. */
-	size_t	quantum;	/* Allocation quantum. */
-	size_t	small_max;	/* Max quantum-spaced allocation size. */
-	size_t	large_max;	/* Max sub-chunksize allocation size. */
-	size_t	chunksize;	/* Size of each virtual memory mapping. */
-	size_t  page_size;	/* Size of pages. */
-	size_t	dirty_max;	/* Max dirty pages per arena. */
+// jemalloc_stats() is not a stable interface.  When using jemalloc_stats_t, be
+// sure that the compiled results of jemalloc.c are in sync with this header
+// file.
+typedef struct
+{
+  // Run-time configuration settings.
+  bool opt_junk;    // Fill allocated memory with kAllocJunk?
+  bool opt_zero;    // Fill allocated memory with 0x0?
+  size_t narenas;   // Number of arenas.
+  size_t quantum;   // Allocation quantum.
+  size_t small_max; // Max quantum-spaced allocation size.
+  size_t large_max; // Max sub-chunksize allocation size.
+  size_t chunksize; // Size of each virtual memory mapping.
+  size_t page_size; // Size of pages.
+  size_t dirty_max; // Max dirty pages per arena.
 
-	/*
-	 * Current memory usage statistics.
-	 */
-	size_t	mapped;		/* Bytes mapped (not necessarily committed). */
-	size_t	allocated;	/* Bytes allocated (committed, in use by application). */
-        size_t  waste;          /* Bytes committed, not in use by the
-                                   application, and not intentionally left
-                                   unused (i.e., not dirty). */
-        size_t	page_cache;	/* Committed, unused pages kept around as a
-                                   cache.  (jemalloc calls these "dirty".) */
-        size_t  bookkeeping;    /* Committed bytes used internally by the
-                                   allocator. */
-	size_t bin_unused; /* Bytes committed to a bin but currently unused. */
+  // Current memory usage statistics.
+  size_t mapped;      // Bytes mapped (not necessarily committed).
+  size_t allocated;   // Bytes allocated (committed, in use by application).
+  size_t waste;       // Bytes committed, not in use by the
+                      // application, and not intentionally left
+                      // unused (i.e., not dirty).
+  size_t page_cache;  // Committed, unused pages kept around as a
+                      // cache.  (jemalloc calls these "dirty".)
+  size_t bookkeeping; // Committed bytes used internally by the
+                      // allocator.
+  size_t bin_unused;  // Bytes committed to a bin but currently unused.
 } jemalloc_stats_t;
 
-enum PtrInfoTag {
+enum PtrInfoTag
+{
   // The pointer is not currently known to the allocator.
   // 'addr' and 'size' are always 0.
   TagUnknown,
 
   // The pointer is within a live allocation.
   // 'addr' and 'size' describe the allocation.
   TagLiveSmall,
   TagLiveLarge,
@@ -105,53 +105,48 @@ enum PtrInfoTag {
   // allocation, including its size, are not available.
   // 'addr' and 'size' describe the page.
   TagFreedPageDirty,
   TagFreedPageDecommitted,
   TagFreedPageMadvised,
   TagFreedPageZeroed,
 };
 
-/*
- * The information in jemalloc_ptr_info_t could be represented in a variety of
- * ways. The chosen representation has the following properties.
- * - The number of fields is minimized.
- * - The 'tag' field unambiguously defines the meaning of the subsequent fields.
- * Helper functions are used to group together related categories of tags.
- */
-typedef struct {
+// The information in jemalloc_ptr_info_t could be represented in a variety of
+// ways. The chosen representation has the following properties.
+// - The number of fields is minimized.
+// - The 'tag' field unambiguously defines the meaning of the subsequent fields.
+// Helper functions are used to group together related categories of tags.
+typedef struct
+{
   enum PtrInfoTag tag;
-  void* addr;     // meaning depends on tag; see above
-  size_t size;    // meaning depends on tag; see above
+  void* addr;  // meaning depends on tag; see above
+  size_t size; // meaning depends on tag; see above
 } jemalloc_ptr_info_t;
 
 static inline bool
 jemalloc_ptr_is_live(jemalloc_ptr_info_t* info)
 {
-  return info->tag == TagLiveSmall ||
-         info->tag == TagLiveLarge ||
+  return info->tag == TagLiveSmall || info->tag == TagLiveLarge ||
          info->tag == TagLiveHuge;
 }
 
 static inline bool
 jemalloc_ptr_is_freed(jemalloc_ptr_info_t* info)
 {
-  return info->tag == TagFreedSmall ||
-         info->tag == TagFreedPageDirty ||
+  return info->tag == TagFreedSmall || info->tag == TagFreedPageDirty ||
          info->tag == TagFreedPageDecommitted ||
-         info->tag == TagFreedPageMadvised ||
-         info->tag == TagFreedPageZeroed;
+         info->tag == TagFreedPageMadvised || info->tag == TagFreedPageZeroed;
 }
 
 static inline bool
 jemalloc_ptr_is_freed_page(jemalloc_ptr_info_t* info)
 {
   return info->tag == TagFreedPageDirty ||
          info->tag == TagFreedPageDecommitted ||
-         info->tag == TagFreedPageMadvised ||
-         info->tag == TagFreedPageZeroed;
+         info->tag == TagFreedPageMadvised || info->tag == TagFreedPageZeroed;
 }
 
 #ifdef __cplusplus
-} /* extern "C" */
+} // extern "C"
 #endif
 
-#endif /* _JEMALLOC_TYPES_H_ */
+#endif // _JEMALLOC_TYPES_H_
--- a/memory/build/mozmemory.h
+++ b/memory/build/mozmemory.h
@@ -1,62 +1,62 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
+ * 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 mozmemory_h
 #define mozmemory_h
 
-/*
- * This header is meant to be used when the following functions are
- * necessary:
- *   - malloc_good_size (used to be called je_malloc_usable_in_advance)
- *   - jemalloc_stats
- *   - jemalloc_purge_freed_pages
- *   - jemalloc_free_dirty_pages
- *   - jemalloc_thread_local_arena
- *   - jemalloc_ptr_info
- */
+// This header is meant to be used when the following functions are
+// necessary:
+//   - malloc_good_size (used to be called je_malloc_usable_in_advance)
+//   - jemalloc_stats
+//   - jemalloc_purge_freed_pages
+//   - jemalloc_free_dirty_pages
+//   - jemalloc_thread_local_arena
+//   - jemalloc_ptr_info
 
 #ifdef MALLOC_H
 #include MALLOC_H
 #endif
 #include "mozmemory_wrap.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Types.h"
 #include "mozjemalloc_types.h"
 
 #ifdef MOZ_MEMORY
-/*
- * On OSX, malloc/malloc.h contains the declaration for malloc_good_size,
- * which will call back in jemalloc, through the zone allocator so just use it.
- */
+// On OSX, malloc/malloc.h contains the declaration for malloc_good_size,
+// which will call back in jemalloc, through the zone allocator so just use it.
 #ifndef XP_DARWIN
-MOZ_MEMORY_API size_t malloc_good_size_impl(size_t size);
+MOZ_MEMORY_API size_t
+malloc_good_size_impl(size_t size);
 
-/* Note: the MOZ_GLUE_IN_PROGRAM ifdef below is there to avoid -Werror turning
- * the protective if into errors. MOZ_GLUE_IN_PROGRAM is what triggers MFBT_API
- * to use weak imports. */
-
-static inline size_t _malloc_good_size(size_t size) {
-#  if defined(MOZ_GLUE_IN_PROGRAM) && !defined(IMPL_MFBT)
+// Note: the MOZ_GLUE_IN_PROGRAM ifdef below is there to avoid -Werror turning
+// the protective if into errors. MOZ_GLUE_IN_PROGRAM is what triggers MFBT_API
+// to use weak imports.
+static inline size_t
+_malloc_good_size(size_t size)
+{
+#if defined(MOZ_GLUE_IN_PROGRAM) && !defined(IMPL_MFBT)
   if (!malloc_good_size)
     return size;
-#  endif
+#endif
   return malloc_good_size_impl(size);
 }
 
-#  define malloc_good_size _malloc_good_size
+#define malloc_good_size _malloc_good_size
 #endif
 
-#define MALLOC_DECL(name, return_type, ...) \
+#define MALLOC_DECL(name, return_type, ...)                                    \
   MOZ_JEMALLOC_API return_type name(__VA_ARGS__);
 #define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
 #include "malloc_decls.h"
 
 #endif
 
-#define MALLOC_DECL(name, return_type, ...) \
+#define MALLOC_DECL(name, return_type, ...)                                    \
   MOZ_JEMALLOC_API return_type name(__VA_ARGS__);
 #define MALLOC_FUNCS MALLOC_FUNCS_ARENA
 #include "malloc_decls.h"
 
-#endif /* mozmemory_h */
+#endif // mozmemory_h
--- a/memory/build/mozmemory_wrap.cpp
+++ b/memory/build/mozmemory_wrap.cpp
@@ -1,20 +1,22 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
+ * 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 <string.h>
 #include "mozmemory_wrap.h"
 #include "mozilla/Types.h"
 
-/* Declare malloc implementation functions with the right return and
- * argument types. */
-#define MALLOC_DECL(name, return_type, ...) \
-  MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
+// Declare malloc implementation functions with the right return and
+// argument types.
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__);
 #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
 #include "malloc_decls.h"
 
 #ifdef MOZ_WRAP_NEW_DELETE
 #include <new>
 
 MFBT_API void*
 operator new(size_t size)
@@ -60,47 +62,47 @@ operator delete(void* ptr, std::nothrow_
 
 MFBT_API void
 operator delete[](void* ptr, std::nothrow_t const&)
 {
   free_impl(ptr);
 }
 #endif
 
-/* strndup and strdup may be defined as macros in string.h, which would
- * clash with the definitions below. */
+// strndup and strdup may be defined as macros in string.h, which would
+// clash with the definitions below.
 #undef strndup
 #undef strdup
 
-MOZ_MEMORY_API char *
-strndup_impl(const char *src, size_t len)
+MOZ_MEMORY_API char*
+strndup_impl(const char* src, size_t len)
 {
-  char* dst = (char*) malloc_impl(len + 1);
+  char* dst = (char*)malloc_impl(len + 1);
   if (dst) {
     strncpy(dst, src, len);
     dst[len] = '\0';
   }
   return dst;
 }
 
-MOZ_MEMORY_API char *
-strdup_impl(const char *src)
+MOZ_MEMORY_API char*
+strdup_impl(const char* src)
 {
   size_t len = strlen(src);
   return strndup_impl(src, len);
 }
 
 #ifdef ANDROID
 #include <stdarg.h>
 #include <stdio.h>
 
 MOZ_MEMORY_API int
-vasprintf_impl(char **str, const char *fmt, va_list ap)
+vasprintf_impl(char** str, const char* fmt, va_list ap)
 {
-  char* ptr, *_ptr;
+  char *ptr, *_ptr;
   int ret;
 
   if (str == NULL || fmt == NULL) {
     return -1;
   }
 
   ptr = (char*)malloc_impl(128);
   if (ptr == NULL) {
@@ -123,45 +125,43 @@ vasprintf_impl(char **str, const char *f
   }
 
   *str = _ptr;
 
   return ret;
 }
 
 MOZ_MEMORY_API int
-asprintf_impl(char **str, const char *fmt, ...)
+asprintf_impl(char** str, const char* fmt, ...)
 {
-   int ret;
-   va_list ap;
-   va_start(ap, fmt);
+  int ret;
+  va_list ap;
+  va_start(ap, fmt);
 
-   ret = vasprintf_impl(str, fmt, ap);
+  ret = vasprintf_impl(str, fmt, ap);
 
-   va_end(ap);
+  va_end(ap);
 
-   return ret;
+  return ret;
 }
 #endif
 
 #ifdef XP_WIN
 #include <wchar.h>
 
-/*
- *  We also need to provide our own impl of wcsdup so that we don't ask
- *  the CRT for memory from its heap (which will then be unfreeable).
- */
+// We also need to provide our own impl of wcsdup so that we don't ask
+// the CRT for memory from its heap (which will then be unfreeable).
 MOZ_MEMORY_API wchar_t*
 wcsdup_impl(const wchar_t* src)
 {
   size_t len = wcslen(src);
-  wchar_t *dst = (wchar_t*) malloc_impl((len + 1) * sizeof(wchar_t));
+  wchar_t* dst = (wchar_t*)malloc_impl((len + 1) * sizeof(wchar_t));
   if (dst)
     wcsncpy(dst, src, len + 1);
   return dst;
 }
 
 MOZ_MEMORY_API void*
 _aligned_malloc(size_t size, size_t alignment)
 {
   return memalign_impl(alignment, size);
 }
-#endif /* XP_WIN */
+#endif // XP_WIN
--- a/memory/build/mozmemory_wrap.h
+++ b/memory/build/mozmemory_wrap.h
@@ -1,170 +1,169 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
+ * 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 mozmemory_wrap_h
 #define mozmemory_wrap_h
 
-/*
- * This header contains #defines which tweak the names of various memory
- * allocation functions.
- *
- * There are several types of functions related to memory allocation
- * that are meant to be used publicly by the Gecko codebase:
- *
- * - malloc implementation functions:
- *   - malloc
- *   - posix_memalign
- *   - aligned_alloc
- *   - calloc
- *   - realloc
- *   - free
- *   - memalign
- *   - valloc
- *   - malloc_usable_size
- *   - malloc_good_size
- *   Some of these functions are specific to some systems, but for
- *   convenience, they are treated as being cross-platform, and available
- *   as such.
- *
- * - duplication functions:
- *   - strndup
- *   - strdup
- *   - wcsdup (Windows only)
- *
- * - jemalloc specific functions:
- *   - jemalloc_stats
- *   - jemalloc_purge_freed_pages
- *   - jemalloc_free_dirty_pages
- *   - jemalloc_thread_local_arena
- *   - jemalloc_ptr_info
- *   (these functions are native to mozjemalloc)
- *
- * These functions are all exported as part of libmozglue (see
- * $(topsrcdir)/mozglue/build/Makefile.in), with a few implementation
- * peculiarities:
- *
- * - On Windows, the malloc implementation functions are all prefixed with
- *   "je_", the duplication functions are prefixed with "wrap_", and jemalloc
- *   specific functions are left unprefixed. All these functions are however
- *   aliased when exporting them, such that the resulting mozglue.dll exports
- *   them unprefixed (see $(topsrcdir)/mozglue/build/mozglue.def.in). The
- *   prefixed malloc implementation and duplication functions are not
- *   exported.
- *
- * - On MacOSX, the system libc has a zone allocator, which allows us to
- *   hook custom malloc implementation functions without exporting them.
- *   However, since we want things in Firefox to skip the system zone
- *   allocator, the malloc implementation functions are all exported
- *   unprefixed, as well as duplication functions.
- *   Jemalloc-specific functions are also left unprefixed.
- *
- * - On Android all functions are left unprefixed. Additionally,
- *   C++ allocation functions (operator new/delete) are also exported and
- *   unprefixed.
- *
- * - On other systems (mostly Linux), all functions are left unprefixed.
- *
- * Only Android adds C++ allocation functions.
- *
- * Proper exporting of the various functions is done with the MOZ_MEMORY_API
- * and MOZ_JEMALLOC_API macros. MOZ_MEMORY_API is meant to be used for malloc
- * implementation and duplication functions, while MOZ_JEMALLOC_API is
- * dedicated to jemalloc specific functions.
- *
- *
- * All these functions are meant to be called with no prefix from Gecko code.
- * In most cases, this is because that's how they are available at runtime.
- * However, on Android, this relies on faulty.lib (the custom dynamic linker)
- * resolving mozglue symbols before libc symbols, which is guaranteed by the
- * way faulty.lib works (it respects the DT_NEEDED order, and libc always
- * appears after mozglue ; which we double check when building anyways)
- *
- *
- * Within libmozglue (when MOZ_MEMORY_IMPL is defined), all the functions
- * should be suffixed with "_impl" both for declarations and use.
- * That is, the implementation declaration for e.g. strdup would look like:
- *   char* strdup_impl(const char *)
- * That implementation would call malloc by using "malloc_impl".
- */
+// This header contains #defines which tweak the names of various memory
+// allocation functions.
+//
+// There are several types of functions related to memory allocation
+// that are meant to be used publicly by the Gecko codebase:
+//
+// - malloc implementation functions:
+//   - malloc
+//   - posix_memalign
+//   - aligned_alloc
+//   - calloc
+//   - realloc
+//   - free
+//   - memalign
+//   - valloc
+//   - malloc_usable_size
+//   - malloc_good_size
+//   Some of these functions are specific to some systems, but for
+//   convenience, they are treated as being cross-platform, and available
+//   as such.
+//
+// - duplication functions:
+//   - strndup
+//   - strdup
+//   - wcsdup (Windows only)
+//
+// - jemalloc specific functions:
+//   - jemalloc_stats
+//   - jemalloc_purge_freed_pages
+//   - jemalloc_free_dirty_pages
+//   - jemalloc_thread_local_arena
+//   - jemalloc_ptr_info
+//   (these functions are native to mozjemalloc)
+//
+// These functions are all exported as part of libmozglue (see
+// $(topsrcdir)/mozglue/build/Makefile.in), with a few implementation
+// peculiarities:
+//
+// - On Windows, the malloc implementation functions are all prefixed with
+//   "je_", the duplication functions are prefixed with "wrap_", and jemalloc
+//   specific functions are left unprefixed. All these functions are however
+//   aliased when exporting them, such that the resulting mozglue.dll exports
+//   them unprefixed (see $(topsrcdir)/mozglue/build/mozglue.def.in). The
+//   prefixed malloc implementation and duplication functions are not
+//   exported.
+//
+// - On MacOSX, the system libc has a zone allocator, which allows us to
+//   hook custom malloc implementation functions without exporting them.
+//   However, since we want things in Firefox to skip the system zone
+//   allocator, the malloc implementation functions are all exported
+//   unprefixed, as well as duplication functions.
+//   Jemalloc-specific functions are also left unprefixed.
+//
+// - On Android all functions are left unprefixed. Additionally,
+//   C++ allocation functions (operator new/delete) are also exported and
+//   unprefixed.
+//
+// - On other systems (mostly Linux), all functions are left unprefixed.
+//
+// Only Android adds C++ allocation functions.
+//
+// Proper exporting of the various functions is done with the MOZ_MEMORY_API
+// and MOZ_JEMALLOC_API macros. MOZ_MEMORY_API is meant to be used for malloc
+// implementation and duplication functions, while MOZ_JEMALLOC_API is
+// dedicated to jemalloc specific functions.
+//
+//
+// All these functions are meant to be called with no prefix from Gecko code.
+// In most cases, this is because that's how they are available at runtime.
+// However, on Android, this relies on faulty.lib (the custom dynamic linker)
+// resolving mozglue symbols before libc symbols, which is guaranteed by the
+// way faulty.lib works (it respects the DT_NEEDED order, and libc always
+// appears after mozglue ; which we double check when building anyways)
+//
+//
+// Within libmozglue (when MOZ_MEMORY_IMPL is defined), all the functions
+// should be suffixed with "_impl" both for declarations and use.
+// That is, the implementation declaration for e.g. strdup would look like:
+//   char* strdup_impl(const char *)
+// That implementation would call malloc by using "malloc_impl".
 
 #if defined(MOZ_MEMORY_IMPL) && !defined(IMPL_MFBT)
-#  ifdef MFBT_API /* mozilla/Types.h was already included */
+#ifdef MFBT_API // mozilla/Types.h was already included
 #    error mozmemory_wrap.h has to be included before mozilla/Types.h when MOZ_MEMORY_IMPL is set and IMPL_MFBT is not.
-#  endif
-#  define IMPL_MFBT
+#endif
+#define IMPL_MFBT
 #endif
 
 #include "mozilla/Types.h"
 
 #ifndef MOZ_EXTERN_C
 #ifdef __cplusplus
 #define MOZ_EXTERN_C extern "C"
 #else
 #define MOZ_EXTERN_C
 #endif
 #endif
 
 #ifdef MOZ_MEMORY_IMPL
-#  define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API
-#  if defined(XP_WIN)
-#    define mozmem_malloc_impl(a)   je_ ## a
-#  else
-#    define MOZ_MEMORY_API MOZ_EXTERN_C MFBT_API
-#    if defined(MOZ_WIDGET_ANDROID)
-#      define MOZ_WRAP_NEW_DELETE
-#    endif
-#  endif
+#define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API
+#if defined(XP_WIN)
+#define mozmem_malloc_impl(a) je_##a
+#else
+#define MOZ_MEMORY_API MOZ_EXTERN_C MFBT_API
+#if defined(MOZ_WIDGET_ANDROID)
+#define MOZ_WRAP_NEW_DELETE
+#endif
+#endif
 #endif
 #ifdef XP_WIN
-#  define mozmem_dup_impl(a)      wrap_ ## a
+#define mozmem_dup_impl(a) wrap_##a
 #endif
 
 #if !defined(MOZ_MEMORY_IMPL)
-#  define MOZ_MEMORY_API MOZ_EXTERN_C MFBT_API
-#  define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API
+#define MOZ_MEMORY_API MOZ_EXTERN_C MFBT_API
+#define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API
 #endif
 
 #ifndef MOZ_MEMORY_API
-#  define MOZ_MEMORY_API MOZ_EXTERN_C
+#define MOZ_MEMORY_API MOZ_EXTERN_C
 #endif
 #ifndef MOZ_JEMALLOC_API
-#  define MOZ_JEMALLOC_API MOZ_EXTERN_C
+#define MOZ_JEMALLOC_API MOZ_EXTERN_C
 #endif
 
 #ifndef mozmem_malloc_impl
-#  define mozmem_malloc_impl(a)   a
+#define mozmem_malloc_impl(a) a
 #endif
 #ifndef mozmem_dup_impl
-#  define mozmem_dup_impl(a)      a
+#define mozmem_dup_impl(a) a
 #endif
 
-/* Malloc implementation functions */
-#define malloc_impl              mozmem_malloc_impl(malloc)
-#define posix_memalign_impl      mozmem_malloc_impl(posix_memalign)
-#define aligned_alloc_impl       mozmem_malloc_impl(aligned_alloc)
-#define calloc_impl              mozmem_malloc_impl(calloc)
-#define realloc_impl             mozmem_malloc_impl(realloc)
-#define free_impl                mozmem_malloc_impl(free)
-#define memalign_impl            mozmem_malloc_impl(memalign)
-#define valloc_impl              mozmem_malloc_impl(valloc)
-#define malloc_usable_size_impl  mozmem_malloc_impl(malloc_usable_size)
-#define malloc_good_size_impl    mozmem_malloc_impl(malloc_good_size)
+// Malloc implementation functions
+#define malloc_impl mozmem_malloc_impl(malloc)
+#define posix_memalign_impl mozmem_malloc_impl(posix_memalign)
+#define aligned_alloc_impl mozmem_malloc_impl(aligned_alloc)
+#define calloc_impl mozmem_malloc_impl(calloc)
+#define realloc_impl mozmem_malloc_impl(realloc)
+#define free_impl mozmem_malloc_impl(free)
+#define memalign_impl mozmem_malloc_impl(memalign)
+#define valloc_impl mozmem_malloc_impl(valloc)
+#define malloc_usable_size_impl mozmem_malloc_impl(malloc_usable_size)
+#define malloc_good_size_impl mozmem_malloc_impl(malloc_good_size)
 
-/* Duplication functions */
-#define strndup_impl   mozmem_dup_impl(strndup)
-#define strdup_impl    mozmem_dup_impl(strdup)
+// Duplication functions
+#define strndup_impl mozmem_dup_impl(strndup)
+#define strdup_impl mozmem_dup_impl(strdup)
 #ifdef XP_WIN
-#  define wcsdup_impl  mozmem_dup_impl(wcsdup)
+#define wcsdup_impl mozmem_dup_impl(wcsdup)
 #endif
 
-/* String functions */
+// String functions
 #ifdef ANDROID
-/* Bug 801571 and Bug 879668, libstagefright uses vasprintf, causing malloc()/
- * free() to be mismatched between bionic and mozglue implementation.
- */
-#define vasprintf_impl  mozmem_dup_impl(vasprintf)
-#define asprintf_impl   mozmem_dup_impl(asprintf)
+// Bug 801571 and Bug 879668, libstagefright uses vasprintf, causing malloc()/
+// free() to be mismatched between bionic and mozglue implementation.
+#define vasprintf_impl mozmem_dup_impl(vasprintf)
+#define asprintf_impl mozmem_dup_impl(asprintf)
 #endif
 
-#endif /* mozmemory_wrap_h */
+#endif // mozmemory_wrap_h
--- a/memory/build/rb.h
+++ b/memory/build/rb.h
@@ -1,226 +1,178 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
-/*
- * Portions of this file were originally under the following license:
- *
- * Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice(s), this list of conditions and the following disclaimer
- *    unmodified other than the allowable addition of one or more
- *    copyright notices.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice(s), this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- ******************************************************************************
- *
- * C++ template implementation of left-leaning red-black trees.
- *
- * All operations are done non-recursively.  Parent pointers are not used, and
- * color bits are stored in the least significant bit of right-child pointers,
- * thus making node linkage as compact as is possible for red-black trees.
- *
- * The RedBlackTree template expects two type arguments: the type of the nodes,
- * containing a RedBlackTreeNode, and a trait providing two methods:
- *  - a GetTreeNode method that returns a reference to the RedBlackTreeNode
- *    corresponding to a given node with the following signature:
- *      static RedBlackTreeNode<T>& GetTreeNode(T*)
- *  - a Compare function with the following signature:
- *      static int Compare(T* aNode, T* aOther)
- *                            ^^^^^
- *                         or aKey
- *
- * Interpretation of comparision function return values:
- *
- *   -1 : aNode <  aOther
- *    0 : aNode == aOther
- *    1 : aNode >  aOther
- *
- * In all cases, the aNode or aKey argument is the first argument to the
- * comparison function, which makes it possible to write comparison functions
- * that treat the first argument specially.
- *
- ******************************************************************************/
+// Portions of this file were originally under the following license:
+//
+// Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+//    notice(s), this list of conditions and the following disclaimer
+//    unmodified other than the allowable addition of one or more
+//    copyright notices.
+// 2. Redistributions in binary form must reproduce the above copyright
+//    notice(s), this list of conditions and the following disclaimer in
+//    the documentation and/or other materials provided with the
+//    distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// ****************************************************************************
+//
+// C++ template implementation of left-leaning red-black trees.
+//
+// All operations are done non-recursively.  Parent pointers are not used, and
+// color bits are stored in the least significant bit of right-child pointers,
+// thus making node linkage as compact as is possible for red-black trees.
+//
+// The RedBlackTree template expects two type arguments: the type of the nodes,
+// containing a RedBlackTreeNode, and a trait providing two methods:
+//  - a GetTreeNode method that returns a reference to the RedBlackTreeNode
+//    corresponding to a given node with the following signature:
+//      static RedBlackTreeNode<T>& GetTreeNode(T*)
+//  - a Compare function with the following signature:
+//      static int Compare(T* aNode, T* aOther)
+//                            ^^^^^
+//                         or aKey
+//
+// Interpretation of comparision function return values:
+//
+//   -1 : aNode <  aOther
+//    0 : aNode == aOther
+//    1 : aNode >  aOther
+//
+// In all cases, the aNode or aKey argument is the first argument to the
+// comparison function, which makes it possible to write comparison functions
+// that treat the first argument specially.
+//
+// ***************************************************************************
 
 #ifndef RB_H_
 #define RB_H_
 
 #include "mozilla/Alignment.h"
 #include "Utils.h"
 
 enum NodeColor
 {
   Black = 0,
   Red = 1,
 };
 
-/* Node structure. */
-template <typename T>
+// Node structure.
+template<typename T>
 class RedBlackTreeNode
 {
   T* mLeft;
-  /* The lowest bit is the color */
+  // The lowest bit is the color
   T* mRightAndColor;
 
 public:
-  T* Left()
-  {
-    return mLeft;
-  }
+  T* Left() { return mLeft; }
 
-  void SetLeft(T* aValue)
-  {
-    mLeft = aValue;
-  }
+  void SetLeft(T* aValue) { mLeft = aValue; }
 
   T* Right()
   {
-    return reinterpret_cast<T*>(
-      reinterpret_cast<uintptr_t>(mRightAndColor) & uintptr_t(~1));
+    return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(mRightAndColor) &
+                                uintptr_t(~1));
   }
 
   void SetRight(T* aValue)
   {
     mRightAndColor = reinterpret_cast<T*>(
       (reinterpret_cast<uintptr_t>(aValue) & uintptr_t(~1)) | Color());
   }
 
   NodeColor Color()
   {
-    return static_cast<NodeColor>(reinterpret_cast<uintptr_t>(mRightAndColor) & 1);
+    return static_cast<NodeColor>(reinterpret_cast<uintptr_t>(mRightAndColor) &
+                                  1);
   }
 
-  bool IsBlack()
-  {
-    return Color() == NodeColor::Black;
-  }
+  bool IsBlack() { return Color() == NodeColor::Black; }
 
-  bool IsRed()
-  {
-    return Color() == NodeColor::Red;
-  }
+  bool IsRed() { return Color() == NodeColor::Red; }
 
   void SetColor(NodeColor aColor)
   {
     mRightAndColor = reinterpret_cast<T*>(
       (reinterpret_cast<uintptr_t>(mRightAndColor) & uintptr_t(~1)) | aColor);
   }
 };
 
-/* Tree structure. */
+// Tree structure.
 template<typename T, typename Trait>
 class RedBlackTree
 {
 public:
   void Init() { mRoot = nullptr; }
 
   T* First(T* aStart = nullptr)
   {
     return First(reinterpret_cast<TreeNode*>(aStart));
   }
 
   T* Last(T* aStart = nullptr)
   {
     return Last(reinterpret_cast<TreeNode*>(aStart));
   }
 
-  T* Next(T* aNode)
-  {
-    return Next(reinterpret_cast<TreeNode*>(aNode));
-  }
+  T* Next(T* aNode) { return Next(reinterpret_cast<TreeNode*>(aNode)); }
+
+  T* Prev(T* aNode) { return Prev(reinterpret_cast<TreeNode*>(aNode)); }
 
-  T* Prev(T* aNode)
-  {
-    return Prev(reinterpret_cast<TreeNode*>(aNode));
-  }
+  T* Search(T* aKey) { return Search(reinterpret_cast<TreeNode*>(aKey)); }
 
-  T* Search(T* aKey)
-  {
-    return Search(reinterpret_cast<TreeNode*>(aKey));
-  }
-
-  /* Find a match if it exists. Otherwise, find the next greater node, if one
-   * exists */
+  // Find a match if it exists. Otherwise, find the next greater node, if one
+  // exists.
   T* SearchOrNext(T* aKey)
   {
     return SearchOrNext(reinterpret_cast<TreeNode*>(aKey));
   }
 
-  void Insert(T* aNode)
-  {
-    Insert(reinterpret_cast<TreeNode*>(aNode));
-  }
+  void Insert(T* aNode) { Insert(reinterpret_cast<TreeNode*>(aNode)); }
 
-  void Remove(T* aNode)
-  {
-    return Remove(reinterpret_cast<TreeNode*>(aNode));
-  }
+  void Remove(T* aNode) { return Remove(reinterpret_cast<TreeNode*>(aNode)); }
 
-  /* Helper class to avoid having all the tree traversal code further below
-   * have to use Trait::GetTreeNode, adding visual noise. */
+  // Helper class to avoid having all the tree traversal code further below
+  // have to use Trait::GetTreeNode, adding visual noise.
   struct TreeNode : public T
   {
-    TreeNode* Left()
-    {
-      return (TreeNode*)Trait::GetTreeNode(this).Left();
-    }
+    TreeNode* Left() { return (TreeNode*)Trait::GetTreeNode(this).Left(); }
 
-    void SetLeft(T* aValue)
-    {
-      Trait::GetTreeNode(this).SetLeft(aValue);
-    }
+    void SetLeft(T* aValue) { Trait::GetTreeNode(this).SetLeft(aValue); }
 
-    TreeNode* Right()
-    {
-      return (TreeNode*)Trait::GetTreeNode(this).Right();
-    }
+    TreeNode* Right() { return (TreeNode*)Trait::GetTreeNode(this).Right(); }
 
-    void SetRight(T* aValue)
-    {
-      Trait::GetTreeNode(this).SetRight(aValue);
-    }
+    void SetRight(T* aValue) { Trait::GetTreeNode(this).SetRight(aValue); }
 
-    NodeColor Color()
-    {
-      return Trait::GetTreeNode(this).Color();
-    }
+    NodeColor Color() { return Trait::GetTreeNode(this).Color(); }
 
-    bool IsRed()
-    {
-      return Trait::GetTreeNode(this).IsRed();
-    }
+    bool IsRed() { return Trait::GetTreeNode(this).IsRed(); }
 
-    bool IsBlack()
-    {
-      return Trait::GetTreeNode(this).IsBlack();
-    }
+    bool IsBlack() { return Trait::GetTreeNode(this).IsBlack(); }
 
     void SetColor(NodeColor aColor)
     {
       Trait::GetTreeNode(this).SetColor(aColor);
     }
   };
 
 private:
@@ -334,39 +286,39 @@ private:
     TreeNode *rbp_i_g, *rbp_i_p, *rbp_i_c, *rbp_i_t, *rbp_i_u;
     int rbp_i_cmp = 0;
     rbp_i_g = nullptr;
     rbp_i_p = rbp_i_s.addr();
     rbp_i_p->SetLeft(mRoot);
     rbp_i_p->SetRight(nullptr);
     rbp_i_p->SetColor(NodeColor::Black);
     rbp_i_c = mRoot;
-    /* Iteratively search down the tree for the insertion point,
-     * splitting 4-nodes as they are encountered. At the end of each
-     * iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down
-     * the tree, assuming a sufficiently deep tree. */
+    // Iteratively search down the tree for the insertion point,
+    // splitting 4-nodes as they are encountered. At the end of each
+    // iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down
+    // the tree, assuming a sufficiently deep tree.
     while (rbp_i_c) {
       rbp_i_t = rbp_i_c->Left();
       rbp_i_u = rbp_i_t ? rbp_i_t->Left() : nullptr;
       if (rbp_i_t && rbp_i_u && rbp_i_t->IsRed() && rbp_i_u->IsRed()) {
-        /* rbp_i_c is the top of a logical 4-node, so split it.
-         * This iteration does not move down the tree, due to the
-         * disruptiveness of node splitting.
-         *
-         * Rotate right. */
+        // rbp_i_c is the top of a logical 4-node, so split it.
+        // This iteration does not move down the tree, due to the
+        // disruptiveness of node splitting.
+        //
+        // Rotate right.
         rbp_i_t = RotateRight(rbp_i_c);
-        /* Pass red links up one level. */
+        // Pass red links up one level.
         rbp_i_u = rbp_i_t->Left();
         rbp_i_u->SetColor(NodeColor::Black);
         if (rbp_i_p->Left() == rbp_i_c) {
           rbp_i_p->SetLeft(rbp_i_t);
           rbp_i_c = rbp_i_t;
         } else {
-          /* rbp_i_c was the right child of rbp_i_p, so rotate
-           * left in order to maintain the left-leaning invariant. */
+          // rbp_i_c was the right child of rbp_i_p, so rotate
+          // left in order to maintain the left-leaning invariant.
           MOZ_ASSERT(rbp_i_p->Right() == rbp_i_c);
           rbp_i_p->SetRight(rbp_i_t);
           rbp_i_u = LeanLeft(rbp_i_p);
           if (rbp_i_g->Left() == rbp_i_p) {
             rbp_i_g->SetLeft(rbp_i_u);
           } else {
             MOZ_ASSERT(rbp_i_g->Right() == rbp_i_p);
             rbp_i_g->SetRight(rbp_i_u);
@@ -387,32 +339,32 @@ private:
       rbp_i_cmp = Trait::Compare(aNode, rbp_i_c);
       if (rbp_i_cmp < 0) {
         rbp_i_c = rbp_i_c->Left();
       } else {
         MOZ_ASSERT(rbp_i_cmp > 0);
         rbp_i_c = rbp_i_c->Right();
       }
     }
-    /* rbp_i_p now refers to the node under which to insert. */
+    // rbp_i_p now refers to the node under which to insert.
     aNode->SetLeft(nullptr);
     aNode->SetRight(nullptr);
     aNode->SetColor(NodeColor::Red);
     if (rbp_i_cmp > 0) {
       rbp_i_p->SetRight(aNode);
       rbp_i_t = LeanLeft(rbp_i_p);
       if (rbp_i_g->Left() == rbp_i_p) {
         rbp_i_g->SetLeft(rbp_i_t);
       } else if (rbp_i_g->Right() == rbp_i_p) {
         rbp_i_g->SetRight(rbp_i_t);
       }
     } else {
       rbp_i_p->SetLeft(aNode);
     }
-    /* Update the root and make sure that it is black. */
+    // Update the root and make sure that it is black.
     mRoot = rbp_i_s.addr()->Left();
     mRoot->SetColor(NodeColor::Black);
   }
 
   void Remove(TreeNode* aNode)
   {
     // rbp_r_s is only used as a placeholder for its RedBlackTreeNode. Use
     // AlignedStorage2 to avoid running the TreeNode base class constructor.
@@ -420,98 +372,98 @@ private:
     TreeNode *rbp_r_p, *rbp_r_c, *rbp_r_xp, *rbp_r_t, *rbp_r_u;
     int rbp_r_cmp;
     rbp_r_p = rbp_r_s.addr();
     rbp_r_p->SetLeft(mRoot);
     rbp_r_p->SetRight(nullptr);
     rbp_r_p->SetColor(NodeColor::Black);
     rbp_r_c = mRoot;
     rbp_r_xp = nullptr;
-    /* Iterate down the tree, but always transform 2-nodes to 3- or
-     * 4-nodes in order to maintain the invariant that the current
-     * node is not a 2-node. This allows simple deletion once a leaf
-     * is reached. Handle the root specially though, since there may
-     * be no way to convert it from a 2-node to a 3-node. */
+    // Iterate down the tree, but always transform 2-nodes to 3- or
+    // 4-nodes in order to maintain the invariant that the current
+    // node is not a 2-node. This allows simple deletion once a leaf
+    // is reached. Handle the root specially though, since there may
+    // be no way to convert it from a 2-node to a 3-node.
     rbp_r_cmp = Trait::Compare(aNode, rbp_r_c);
     if (rbp_r_cmp < 0) {
       rbp_r_t = rbp_r_c->Left();
       rbp_r_u = rbp_r_t ? rbp_r_t->Left() : nullptr;
       if ((!rbp_r_t || rbp_r_t->IsBlack()) &&
           (!rbp_r_u || rbp_r_u->IsBlack())) {
-        /* Apply standard transform to prepare for left move. */
+        // Apply standard transform to prepare for left move.
         rbp_r_t = MoveRedLeft(rbp_r_c);
         rbp_r_t->SetColor(NodeColor::Black);
         rbp_r_p->SetLeft(rbp_r_t);
         rbp_r_c = rbp_r_t;
       } else {
-        /* Move left. */
+        // Move left.
         rbp_r_p = rbp_r_c;
         rbp_r_c = rbp_r_c->Left();
       }
     } else {
       if (rbp_r_cmp == 0) {
         MOZ_ASSERT(aNode == rbp_r_c);
         if (!rbp_r_c->Right()) {
-          /* Delete root node (which is also a leaf node). */
+          // Delete root node (which is also a leaf node).
           if (rbp_r_c->Left()) {
             rbp_r_t = LeanRight(rbp_r_c);
             rbp_r_t->SetRight(nullptr);
           } else {
             rbp_r_t = nullptr;
           }
           rbp_r_p->SetLeft(rbp_r_t);
         } else {
-          /* This is the node we want to delete, but we will
-           * instead swap it with its successor and delete the
-           * successor. Record enough information to do the
-           * swap later. rbp_r_xp is the aNode's parent. */
+          // This is the node we want to delete, but we will
+          // instead swap it with its successor and delete the
+          // successor. Record enough information to do the
+          // swap later. rbp_r_xp is the aNode's parent.
           rbp_r_xp = rbp_r_p;
-          rbp_r_cmp = 1; /* Note that deletion is incomplete. */
+          rbp_r_cmp = 1; // Note that deletion is incomplete.
         }
       }
       if (rbp_r_cmp == 1) {
         if (rbp_r_c->Right() && (!rbp_r_c->Right()->Left() ||
                                  rbp_r_c->Right()->Left()->IsBlack())) {
           rbp_r_t = rbp_r_c->Left();
           if (rbp_r_t->IsRed()) {
-            /* Standard transform. */
+            // Standard transform.
             rbp_r_t = MoveRedRight(rbp_r_c);
           } else {
-            /* Root-specific transform. */
+            // Root-specific transform.
             rbp_r_c->SetColor(NodeColor::Red);
             rbp_r_u = rbp_r_t->Left();
             if (rbp_r_u && rbp_r_u->IsRed()) {
               rbp_r_u->SetColor(NodeColor::Black);
               rbp_r_t = RotateRight(rbp_r_c);
               rbp_r_u = RotateLeft(rbp_r_c);
               rbp_r_t->SetRight(rbp_r_u);
             } else {
               rbp_r_t->SetColor(NodeColor::Red);
               rbp_r_t = RotateLeft(rbp_r_c);
             }
           }
           rbp_r_p->SetLeft(rbp_r_t);
           rbp_r_c = rbp_r_t;
         } else {
-          /* Move right. */
+          // Move right.
           rbp_r_p = rbp_r_c;
           rbp_r_c = rbp_r_c->Right();
         }
       }
     }
     if (rbp_r_cmp != 0) {
       while (true) {
         MOZ_ASSERT(rbp_r_p);
         rbp_r_cmp = Trait::Compare(aNode, rbp_r_c);
         if (rbp_r_cmp < 0) {
           rbp_r_t = rbp_r_c->Left();
           if (!rbp_r_t) {
-            /* rbp_r_c now refers to the successor node to
-             * relocate, and rbp_r_xp/aNode refer to the
-             * context for the relocation. */
+            // rbp_r_c now refers to the successor node to
+            // relocate, and rbp_r_xp/aNode refer to the
+            // context for the relocation.
             if (rbp_r_xp->Left() == aNode) {
               rbp_r_xp->SetLeft(rbp_r_c);
             } else {
               MOZ_ASSERT(rbp_r_xp->Right() == (aNode));
               rbp_r_xp->SetRight(rbp_r_c);
             }
             rbp_r_c->SetLeft(aNode->Left());
             rbp_r_c->SetRight(aNode->Right());
@@ -533,40 +485,40 @@ private:
               rbp_r_p->SetRight(rbp_r_t);
             }
             rbp_r_c = rbp_r_t;
           } else {
             rbp_r_p = rbp_r_c;
             rbp_r_c = rbp_r_c->Left();
           }
         } else {
-          /* Check whether to delete this node (it has to be
-           * the correct node and a leaf node). */
+          // Check whether to delete this node (it has to be
+          // the correct node and a leaf node).
           if (rbp_r_cmp == 0) {
             MOZ_ASSERT(aNode == rbp_r_c);
             if (!rbp_r_c->Right()) {
-              /* Delete leaf node. */
+              // Delete leaf node.
               if (rbp_r_c->Left()) {
                 rbp_r_t = LeanRight(rbp_r_c);
                 rbp_r_t->SetRight(nullptr);
               } else {
                 rbp_r_t = nullptr;
               }
               if (rbp_r_p->Left() == rbp_r_c) {
                 rbp_r_p->SetLeft(rbp_r_t);
               } else {
                 rbp_r_p->SetRight(rbp_r_t);
               }
               break;
             }
-            /* This is the node we want to delete, but we
-             * will instead swap it with its successor
-             * and delete the successor. Record enough
-             * information to do the swap later.
-             * rbp_r_xp is aNode's parent. */
+            // This is the node we want to delete, but we
+            // will instead swap it with its successor
+            // and delete the successor. Record enough
+            // information to do the swap later.
+            // rbp_r_xp is aNode's parent.
             rbp_r_xp = rbp_r_p;
           }
           rbp_r_t = rbp_r_c->Right();
           rbp_r_u = rbp_r_t->Left();
           if (!rbp_r_u || rbp_r_u->IsBlack()) {
             rbp_r_t = MoveRedRight(rbp_r_c);
             if (rbp_r_p->Left() == rbp_r_c) {
               rbp_r_p->SetLeft(rbp_r_t);
@@ -576,17 +528,17 @@ private:
             rbp_r_c = rbp_r_t;
           } else {
             rbp_r_p = rbp_r_c;
             rbp_r_c = rbp_r_c->Right();
           }
         }
       }
     }
-    /* Update root. */
+    // Update root.
     mRoot = rbp_r_s.addr()->Left();
   }
 
   TreeNode* RotateLeft(TreeNode* aNode)
   {
     TreeNode* node = aNode->Right();
     aNode->SetRight(node->Left());
     node->SetLeft(aNode);
@@ -682,53 +634,49 @@ private:
         node->SetRight(rbp_mrr_t);
       } else {
         node = RotateLeft(aNode);
       }
     }
     return node;
   }
 
-  /*
-   * The iterator simulates recursion via an array of pointers that store the
-   * current path.  This is critical to performance, since a series of calls to
-   * rb_{next,prev}() would require time proportional to (n lg n), whereas this
-   * implementation only requires time proportional to (n).
-   *
-   * Since the iterator caches a path down the tree, any tree modification may
-   * cause the cached path to become invalid. Don't modify the tree during an
-   * iteration.
-   */
+  // The iterator simulates recursion via an array of pointers that store the
+  // current path.  This is critical to performance, since a series of calls to
+  // rb_{next,prev}() would require time proportional to (n lg n), whereas this
+  // implementation only requires time proportional to (n).
+  //
+  // Since the iterator caches a path down the tree, any tree modification may
+  // cause the cached path to become invalid. Don't modify the tree during an
+  // iteration.
 
-  /*
-   * Size the path arrays such that they are always large enough, even if a
-   * tree consumes all of memory.  Since each node must contain a minimum of
-   * two pointers, there can never be more nodes than:
-   *
-   *   1 << ((sizeof(void*)<<3) - (log2(sizeof(void*))+1))
-   *
-   * Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
-   * is:
-   *
-   *   (3 * ((sizeof(void*)<<3) - (log2(sizeof(void*))+1)))
-   *
-   * This works out to a maximum depth of 87 and 180 for 32- and 64-bit
-   * systems, respectively (approximately 348 and 1440 bytes, respectively).
-   */
+  // Size the path arrays such that they are always large enough, even if a
+  // tree consumes all of memory.  Since each node must contain a minimum of
+  // two pointers, there can never be more nodes than:
+  //
+  //   1 << ((sizeof(void*)<<3) - (log2(sizeof(void*))+1))
+  //
+  // Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
+  // is:
+  //
+  //   (3 * ((sizeof(void*)<<3) - (log2(sizeof(void*))+1)))
+  //
+  // This works out to a maximum depth of 87 and 180 for 32- and 64-bit
+  // systems, respectively (approximately 348 and 1440 bytes, respectively).
 public:
   class Iterator
   {
     TreeNode* mPath[3 * ((sizeof(void*) << 3) - (LOG2(sizeof(void*)) + 1))];
     unsigned mDepth;
 
   public:
     explicit Iterator(RedBlackTree<T, Trait>* aTree)
       : mDepth(0)
     {
-      /* Initialize the path to contain the left spine. */
+      // Initialize the path to contain the left spine.
       if (aTree->mRoot) {
         TreeNode* node;
         mPath[mDepth++] = aTree->mRoot;
         while ((node = mPath[mDepth - 1]->Left())) {
           mPath[mDepth++] = node;
         }
       }
     }
@@ -738,17 +686,18 @@ public:
     {
       Iterator* mIterator;
       T* mItem;
 
     public:
       Item(Iterator* aIterator, T* aItem)
         : mIterator(aIterator)
         , mItem(aItem)
-      { }
+      {
+      }
 
       bool operator!=(const Item& aOther) const
       {
         return (mIterator != aOther.mIterator) || (mItem != aOther.mItem);
       }
 
       T* operator*() const { return mItem; }
 
@@ -759,39 +708,36 @@ public:
       }
     };
 
     Item<Iterator> begin()
     {
       return Item<Iterator>(this, mDepth > 0 ? mPath[mDepth - 1] : nullptr);
     }
 
-    Item<Iterator> end()
-    {
-      return Item<Iterator>(this, nullptr);
-    }
+    Item<Iterator> end() { return Item<Iterator>(this, nullptr); }
 
     TreeNode* Next()
     {
       TreeNode* node;
       if ((node = mPath[mDepth - 1]->Right())) {
-        /* The successor is the left-most node in the right subtree. */
+        // The successor is the left-most node in the right subtree.
         mPath[mDepth++] = node;
         while ((node = mPath[mDepth - 1]->Left())) {
           mPath[mDepth++] = node;
         }
       } else {
-        /* The successor is above the current node.  Unwind until a
-         * left-leaning edge is removed from the path, of the path is empty. */
+        // The successor is above the current node.  Unwind until a
+        // left-leaning edge is removed from the path, of the path is empty.
         for (mDepth--; mDepth > 0; mDepth--) {
           if (mPath[mDepth - 1]->Left() == mPath[mDepth]) {
             break;
           }
         }
       }
       return mDepth > 0 ? mPath[mDepth - 1] : nullptr;
     }
   };
 
   Iterator iter() { return Iterator(this); }
 };
 
-#endif /* RB_H_ */
+#endif // RB_H_
--- a/memory/build/replace_malloc.h
+++ b/memory/build/replace_malloc.h
@@ -1,96 +1,96 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
+ * 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 replace_malloc_h
 #define replace_malloc_h
 
-/*
- * The replace_malloc facility allows an external library to replace or
- * supplement the jemalloc implementation.
- *
- * The external library may be hooked by setting one of the following
- * environment variables to the library path:
- *   - LD_PRELOAD on Linux,
- *   - DYLD_INSERT_LIBRARIES on OSX,
- *   - MOZ_REPLACE_MALLOC_LIB on Windows and Android.
- *
- * An initialization function is called before any malloc replacement
- * function, and has the following declaration:
- *
- *   void replace_init(const malloc_table_t *)
- *
- * The const malloc_table_t pointer given to that function is a table
- * containing pointers to the original jemalloc implementation, so that
- * replacement functions can call them back if they need to. The pointer
- * itself can safely be kept around (no need to copy the table itself).
- *
- * The functions to be implemented in the external library are of the form:
- *
- *   void *replace_malloc(size_t size)
- *   {
- *     // Fiddle with the size if necessary.
- *     // orig->malloc doesn't have to be called if the external library
- *     // provides its own allocator, but in this case it will have to
- *     // implement all functions.
- *     void *ptr = orig->malloc(size);
- *     // Do whatever you want with the ptr.
- *     return ptr;
- *   }
- *
- * where "orig" is the pointer obtained from replace_init.
- *
- * See malloc_decls.h for a list of functions that can be replaced this
- * way. The implementations are all in the form:
- *   return_type replace_name(arguments [,...])
- *
- * They don't all need to be provided.
- *
- * Building a replace-malloc library is like rocket science. It can end up
- * with things blowing up, especially when trying to use complex types, and
- * even more especially when these types come from XPCOM or other parts of the
- * Mozilla codebase.
- * It is recommended to add the following to a replace-malloc implementation's
- * moz.build:
- *   DISABLE_STL_WRAPPING = True # Avoid STL wrapping
- *
- * If your replace-malloc implementation lives under memory/replace, these
- * are taken care of by memory/replace/defs.mk.
- */
+// The replace_malloc facility allows an external library to replace or
+// supplement the jemalloc implementation.
+//
+// The external library may be hooked by setting one of the following
+// environment variables to the library path:
+//   - LD_PRELOAD on Linux,
+//   - DYLD_INSERT_LIBRARIES on OSX,
+//   - MOZ_REPLACE_MALLOC_LIB on Windows and Android.
+//
+// An initialization function is called before any malloc replacement
+// function, and has the following declaration:
+//
+//   void replace_init(const malloc_table_t *)
+//
+// The const malloc_table_t pointer given to that function is a table
+// containing pointers to the original jemalloc implementation, so that
+// replacement functions can call them back if they need to. The pointer
+// itself can safely be kept around (no need to copy the table itself).
+//
+// The functions to be implemented in the external library are of the form:
+//
+//   void *replace_malloc(size_t size)
+//   {
+//     // Fiddle with the size if necessary.
+//     // orig->malloc doesn't have to be called if the external library
+//     // provides its own allocator, but in this case it will have to
+//     // implement all functions.
+//     void *ptr = orig->malloc(size);
+//     // Do whatever you want with the ptr.
+//     return ptr;
+//   }
+//
+// where "orig" is the pointer obtained from replace_init.
+//
+// See malloc_decls.h for a list of functions that can be replaced this
+// way. The implementations are all in the form:
+//   return_type replace_name(arguments [,...])
+//
+// They don't all need to be provided.
+//
+// Building a replace-malloc library is like rocket science. It can end up
+// with things blowing up, especially when trying to use complex types, and
+// even more especially when these types come from XPCOM or other parts of the
+// Mozilla codebase.
+// It is recommended to add the following to a replace-malloc implementation's
+// moz.build:
+//   DISABLE_STL_WRAPPING = True # Avoid STL wrapping
+//
+// If your replace-malloc implementation lives under memory/replace, these
+// are taken care of by memory/replace/defs.mk.
 
 #ifdef replace_malloc_bridge_h
 #error Do not include replace_malloc_bridge.h before replace_malloc.h. \
   In fact, you only need the latter.
 #endif
 
 #define REPLACE_MALLOC_IMPL
 
 #include "replace_malloc_bridge.h"
 
-/* Implementing a replace-malloc library is incompatible with using mozalloc. */
+// Implementing a replace-malloc library is incompatible with using mozalloc.
 #define MOZ_NO_MOZALLOC 1
 
 #include "mozilla/Types.h"
 
 MOZ_BEGIN_EXTERN_C
 
-/* MOZ_NO_REPLACE_FUNC_DECL and MOZ_REPLACE_WEAK are only defined in
- * replace_malloc.c. Normally including this header will add function
- * definitions. */
+// MOZ_NO_REPLACE_FUNC_DECL and MOZ_REPLACE_WEAK are only defined in
+// replace_malloc.c. Normally including this header will add function
+// definitions.
 #ifndef MOZ_NO_REPLACE_FUNC_DECL
 
-#  ifndef MOZ_REPLACE_WEAK
-#    define MOZ_REPLACE_WEAK
-#  endif
+#ifndef MOZ_REPLACE_WEAK
+#define MOZ_REPLACE_WEAK
+#endif
 
-#  define MALLOC_DECL(name, return_type, ...) \
-    MOZ_EXPORT return_type replace_ ## name(__VA_ARGS__) MOZ_REPLACE_WEAK;
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  MOZ_EXPORT return_type replace_##name(__VA_ARGS__) MOZ_REPLACE_WEAK;
 
-#  define MALLOC_FUNCS MALLOC_FUNCS_ALL
-#  include "malloc_decls.h"
+#define MALLOC_FUNCS MALLOC_FUNCS_ALL
+#include "malloc_decls.h"
 
-#endif /* MOZ_NO_REPLACE_FUNC_DECL */
+#endif // MOZ_NO_REPLACE_FUNC_DECL
 
 MOZ_END_EXTERN_C
 
-#endif /* replace_malloc_h */
+#endif // replace_malloc_h
--- a/memory/build/replace_malloc_bridge.h
+++ b/memory/build/replace_malloc_bridge.h
@@ -1,216 +1,225 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
+ * 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 replace_malloc_bridge_h
 #define replace_malloc_bridge_h
 
-/*
- * The replace-malloc bridge allows bidirectional method calls between
- * a program and the replace-malloc library that has been loaded for it.
- * In Firefox, this is used to allow method calls between code in libxul
- * and code in the replace-malloc library, without libxul needing to link
- * against that library or vice-versa.
- *
- * Subsystems can add methods for their own need. Replace-malloc libraries
- * can decide to implement those methods or not.
- *
- * Replace-malloc libraries can provide such a bridge by implementing
- * a ReplaceMallocBridge-derived class, and a replace_get_bridge function
- * returning an instance of that class. The default methods in
- * ReplaceMallocBridge are expected to return values that callers would
- * understand as "the bridge doesn't implement this method", so that a
- * replace-malloc library doesn't have to implement all methods.
- *
- * The ReplaceMallocBridge class contains definitions for methods for
- * all replace-malloc libraries. Each library picks the methods it wants
- * to reply to in its ReplaceMallocBridge-derived class instance.
- * All methods of ReplaceMallocBridge must be virtual. Similarly,
- * anything passed as an argument to those methods must be plain data, or
- * an instance of a class with only virtual methods.
- *
- * Binary compatibility is expected to be maintained, such that a newer
- * Firefox can be used with an old replace-malloc library, or an old
- * Firefox can be used with a newer replace-malloc library. As such, only
- * new virtual methods should be added to ReplaceMallocBridge, and
- * each change should have a corresponding bump of the mVersion value.
- * At the same time, each virtual method should have a corresponding
- * wrapper calling the virtual method on the instance from
- * ReplaceMallocBridge::Get(), giving it the version the virtual method
- * was added.
- *
- * Parts that are not relevant to the replace-malloc library end of the
- * bridge are hidden when REPLACE_MALLOC_IMPL is not defined, which is
- * the case when including replace_malloc.h.
- */
+// The replace-malloc bridge allows bidirectional method calls between
+// a program and the replace-malloc library that has been loaded for it.
+// In Firefox, this is used to allow method calls between code in libxul
+// and code in the replace-malloc library, without libxul needing to link
+// against that library or vice-versa.
+//
+// Subsystems can add methods for their own need. Replace-malloc libraries
+// can decide to implement those methods or not.
+//
+// Replace-malloc libraries can provide such a bridge by implementing
+// a ReplaceMallocBridge-derived class, and a replace_get_bridge function
+// returning an instance of that class. The default methods in
+// ReplaceMallocBridge are expected to return values that callers would
+// understand as "the bridge doesn't implement this method", so that a
+// replace-malloc library doesn't have to implement all methods.
+//
+// The ReplaceMallocBridge class contains definitions for methods for
+// all replace-malloc libraries. Each library picks the methods it wants
+// to reply to in its ReplaceMallocBridge-derived class instance.
+// All methods of ReplaceMallocBridge must be virtual. Similarly,
+// anything passed as an argument to those methods must be plain data, or
+// an instance of a class with only virtual methods.
+//
+// Binary compatibility is expected to be maintained, such that a newer
+// Firefox can be used with an old replace-malloc library, or an old
+// Firefox can be used with a newer replace-malloc library. As such, only
+// new virtual methods should be added to ReplaceMallocBridge, and
+// each change should have a corresponding bump of the mVersion value.
+// At the same time, each virtual method should have a corresponding
+// wrapper calling the virtual method on the instance from
+// ReplaceMallocBridge::Get(), giving it the version the virtual method
+// was added.
+//
+// Parts that are not relevant to the replace-malloc library end of the
+// bridge are hidden when REPLACE_MALLOC_IMPL is not defined, which is
+// the case when including replace_malloc.h.
 
 struct ReplaceMallocBridge;
 
 #include "mozilla/Types.h"
 
 MOZ_BEGIN_EXTERN_C
 
 #ifndef REPLACE_MALLOC_IMPL
-/* Returns the replace-malloc bridge if there is one to be returned. */
-MFBT_API ReplaceMallocBridge* get_bridge();
+// Returns the replace-malloc bridge if there is one to be returned.
+MFBT_API ReplaceMallocBridge*
+get_bridge();
 #endif
 
-/* Table of malloc functions.
- *   e.g. void* (*malloc)(size_t), etc.
- */
-#define MALLOC_DECL(name, return_type, ...) \
-  typedef return_type(name ## _impl_t)(__VA_ARGS__);
+// Table of malloc functions.
+//   e.g. void* (*malloc)(size_t), etc.
+
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  typedef return_type(name##_impl_t)(__VA_ARGS__);
 
 #include "malloc_decls.h"
 
-#define MALLOC_DECL(name, return_type, ...) \
-  name ## _impl_t * name;
+#define MALLOC_DECL(name, return_type, ...) name##_impl_t* name;
 
-typedef struct {
+typedef struct
+{
 #include "malloc_decls.h"
 } malloc_table_t;
 
 MOZ_END_EXTERN_C
 
 #ifdef __cplusplus
 
-/* Table of malloc hook functions.
- * Those functions are called with the arguments and results of malloc
- * functions after they are called.
- *   e.g. void* (*malloc_hook)(void*, size_t), etc.
- * They can either return the result they're given, or alter it before
- * returning it.
- * The hooks corresponding to functions, like free(void*), that return no
- * value, don't take an extra argument.
- * The table must at least contain a pointer for malloc_hook and free_hook
- * functions. They will be used as fallback if no pointer is given for
- * other allocation functions, like calloc_hook.
- */
+// Table of malloc hook functions.
+// Those functions are called with the arguments and results of malloc
+// functions after they are called.
+//   e.g. void* (*malloc_hook)(void*, size_t), etc.
+// They can either return the result they're given, or alter it before
+// returning it.
+// The hooks corresponding to functions, like free(void*), that return no
+// value, don't take an extra argument.
+// The table must at least contain a pointer for malloc_hook and free_hook
+// functions. They will be used as fallback if no pointer is given for
+// other allocation functions, like calloc_hook.
 namespace mozilla {
 namespace detail {
-template <typename R, typename... Args>
-struct AllocHookType {
+template<typename R, typename... Args>
+struct AllocHookType
+{
   using Type = R (*)(R, Args...);
 };
 
-template <typename... Args>
+template<typename... Args>
 struct AllocHookType<void, Args...>
 {
   using Type = void (*)(Args...);
 };
 
 } // namespace detail
 } // namespace mozilla
 
-#define MALLOC_DECL(name, return_type, ...) \
-  typename mozilla::detail::AllocHookType<return_type, ##__VA_ARGS__>::Type \
-    name ## _hook;
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  typename mozilla::detail::AllocHookType<return_type, ##__VA_ARGS__>::Type    \
+    name##_hook;
 
-typedef struct {
+typedef struct
+{
 #include "malloc_decls.h"
-  /* Like free_hook, but called before realloc_hook. free_hook is called
-   * instead of not given. */
+  // Like free_hook, but called before realloc_hook. free_hook is called
+  // instead of not given.
   void (*realloc_hook_before)(void* aPtr);
 } malloc_hook_table_t;
 
 namespace mozilla {
 namespace dmd {
 struct DMDFuncs;
 } // namespace dmd
 
-/* Callbacks to register debug file handles for Poison IO interpose.
- * See Mozilla(|Un)RegisterDebugHandle in xpcom/build/PoisonIOInterposer.h */
+// Callbacks to register debug file handles for Poison IO interpose.
+// See Mozilla(|Un)RegisterDebugHandle in xpcom/build/PoisonIOInterposer.h
 struct DebugFdRegistry
 {
   virtual void RegisterHandle(intptr_t aFd);
 
   virtual void UnRegisterHandle(intptr_t aFd);
 };
 
 } // namespace mozilla
 
 struct ReplaceMallocBridge
 {
-  ReplaceMallocBridge() : mVersion(3) {}
+  ReplaceMallocBridge()
+    : mVersion(3)
+  {
+  }
 
-  /* This method was added in version 1 of the bridge. */
+  // This method was added in version 1 of the bridge.
   virtual mozilla::dmd::DMDFuncs* GetDMDFuncs() { return nullptr; }
 
-  /* Send a DebugFdRegistry instance to the replace-malloc library so that
-   * it can register/unregister file descriptors whenever needed. The
-   * instance is valid until the process dies.
-   * This method was added in version 2 of the bridge. */
+  // Send a DebugFdRegistry instance to the replace-malloc library so that
+  // it can register/unregister file descriptors whenever needed. The
+  // instance is valid until the process dies.
+  // This method was added in version 2 of the bridge.
   virtual void InitDebugFd(mozilla::DebugFdRegistry&) {}
 
-  /* Register a list of malloc functions and hook functions to the
-   * replace-malloc library so that it can choose to dispatch to them
-   * when needed. The details of what is dispatched when is left to the
-   * replace-malloc library.
-   * Passing a nullptr for either table will unregister a previously
-   * registered table under the same name.
-   * Returns nullptr if registration failed.
-   * If registration succeeded, a table of "pure" malloc functions is
-   * returned. Those "pure" malloc functions won't call hooks.
-   * /!\ Do not rely on registration/unregistration to be instantaneous.
-   * Functions from a previously registered table may still be called for
-   * a brief time after RegisterHook returns.
-   * This method was added in version 3 of the bridge. */
-  virtual const malloc_table_t*
-  RegisterHook(const char* aName, const malloc_table_t* aTable,
-               const malloc_hook_table_t* aHookTable) { return nullptr; }
+  // Register a list of malloc functions and hook functions to the
+  // replace-malloc library so that it can choose to dispatch to them
+  // when needed. The details of what is dispatched when is left to the
+  // replace-malloc library.
+  // Passing a nullptr for either table will unregister a previously
+  // registered table under the same name.
+  // Returns nullptr if registration failed.
+  // If registration succeeded, a table of "pure" malloc functions is
+  // returned. Those "pure" malloc functions won't call hooks.
+  // /!\ Do not rely on registration/unregistration to be instantaneous.
+  // Functions from a previously registered table may still be called for
+  // a brief time after RegisterHook returns.
+  // This method was added in version 3 of the bridge.
+  virtual const malloc_table_t* RegisterHook(
+    const char* aName,
+    const malloc_table_t* aTable,
+    const malloc_hook_table_t* aHookTable)
+  {
+    return nullptr;
+  }
 
 #ifndef REPLACE_MALLOC_IMPL
-  /* Returns the replace-malloc bridge if its version is at least the
-   * requested one. */
-  static ReplaceMallocBridge* Get(int aMinimumVersion) {
+  // Returns the replace-malloc bridge if its version is at least the
+  // requested one.
+  static ReplaceMallocBridge* Get(int aMinimumVersion)
+  {
     static ReplaceMallocBridge* sSingleton = get_bridge();
-    return (sSingleton && sSingleton->mVersion >= aMinimumVersion)
-      ? sSingleton : nullptr;
+    return (sSingleton && sSingleton->mVersion >= aMinimumVersion) ? sSingleton
+                                                                   : nullptr;
   }
 #endif
 
 protected:
   const int mVersion;
 };
 
 #ifndef REPLACE_MALLOC_IMPL
-/* Class containing wrappers for calls to ReplaceMallocBridge methods.
- * Those wrappers need to be static methods in a class because compilers
- * complain about unused static global functions, and linkers complain
- * about multiple definitions of non-static global functions.
- * Using a separate class from ReplaceMallocBridge allows the function
- * names to be identical. */
+// Class containing wrappers for calls to ReplaceMallocBridge methods.
+// Those wrappers need to be static methods in a class because compilers
+// complain about unused static global functions, and linkers complain
+// about multiple definitions of non-static global functions.
+// Using a separate class from ReplaceMallocBridge allows the function
+// names to be identical.
 struct ReplaceMalloc
 {
-  /* Don't call this method from performance critical code. Use
-   * mozilla::dmd::DMDFuncs::Get() instead, it has less overhead. */
+  // Don't call this method from performance critical code. Use
+  // mozilla::dmd::DMDFuncs::Get() instead, it has less overhead.
   static mozilla::dmd::DMDFuncs* GetDMDFuncs()
   {
     auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 1);
     return singleton ? singleton->GetDMDFuncs() : nullptr;
   }
 
   static void InitDebugFd(mozilla::DebugFdRegistry& aRegistry)
   {
     auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 2);
     if (singleton) {
       singleton->InitDebugFd(aRegistry);
     }
   }
 
-  static const malloc_table_t*
-  RegisterHook(const char* aName, const malloc_table_t* aTable,
-               const malloc_hook_table_t* aHookTable)
+  static const malloc_table_t* RegisterHook(
+    const char* aName,
+    const malloc_table_t* aTable,
+    const malloc_hook_table_t* aHookTable)
   {
     auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 3);
     return singleton ? singleton->RegisterHook(aName, aTable, aHookTable)
                      : nullptr;
   }
 };
 #endif
 
-#endif /* __cplusplus */
+#endif // __cplusplus
 
-#endif /* replace_malloc_bridge_h */
+#endif // replace_malloc_bridge_h
--- a/memory/build/zone.c
+++ b/memory/build/zone.c
@@ -1,138 +1,155 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
+ * 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 "mozmemory_wrap.h"
 
 #include <stdlib.h>
 #include <mach/mach_types.h>
 #include "mozilla/Assertions.h"
 
-/*
- * Malloc implementation functions are MOZ_MEMORY_API, and jemalloc
- * specific functions MOZ_JEMALLOC_API; see mozmemory_wrap.h
- */
-#define MALLOC_DECL(name, return_type, ...) \
-  MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
+// Malloc implementation functions are MOZ_MEMORY_API, and jemalloc
+// specific functions MOZ_JEMALLOC_API; see mozmemory_wrap.h
+
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__);
 #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
 #include "malloc_decls.h"
 
-#define MALLOC_DECL(name, return_type, ...) \
-  MOZ_JEMALLOC_API return_type name ## _impl(__VA_ARGS__);
+#define MALLOC_DECL(name, return_type, ...)                                    \
+  MOZ_JEMALLOC_API return_type name##_impl(__VA_ARGS__);
 #define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
 #include "malloc_decls.h"
 
-/*
- * Definitions of the following structs in malloc/malloc.h might be too old
- * for the built binary to run on newer versions of OSX. So use the newest
- * possible version of those structs.
- */
-typedef struct _malloc_zone_t {
-  void *reserved1;
-  void *reserved2;
-  size_t (*size)(struct _malloc_zone_t *, const void *);
-  void *(*malloc)(struct _malloc_zone_t *, size_t);
-  void *(*calloc)(struct _malloc_zone_t *, size_t, size_t);
-  void *(*valloc)(struct _malloc_zone_t *, size_t);
-  void (*free)(struct _malloc_zone_t *, void *);
-  void *(*realloc)(struct _malloc_zone_t *, void *, size_t);
-  void (*destroy)(struct _malloc_zone_t *);
-  const char *zone_name;
-  unsigned (*batch_malloc)(struct _malloc_zone_t *, size_t, void **, unsigned);
-  void (*batch_free)(struct _malloc_zone_t *, void **, unsigned);
-  struct malloc_introspection_t *introspect;
+// Definitions of the following structs in malloc/malloc.h might be too old
+// for the built binary to run on newer versions of OSX. So use the newest
+// possible version of those structs.
+
+typedef struct _malloc_zone_t
+{
+  void* reserved1;
+  void* reserved2;
+  size_t (*size)(struct _malloc_zone_t*, const void*);
+  void* (*malloc)(struct _malloc_zone_t*, size_t);
+  void* (*calloc)(struct _malloc_zone_t*, size_t, size_t);
+  void* (*valloc)(struct _malloc_zone_t*, size_t);
+  void (*free)(struct _malloc_zone_t*, void*);
+  void* (*realloc)(struct _malloc_zone_t*, void*, size_t);
+  void (*destroy)(struct _malloc_zone_t*);
+  const char* zone_name;
+  unsigned (*batch_malloc)(struct _malloc_zone_t*, size_t, void**, unsigned);
+  void (*batch_free)(struct _malloc_zone_t*, void**, unsigned);
+  struct malloc_introspection_t* introspect;
   unsigned version;
-  void *(*memalign)(struct _malloc_zone_t *, size_t, size_t);
-  void (*free_definite_size)(struct _malloc_zone_t *, void *, size_t);
-  size_t (*pressure_relief)(struct _malloc_zone_t *, size_t);
+  void* (*memalign)(struct _malloc_zone_t*, size_t, size_t);
+  void (*free_definite_size)(struct _malloc_zone_t*, void*, size_t);
+  size_t (*pressure_relief)(struct _malloc_zone_t*, size_t);
 } malloc_zone_t;
 
-typedef struct {
+typedef struct
+{
   vm_address_t address;
   vm_size_t size;
 } vm_range_t;
 
-typedef struct malloc_statistics_t {
+typedef struct malloc_statistics_t
+{
   unsigned blocks_in_use;
   size_t size_in_use;
   size_t max_size_in_use;
   size_t size_allocated;
 } malloc_statistics_t;
 
-typedef kern_return_t memory_reader_t(task_t, vm_address_t, vm_size_t, void **);
+typedef kern_return_t
+memory_reader_t(task_t, vm_address_t, vm_size_t, void**);
 
-typedef void vm_range_recorder_t(task_t, void *, unsigned type, vm_range_t *, unsigned);
+typedef void
+vm_range_recorder_t(task_t, void*, unsigned type, vm_range_t*, unsigned);
 
-typedef struct malloc_introspection_t {
-  kern_return_t (*enumerator)(task_t, void *, unsigned, vm_address_t, memory_reader_t, vm_range_recorder_t);
-  size_t (*good_size)(malloc_zone_t *, size_t);
-  boolean_t (*check)(malloc_zone_t *);
-  void (*print)(malloc_zone_t *, boolean_t);
-  void (*log)(malloc_zone_t *, void *);
-  void (*force_lock)(malloc_zone_t *);
-  void (*force_unlock)(malloc_zone_t *);
-  void (*statistics)(malloc_zone_t *, malloc_statistics_t *);
-  boolean_t (*zone_locked)(malloc_zone_t *);
-  boolean_t (*enable_discharge_checking)(malloc_zone_t *);
-  boolean_t (*disable_discharge_checking)(malloc_zone_t *);
-  void (*discharge)(malloc_zone_t *, void *);
+typedef struct malloc_introspection_t
+{
+  kern_return_t (*enumerator)(task_t,
+                              void*,
+                              unsigned,
+                              vm_address_t,
+                              memory_reader_t,
+                              vm_range_recorder_t);
+  size_t (*good_size)(malloc_zone_t*, size_t);
+  boolean_t (*check)(malloc_zone_t*);
+  void (*print)(malloc_zone_t*, boolean_t);
+  void (*log)(malloc_zone_t*, void*);
+  void (*force_lock)(malloc_zone_t*);
+  void (*force_unlock)(malloc_zone_t*);
+  void (*statistics)(malloc_zone_t*, malloc_statistics_t*);
+  boolean_t (*zone_locked)(malloc_zone_t*);
+  boolean_t (*enable_discharge_checking)(malloc_zone_t*);
+  boolean_t (*disable_discharge_checking)(malloc_zone_t*);
+  void (*discharge)(malloc_zone_t*, void*);
 #ifdef __BLOCKS__
-  void (*enumerate_discharged_pointers)(malloc_zone_t *, void (^)(void *, void *));
+  void (*enumerate_discharged_pointers)(malloc_zone_t*, void (^)(void*, void*));
 #else
-  void *enumerate_unavailable_without_blocks;
+  void* enumerate_unavailable_without_blocks;
 #endif
-  void (*reinit_lock)(malloc_zone_t *);
+  void (*reinit_lock)(malloc_zone_t*);
 } malloc_introspection_t;
 
-extern kern_return_t malloc_get_all_zones(task_t, memory_reader_t, vm_address_t **, unsigned *);
+extern kern_return_t
+malloc_get_all_zones(task_t, memory_reader_t, vm_address_t**, unsigned*);
 
-extern malloc_zone_t *malloc_default_zone(void);
-
-extern void malloc_zone_register(malloc_zone_t *zone);
+extern malloc_zone_t*
+malloc_default_zone(void);
 
-extern void malloc_zone_unregister(malloc_zone_t *zone);
+extern void
+malloc_zone_register(malloc_zone_t* zone);
 
-extern malloc_zone_t *malloc_default_purgeable_zone(void);
+extern void
+malloc_zone_unregister(malloc_zone_t* zone);
 
-extern malloc_zone_t* malloc_zone_from_ptr(const void* ptr);
+extern malloc_zone_t*
+malloc_default_purgeable_zone(void);
 
-extern void malloc_zone_free(malloc_zone_t* zone, void* ptr);
+extern malloc_zone_t*
+malloc_zone_from_ptr(const void* ptr);
 
-extern void* malloc_zone_realloc(malloc_zone_t* zone, void* ptr, size_t size);
+extern void
+malloc_zone_free(malloc_zone_t* zone, void* ptr);
 
-/*
- * The following is a OSX zone allocator implementation.
- * /!\ WARNING. It assumes the underlying malloc implementation's
- * malloc_usable_size returns 0 when the given pointer is not owned by
- * the allocator. Sadly, OSX does call zone_size with pointers not
- * owned by the allocator.
- */
+extern void*
+malloc_zone_realloc(malloc_zone_t* zone, void* ptr, size_t size);
+
+// The following is a OSX zone allocator implementation.
+// /!\ WARNING. It assumes the underlying malloc implementation's
+// malloc_usable_size returns 0 when the given pointer is not owned by
+// the allocator. Sadly, OSX does call zone_size with pointers not
+// owned by the allocator.
 
 static size_t
-zone_size(malloc_zone_t *zone, const void *ptr)
+zone_size(malloc_zone_t* zone, const void* ptr)
 {
   return malloc_usable_size_impl(ptr);
 }
 
-static void *
-zone_malloc(malloc_zone_t *zone, size_t size)
+static void*
+zone_malloc(malloc_zone_t* zone, size_t size)
 {
   return malloc_impl(size);
 }
 
-static void *
-zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
+static void*
+zone_calloc(malloc_zone_t* zone, size_t num, size_t size)
 {
   return calloc_impl(num, size);
 }
 
-static void *
-zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
+static void*
+zone_realloc(malloc_zone_t* zone, void* ptr, size_t size)
 {
   if (malloc_usable_size_impl(ptr))
     return realloc_impl(ptr, size);
 
   // Sometimes, system libraries call malloc_zone_* functions with the wrong
   // zone (e.g. CoreFoundation does). In that case, we need to find the real
   // one. We can't call libSystem's realloc directly because we're exporting
   // realloc from libmozglue and we'd pick that one, so we manually find the
@@ -160,201 +177,206 @@ other_zone_free(malloc_zone_t* original_
   // The system allocator crashes voluntarily by default when a pointer can't
   // be traced back to a zone. Do the same.
   MOZ_RELEASE_ASSERT(zone);
   MOZ_RELEASE_ASSERT(zone != original_zone);
   return malloc_zone_free(zone, ptr);
 }
 
 static void
-zone_free(malloc_zone_t *zone, void *ptr)
+zone_free(malloc_zone_t* zone, void* ptr)
 {
   if (malloc_usable_size_impl(ptr)) {
     free_impl(ptr);
     return;
   }
   other_zone_free(zone, ptr);
 }
 
 static void
-zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
+zone_free_definite_size(malloc_zone_t* zone, void* ptr, size_t size)
 {
   size_t current_size = malloc_usable_size_impl(ptr);
   if (current_size) {
     MOZ_ASSERT(current_size == size);
     free_impl(ptr);
     return;
   }
   other_zone_free(zone, ptr);
 }
 
-static void *
-zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
+static void*
+zone_memalign(malloc_zone_t* zone, size_t alignment, size_t size)
 {
-  void *ptr;
+  void* ptr;
   if (posix_memalign_impl(&ptr, alignment, size) == 0)
     return ptr;
   return NULL;
 }
 
-static void *
-zone_valloc(malloc_zone_t *zone, size_t size)
+static void*
+zone_valloc(malloc_zone_t* zone, size_t size)
 {
   return valloc_impl(size);
 }
 
 static void
-zone_destroy(malloc_zone_t *zone)
+zone_destroy(malloc_zone_t* zone)
 {
-  /* This function should never be called. */
+  // This function should never be called.
   MOZ_CRASH();
 }
 
 static unsigned
-zone_batch_malloc(malloc_zone_t *zone, size_t size, void **results,
-    unsigned num_requested)
+zone_batch_malloc(malloc_zone_t* zone,
+                  size_t size,
+                  void** results,
+                  unsigned num_requested)
 {
   unsigned i;
 
   for (i = 0; i < num_requested; i++) {
     results[i] = malloc_impl(size);
     if (!results[i])
       break;
   }
 
   return i;
 }
 
 static void
-zone_batch_free(malloc_zone_t *zone, void **to_be_freed,
-    unsigned num_to_be_freed)
+zone_batch_free(malloc_zone_t* zone,
+                void** to_be_freed,
+                unsigned num_to_be_freed)
 {
   unsigned i;
 
   for (i = 0; i < num_to_be_freed; i++) {
     zone_free(zone, to_be_freed[i]);
     to_be_freed[i] = NULL;
   }
 }
 
 static size_t
-zone_pressure_relief(malloc_zone_t *zone, size_t goal)
+zone_pressure_relief(malloc_zone_t* zone, size_t goal)
 {
   return 0;
 }
 
 static size_t
-zone_good_size(malloc_zone_t *zone, size_t size)
+zone_good_size(malloc_zone_t* zone, size_t size)
 {
   return malloc_good_size_impl(size);
 }
 
 static kern_return_t
-zone_enumerator(task_t task, void *data, unsigned type_mask,
-    vm_address_t zone_address, memory_reader_t reader,
-    vm_range_recorder_t recorder)
+zone_enumerator(task_t task,
+                void* data,
+                unsigned type_mask,
+                vm_address_t zone_address,
+                memory_reader_t reader,
+                vm_range_recorder_t recorder)
 {
   return KERN_SUCCESS;
 }
 
 static boolean_t
-zone_check(malloc_zone_t *zone)
+zone_check(malloc_zone_t* zone)
 {
   return true;
 }
 
 static void
-zone_print(malloc_zone_t *zone, boolean_t verbose)
+zone_print(malloc_zone_t* zone, boolean_t verbose)
 {
 }
 
 static void
-zone_log(malloc_zone_t *zone, void *address)
+zone_log(malloc_zone_t* zone, void* address)
 {
 }
 
-extern void _malloc_prefork(void);
-extern void _malloc_postfork_child(void);
+extern void
+_malloc_prefork(void);
+extern void
+_malloc_postfork_child(void);
 
 static void
-zone_force_lock(malloc_zone_t *zone)
+zone_force_lock(malloc_zone_t* zone)
 {
-  /* /!\ This calls into mozjemalloc. It works because we're linked in the
-   * same library. */
+  // /!\ This calls into mozjemalloc. It works because we're linked in the
+  // same library.
   _malloc_prefork();
 }
 
 static void
-zone_force_unlock(malloc_zone_t *zone)
+zone_force_unlock(malloc_zone_t* zone)
 {
-  /* /!\ This calls into mozjemalloc. It works because we're linked in the
-   * same library. */
+  // /!\ This calls into mozjemalloc. It works because we're linked in the
+  // same library.
   _malloc_postfork_child();
 }
 
 static void
-zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats)
+zone_statistics(malloc_zone_t* zone, malloc_statistics_t* stats)
 {
-  /* We make no effort to actually fill the values */
+  // We make no effort to actually fill the values
   stats->blocks_in_use = 0;
   stats->size_in_use = 0;
   stats->max_size_in_use = 0;
   stats->size_allocated = 0;
 }
 
 static boolean_t
-zone_locked(malloc_zone_t *zone)
+zone_locked(malloc_zone_t* zone)
 {
-  /* Pretend no lock is being held */
+  // Pretend no lock is being held
   return false;
 }
 
 static void
-zone_reinit_lock(malloc_zone_t *zone)
+zone_reinit_lock(malloc_zone_t* zone)
 {
-  /* As of OSX 10.12, this function is only used when force_unlock would
-   * be used if the zone version were < 9. So just use force_unlock. */
+  // As of OSX 10.12, this function is only used when force_unlock would
+  // be used if the zone version were < 9. So just use force_unlock.
   zone_force_unlock(zone);
 }
 
 static malloc_zone_t zone;
 static struct malloc_introspection_t zone_introspect;
 
-static malloc_zone_t *get_default_zone()
+static malloc_zone_t*
+get_default_zone()
 {
-  malloc_zone_t **zones = NULL;
+  malloc_zone_t** zones = NULL;
   unsigned int num_zones = 0;
 
-  /*
-   * On OSX 10.12, malloc_default_zone returns a special zone that is not
-   * present in the list of registered zones. That zone uses a "lite zone"
-   * if one is present (apparently enabled when malloc stack logging is
-   * enabled), or the first registered zone otherwise. In practice this
-   * means unless malloc stack logging is enabled, the first registered
-   * zone is the default.
-   * So get the list of zones to get the first one, instead of relying on
-   * malloc_default_zone.
-   */
-  if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, (vm_address_t**) &zones,
-                                           &num_zones)) {
-    /* Reset the value in case the failure happened after it was set. */
+  // On OSX 10.12, malloc_default_zone returns a special zone that is not
+  // present in the list of registered zones. That zone uses a "lite zone"
+  // if one is present (apparently enabled when malloc stack logging is
+  // enabled), or the first registered zone otherwise. In practice this
+  // means unless malloc stack logging is enabled, the first registered
+  // zone is the default.
+  // So get the list of zones to get the first one, instead of relying on
+  // malloc_default_zone.
+  if (KERN_SUCCESS !=
+      malloc_get_all_zones(0, NULL, (vm_address_t**)&zones, &num_zones)) {
+    // Reset the value in case the failure happened after it was set.
     num_zones = 0;
   }
   if (num_zones) {
     return zones[0];
   }
   return malloc_default_zone();
 }
 
-
- __attribute__((constructor))
-static void
+__attribute__((constructor)) static void
 register_zone(void)
 {
-  malloc_zone_t *default_zone = get_default_zone();
+  malloc_zone_t* default_zone = get_default_zone();
 
   zone.size = zone_size;
   zone.malloc = zone_malloc;
   zone.calloc = zone_calloc;
   zone.valloc = zone_valloc;
   zone.free = zone_free;
   zone.realloc = zone_realloc;
   zone.destroy = zone_destroy;
@@ -384,49 +406,44 @@ register_zone(void)
   zone_introspect.discharge = NULL;
 #ifdef __BLOCKS__
   zone_introspect.enumerate_discharged_pointers = NULL;
 #else
   zone_introspect.enumerate_unavailable_without_blocks = NULL;
 #endif
   zone_introspect.reinit_lock = zone_reinit_lock;
 
-  /*
-   * The default purgeable zone is created lazily by OSX's libc.  It uses
-   * the default zone when it is created for "small" allocations
-   * (< 15 KiB), but assumes the default zone is a scalable_zone.  This
-   * obviously fails when the default zone is the jemalloc zone, so
-   * malloc_default_purgeable_zone is called beforehand so that the
-   * default purgeable zone is created when the default zone is still
-   * a scalable_zone.
-   */
-  malloc_zone_t *purgeable_zone = malloc_default_purgeable_zone();
+  // The default purgeable zone is created lazily by OSX's libc.  It uses
+  // the default zone when it is created for "small" allocations
+  // (< 15 KiB), but assumes the default zone is a scalable_zone.  This
+  // obviously fails when the default zone is the jemalloc zone, so
+  // malloc_default_purgeable_zone is called beforehand so that the
+  // default purgeable zone is created when the default zone is still
+  // a scalable_zone.
+  malloc_zone_t* purgeable_zone = malloc_default_purgeable_zone();
 
-  /* Register the custom zone.  At this point it won't be the default. */
+  // Register the custom zone.  At this point it won't be the default.
   malloc_zone_register(&zone);
 
   do {
-    /*
-     * Unregister and reregister the default zone.  On OSX >= 10.6,
-     * unregistering takes the last registered zone and places it at the
-     * location of the specified zone.  Unregistering the default zone thus
-     * makes the last registered one the default.  On OSX < 10.6,
-     * unregistering shifts all registered zones.  The first registered zone
-     * then becomes the default.
-     */
+    // Unregister and reregister the default zone.  On OSX >= 10.6,
+    // unregistering takes the last registered zone and places it at the
+    // location of the specified zone.  Unregistering the default zone thus
+    // makes the last registered one the default.  On OSX < 10.6,
+    // unregistering shifts all registered zones.  The first registered zone
+    // then becomes the default.
     malloc_zone_unregister(default_zone);
     malloc_zone_register(default_zone);
-    /*
-     * On OSX 10.6, having the default purgeable zone appear before the default
-     * zone makes some things crash because it thinks it owns the default
-     * zone allocated pointers. We thus unregister/re-register it in order to
-     * ensure it's always after the default zone. On OSX < 10.6, as
-     * unregistering shifts registered zones, this simply removes the purgeable
-     * zone from the list and adds it back at the end, after the default zone.
-     * On OSX >= 10.6, unregistering replaces the purgeable zone with the last
-     * registered zone above, i.e the default zone. Registering it again then
-     * puts it at the end, obviously after the default zone.
-     */
+
+    // On OSX 10.6, having the default purgeable zone appear before the default
+    // zone makes some things crash because it thinks it owns the default
+    // zone allocated pointers. We thus unregister/re-register it in order to
+    // ensure it's always after the default zone. On OSX < 10.6, as
+    // unregistering shifts registered zones, this simply removes the purgeable
+    // zone from the list and adds it back at the end, after the default zone.
+    // On OSX >= 10.6, unregistering replaces the purgeable zone with the last
+    // registered zone above, i.e the default zone. Registering it again then
+    // puts it at the end, obviously after the default zone.
     malloc_zone_unregister(purgeable_zone);
     malloc_zone_register(purgeable_zone);
     default_zone = get_default_zone();
   } while (default_zone != &zone);
 }
--- a/security/sandbox/mac/SandboxPolicies.h
+++ b/security/sandbox/mac/SandboxPolicies.h
@@ -245,20 +245,16 @@ static const char contentSandboxRules[] 
   (if (string? debugWriteDir)
     (begin
       (allow file-write-data (subpath debugWriteDir))
       (allow file-write-create
         (require-all
           (subpath debugWriteDir)
           (vnode-type REGULAR-FILE)))))
 
-  ; bug 1324610
-  (allow network-outbound file-read*
-    (literal "/private/var/run/cupsd"))
-
   (allow-shared-list "org.mozilla.plugincontainer")
 
 ; the following rule should be removed when microphone access
 ; is brokered through the content process
   (allow device-microphone)
 
 ; Per-user and system-wide Extensions dir
   (allow file-read*
--- a/servo/components/compositing/compositor.rs
+++ b/servo/components/compositing/compositor.rs
@@ -1306,17 +1306,17 @@ impl<Window: WindowMethods> IOCompositor
             self.webrender.render(self.frame_size).ok();
         });
 
         // If there are pending paint metrics, we check if any of the painted epochs is
         // one of the ones that the paint metrics recorder is expecting . In that case,
         // we get the current time, inform the layout thread about it and remove the
         // pending metric from the list.
         if !self.pending_paint_metrics.is_empty() {
-            let paint_time = precise_time_ns() as f64;
+            let paint_time = precise_time_ns();
             let mut to_remove = Vec::new();
             // For each pending paint metrics pipeline id
             for (id, pending_epoch) in &self.pending_paint_metrics {
                 // we get the last painted frame id from webrender
                 if let Some(webrender_api::Epoch(epoch)) = self.webrender.current_epoch(id.to_webrender()) {
                     // and check if it is the one the layout thread is expecting,
                     let epoch = Epoch(epoch);
                     if *pending_epoch != epoch {
--- a/servo/components/metrics/lib.rs
+++ b/servo/components/metrics/lib.rs
@@ -29,60 +29,60 @@ use std::cmp::Ordering;
 use std::collections::HashMap;
 use time::precise_time_ns;
 
 pub trait ProfilerMetadataFactory {
     fn new_metadata(&self) -> Option<TimerMetadata>;
 }
 
 pub trait ProgressiveWebMetric {
-    fn get_navigation_start(&self) -> Option<f64>;
-    fn set_navigation_start(&mut self, time: f64);
+    fn get_navigation_start(&self) -> Option<u64>;
+    fn set_navigation_start(&mut self, time: u64);
     fn get_time_profiler_chan(&self) -> &ProfilerChan;
-    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: f64);
+    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: u64);
 }
 
 /// maximum task time is 50ms (in ns)
 pub const MAX_TASK_NS: u64 = 50000000;
 /// 10 second window (in ns)
 const INTERACTIVE_WINDOW_SECONDS_IN_NS: u64 = 10000000000;
 
 
 fn set_metric<U: ProgressiveWebMetric>(
     pwm: &U,
     metadata: Option<TimerMetadata>,
     metric_type: ProgressiveWebMetricType,
     category: ProfilerCategory,
-    attr: &Cell<Option<f64>>,
-    metric_time: Option<f64>)
+    attr: &Cell<Option<u64>>,
+    metric_time: Option<u64>)
 {
     let navigation_start = match pwm.get_navigation_start() {
         Some(time) => time,
         None => {
             warn!("Trying to set metric before navigation start");
             return;
         }
     };
     let now = match metric_time {
         Some(time) => time,
-        None => precise_time_ns() as f64,
+        None => precise_time_ns(),
     };
     let time = now - navigation_start;
     attr.set(Some(time));
 
     // Queue performance observer notification.
     pwm.send_queued_constellation_msg(metric_type, time);
 
     // Send the metric to the time profiler.
     send_profile_data(
         category,
         metadata,
         &pwm.get_time_profiler_chan(),
-        time as u64,
-        time as u64,
+        time,
+        time,
         0,
         0,
     );
 
     // Print the metric to console if the print-pwm option was given.
     if opts::get().print_pwm {
         println!("{:?} {:?}", metric_type, time);
     }
@@ -92,23 +92,23 @@ fn set_metric<U: ProgressiveWebMetric>(
 // https://github.com/GoogleChrome/lighthouse/issues/27
 // we can look at three different metrics here:
 // navigation start -> visually ready (dom content loaded)
 // navigation start -> thread ready (main thread available)
 // visually ready -> thread ready
 #[derive(MallocSizeOf)]
 pub struct InteractiveMetrics {
     /// when we navigated to the page
-    navigation_start: Option<f64>,
+    navigation_start: Option<u64>,
     /// indicates if the page is visually ready
-    dom_content_loaded: Cell<Option<f64>>,
+    dom_content_loaded: Cell<Option<u64>>,
     /// main thread is available -- there's been a 10s window with no tasks longer than 50ms
-    main_thread_available: Cell<Option<f64>>,
+    main_thread_available: Cell<Option<u64>>,
     // max(main_thread_available, dom_content_loaded)
-    time_to_interactive: Cell<Option<f64>>,
+    time_to_interactive: Cell<Option<u64>>,
     #[ignore_malloc_size_of = "can't measure channels"]
     time_profiler_chan: ProfilerChan,
 }
 
 #[derive(Clone, Copy, Debug, MallocSizeOf)]
 pub struct InteractiveWindow {
     start: u64,
 }
@@ -137,47 +137,47 @@ impl InteractiveWindow {
     pub fn get_start(&self) -> u64 {
         self.start
     }
 }
 
 #[derive(Debug)]
 pub enum InteractiveFlag {
     DOMContentLoaded,
-    TimeToInteractive(f64),
+    TimeToInteractive(u64),
 }
 
 impl InteractiveMetrics {
     pub fn new(time_profiler_chan: ProfilerChan) -> InteractiveMetrics {
         InteractiveMetrics {
             navigation_start: None,
             dom_content_loaded: Cell::new(None),
             main_thread_available: Cell::new(None),
             time_to_interactive: Cell::new(None),
             time_profiler_chan: time_profiler_chan,
         }
     }
 
     pub fn set_dom_content_loaded(&self) {
         if self.dom_content_loaded.get().is_none() {
-            self.dom_content_loaded.set(Some(precise_time_ns() as f64));
+            self.dom_content_loaded.set(Some(precise_time_ns()));
         }
     }
 
-    pub fn set_main_thread_available(&self, time: f64) {
+    pub fn set_main_thread_available(&self, time: u64) {
         if self.main_thread_available.get().is_none() {
             self.main_thread_available.set(Some(time));
         }
     }
 
-    pub fn get_dom_content_loaded(&self) -> Option<f64> {
+    pub fn get_dom_content_loaded(&self) -> Option<u64> {
         self.dom_content_loaded.get()
     }
 
-    pub fn get_main_thread_available(&self) -> Option<f64> {
+    pub fn get_main_thread_available(&self) -> Option<u64> {
         self.main_thread_available.get()
     }
 
     // can set either dlc or tti first, but both must be set to actually calc metric
     // when the second is set, set_tti is called with appropriate time
     pub fn maybe_set_tti<T>(
         &self,
         profiler_metadata_factory: &T,
@@ -208,42 +208,42 @@ impl InteractiveMetrics {
             self,
             profiler_metadata_factory.new_metadata(),
             ProgressiveWebMetricType::TimeToInteractive,
             ProfilerCategory::TimeToInteractive,
             &self.time_to_interactive,
             Some(metric_time));
     }
 
-    pub fn get_tti(&self) -> Option<f64> {
+    pub fn get_tti(&self) -> Option<u64> {
         self.time_to_interactive.get()
     }
 }
 
 impl ProgressiveWebMetric for InteractiveMetrics {
-    fn get_navigation_start(&self) -> Option<f64> {
+    fn get_navigation_start(&self) -> Option<u64> {
         self.navigation_start
     }
 
-    fn set_navigation_start(&mut self, time: f64) {
+    fn set_navigation_start(&mut self, time: u64) {
         self.navigation_start = Some(time);
     }
 
-    fn send_queued_constellation_msg(&self, _name: ProgressiveWebMetricType, _time: f64) { }
+    fn send_queued_constellation_msg(&self, _name: ProgressiveWebMetricType, _time: u64) { }
 
     fn get_time_profiler_chan(&self) -> &ProfilerChan {
         &self.time_profiler_chan
     }
 }
 
 pub struct PaintTimeMetrics {
     pending_metrics: RefCell<HashMap<Epoch, (Option<TimerMetadata>, bool)>>,
-    navigation_start: Option<f64>,
-    first_paint: Cell<Option<f64>>,
-    first_contentful_paint: Cell<Option<f64>>,
+    navigation_start: Option<u64>,
+    first_paint: Cell<Option<u64>>,
+    first_contentful_paint: Cell<Option<u64>>,
     pipeline_id: PipelineId,
     time_profiler_chan: ProfilerChan,
     constellation_chan: IpcSender<LayoutMsg>,
     script_chan: IpcSender<ConstellationControlMsg>,
 }
 
 impl PaintTimeMetrics {
     pub fn new(
@@ -317,17 +317,17 @@ impl PaintTimeMetrics {
         // The compositor will record the current time after painting the
         // frame with the given ID and will send the metric back to us.
         let msg = LayoutMsg::PendingPaintMetric(self.pipeline_id, epoch);
         if let Err(e) = self.constellation_chan.send(msg) {
             warn!("Failed to send PendingPaintMetric {:?}", e);
         }
     }
 
-    pub fn maybe_set_metric(&self, epoch: Epoch, paint_time: f64) {
+    pub fn maybe_set_metric(&self, epoch: Epoch, paint_time: u64) {
         if self.first_paint.get().is_some() && self.first_contentful_paint.get().is_some() ||
             self.navigation_start.is_none() {
             // If we already set all paint metrics or we have not set navigation start yet,
             // we just bail out.
             return;
         }
 
         if let Some(pending_metric) = self.pending_metrics.borrow_mut().remove(&epoch) {
@@ -349,35 +349,35 @@ impl PaintTimeMetrics {
                     ProfilerCategory::TimeToFirstContentfulPaint,
                     &self.first_contentful_paint,
                     Some(paint_time),
                 );
             }
         }
     }
 
-    pub fn get_first_paint(&self) -> Option<f64> {
+    pub fn get_first_paint(&self) -> Option<u64> {
         self.first_paint.get()
     }
 
-    pub fn get_first_contentful_paint(&self) -> Option<f64> {
+    pub fn get_first_contentful_paint(&self) -> Option<u64> {
         self.first_contentful_paint.get()
     }
 }
 
 impl ProgressiveWebMetric for PaintTimeMetrics {
-    fn get_navigation_start(&self) -> Option<f64> {
+    fn get_navigation_start(&self) -> Option<u64> {
         self.navigation_start
     }
 
-    fn set_navigation_start(&mut self, time: f64) {
+    fn set_navigation_start(&mut self, time: u64) {
         self.navigation_start = Some(time);
     }
 
-    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: f64) {
+    fn send_queued_constellation_msg(&self, name: ProgressiveWebMetricType, time: u64) {
         let msg = ConstellationControlMsg::PaintMetric(self.pipeline_id, name, time);
         if let Err(e) = self.script_chan.send(msg) {
             warn!("Sending metric to script thread failed ({}).", e);
         }
     }
 
     fn get_time_profiler_chan(&self) -> &ProfilerChan {
         &self.time_profiler_chan
--- a/servo/components/script/dom/document.rs
+++ b/servo/components/script/dom/document.rs
@@ -1956,17 +1956,17 @@ impl Document {
     /// check tti for this document
     /// if it's been 10s since this doc encountered a task over 50ms, then we consider the
     /// main thread available and try to set tti
     pub fn record_tti_if_necessary(&self) {
         if self.has_recorded_tti_metric() { return; }
 
         if self.tti_window.borrow().needs_check() {
             self.get_interactive_metrics().maybe_set_tti(self,
-                InteractiveFlag::TimeToInteractive(self.tti_window.borrow().get_start() as f64));
+                InteractiveFlag::TimeToInteractive(self.tti_window.borrow().get_start()));
         }
     }
 
     // https://html.spec.whatwg.org/multipage/#fire-a-focus-event
     fn fire_focus_event(&self, focus_event_type: FocusEventType, node: &Node, related_target: Option<&EventTarget>) {
         let (event_name, does_bubble) = match focus_event_type {
             FocusEventType::Focus => (DOMString::from("focus"), EventBubbles::DoesNotBubble),
             FocusEventType::Blur => (DOMString::from("blur"), EventBubbles::DoesNotBubble),
--- a/servo/components/script/dom/performance.rs
+++ b/servo/components/script/dom/performance.rs
@@ -109,23 +109,23 @@ struct PerformanceObserver {
 
 #[dom_struct]
 pub struct Performance {
     reflector_: Reflector,
     timing: Option<Dom<PerformanceTiming>>,
     entries: DomRefCell<PerformanceEntryList>,
     observers: DomRefCell<Vec<PerformanceObserver>>,
     pending_notification_observers_task: Cell<bool>,
-    navigation_start_precise: f64,
+    navigation_start_precise: u64,
 }
 
 impl Performance {
     fn new_inherited(global: &GlobalScope,
                      navigation_start: u64,
-                     navigation_start_precise: f64) -> Performance {
+                     navigation_start_precise: u64) -> Performance {
         Performance {
             reflector_: Reflector::new(),
             timing: if global.is::<Window>() {
                 Some(Dom::from_ref(&*PerformanceTiming::new(global.as_window(),
                                                            navigation_start,
                                                            navigation_start_precise)))
             } else {
                 None
@@ -134,17 +134,17 @@ impl Performance {
             observers: DomRefCell::new(Vec::new()),
             pending_notification_observers_task: Cell::new(false),
             navigation_start_precise,
         }
     }
 
     pub fn new(global: &GlobalScope,
                navigation_start: u64,
-               navigation_start_precise: f64) -> DomRoot<Performance> {
+               navigation_start_precise: u64) -> DomRoot<Performance> {
         reflect_dom_object(
             Box::new(Performance::new_inherited(global, navigation_start, navigation_start_precise)),
             global,
             PerformanceBinding::Wrap
         )
     }
 
     /// Add a PerformanceObserver to the list of observers with a set of
@@ -255,17 +255,17 @@ impl Performance {
         }
     }
 
     fn now(&self) -> f64 {
         let nav_start = match self.timing {
             Some(ref timing) => timing.navigation_start_precise(),
             None => self.navigation_start_precise,
         };
-        (time::precise_time_ns() as f64 - nav_start) / 1000000 as f64
+        (time::precise_time_ns() - nav_start) as f64 / 1000000.
     }
 }
 
 impl PerformanceMethods for Performance {
     // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html#performance-timing-attribute
     fn Timing(&self) -> DomRoot<PerformanceTiming> {
         match self.timing {
             Some(ref timing) => DomRoot::from_ref(&*timing),
--- a/servo/components/script/dom/performancepainttiming.rs
+++ b/servo/components/script/dom/performancepainttiming.rs
@@ -12,30 +12,30 @@ use dom_struct::dom_struct;
 use script_traits::ProgressiveWebMetricType;
 
 #[dom_struct]
 pub struct PerformancePaintTiming {
     entry: PerformanceEntry,
 }
 
 impl PerformancePaintTiming {
-    fn new_inherited(metric_type: ProgressiveWebMetricType, start_time: f64) -> PerformancePaintTiming {
+    fn new_inherited(metric_type: ProgressiveWebMetricType, start_time: u64) -> PerformancePaintTiming {
         let name = match metric_type {
             ProgressiveWebMetricType::FirstPaint => DOMString::from("first-paint"),
             ProgressiveWebMetricType::FirstContentfulPaint => DOMString::from("first-contentful-paint"),
             _ => DOMString::from(""),
         };
         PerformancePaintTiming {
             entry: PerformanceEntry::new_inherited(name,
                                                    DOMString::from("paint"),
-                                                   start_time,
+                                                   start_time as f64,
                                                    0.)
         }
     }
 
     #[allow(unrooted_must_root)]
     pub fn new(global: &GlobalScope,
                metric_type: ProgressiveWebMetricType,
-               start_time: f64) -> DomRoot<PerformancePaintTiming> {
+               start_time: u64) -> DomRoot<PerformancePaintTiming> {
         let entry = PerformancePaintTiming::new_inherited(metric_type, start_time);
         reflect_dom_object(Box::new(entry), global, PerformancePaintTimingBinding::Wrap)
     }
 }
--- a/servo/components/script/dom/performancetiming.rs
+++ b/servo/components/script/dom/performancetiming.rs
@@ -10,37 +10,37 @@ use dom::bindings::root::{Dom, DomRoot};
 use dom::document::Document;
 use dom::window::Window;
 use dom_struct::dom_struct;
 
 #[dom_struct]
 pub struct PerformanceTiming {
     reflector_: Reflector,
     navigation_start: u64,
-    navigation_start_precise: f64,
+    navigation_start_precise: u64,
     document: Dom<Document>,
 }
 
 impl PerformanceTiming {
     fn new_inherited(nav_start: u64,
-                     nav_start_precise: f64,
+                     nav_start_precise: u64,
                      document: &Document)
                          -> PerformanceTiming {
         PerformanceTiming {
             reflector_: Reflector::new(),
             navigation_start: nav_start,
             navigation_start_precise: nav_start_precise,
             document: Dom::from_ref(document),
         }
     }
 
     #[allow(unrooted_must_root)]
     pub fn new(window: &Window,
                navigation_start: u64,
-               navigation_start_precise: f64)
+               navigation_start_precise: u64)
                -> DomRoot<PerformanceTiming> {
         let timing = PerformanceTiming::new_inherited(navigation_start,
                                                       navigation_start_precise,
                                                       &window.Document());
         reflect_dom_object(Box::new(timing),
                            window,
                            PerformanceTimingBinding::Wrap)
     }
@@ -85,12 +85,12 @@ impl PerformanceTimingMethods for Perfor
     // https://w3c.github.io/navigation-timing/#widl-PerformanceTiming-loadEventEnd
     fn LoadEventEnd(&self) -> u64 {
         self.document.get_load_event_end()
     }
 }
 
 
 impl PerformanceTiming {
-    pub fn navigation_start_precise(&self) -> f64 {
+    pub fn navigation_start_precise(&self) -> u64 {
         self.navigation_start_precise
     }
 }
--- a/servo/components/script/dom/window.rs
+++ b/servo/components/script/dom/window.rs
@@ -181,17 +181,17 @@ pub struct Window {
     image_cache_chan: Sender<ImageCacheMsg>,
     window_proxy: MutNullableDom<WindowProxy>,
     document: MutNullableDom<Document>,
     location: MutNullableDom<Location>,
     history: MutNullableDom<History>,
     custom_element_registry: MutNullableDom<CustomElementRegistry>,
     performance: MutNullableDom<Performance>,
     navigation_start: Cell<u64>,
-    navigation_start_precise: Cell<f64>,
+    navigation_start_precise: Cell<u64>,
     screen: MutNullableDom<Screen>,
     session_storage: MutNullableDom<Storage>,
     local_storage: MutNullableDom<Storage>,
     status: DomRefCell<DOMString>,
 
     /// For sending timeline markers. Will be ignored if
     /// no devtools server
     devtools_markers: DomRefCell<HashSet<TimelineMarkerType>>,
@@ -1040,17 +1040,17 @@ impl WindowMethods for Window {
 
 impl Window {
     pub fn task_canceller(&self) -> TaskCanceller {
         TaskCanceller {
             cancelled: Some(self.ignore_further_async_events.borrow().clone()),
         }
     }
 
-    pub fn get_navigation_start(&self) -> f64 {
+    pub fn get_navigation_start(&self) -> u64 {
         self.navigation_start_precise.get()
     }
 
     /// Cancels all the tasks associated with that window.
     ///
     /// This sets the current `ignore_further_async_events` sentinel value to
     /// `true` and replaces it with a brand new one for future tasks.
     pub fn cancel_all_tasks(&self) {
@@ -1729,17 +1729,17 @@ impl Window {
     pub fn unminified_js_dir(&self) -> Option<String> {
         self.unminified_js_dir.borrow().clone()
     }
 
     pub fn set_navigation_start(&self) {
         let current_time = time::get_time();
         let now = (current_time.sec * 1000 + current_time.nsec as i64 / 1000000) as u64;
         self.navigation_start.set(now);
-        self.navigation_start_precise.set(time::precise_time_ns() as f64);
+        self.navigation_start_precise.set(time::precise_time_ns());
     }
 
     fn send_to_constellation(&self, msg: ScriptMsg) {
         self.upcast::<GlobalScope>()
             .script_to_constellation_chan()
             .send(msg)
             .unwrap();
     }
@@ -1772,17 +1772,17 @@ impl Window {
         scheduler_chan: IpcSender<TimerSchedulerMsg>,
         timer_event_chan: IpcSender<TimerEvent>,
         layout_chan: Sender<Msg>,
         pipelineid: PipelineId,
         parent_info: Option<(PipelineId, FrameType)>,
         window_size: Option<WindowSizeData>,
         origin: MutableOrigin,
         navigation_start: u64,
-        navigation_start_precise: f64,
+        navigation_start_precise: u64,
         webgl_chan: WebGLChan,
         webvr_chan: Option<IpcSender<WebVRMsg>>,
         microtask_queue: Rc<MicrotaskQueue>,
         webrender_document: DocumentId,
     ) -> DomRoot<Self> {
         let layout_rpc: Box<LayoutRPC + Send> = {
             let (rpc_send, rpc_recv) = channel();
             layout_chan.send(Msg::GetRPC(rpc_send)).unwrap();
--- a/servo/components/script/dom/workerglobalscope.rs
+++ b/servo/components/script/dom/workerglobalscope.rs
@@ -85,17 +85,17 @@ pub struct WorkerGlobalScope {
     /// to the server from within the worker
     from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
 
     #[ignore_malloc_size_of = "Defined in std"]
     /// This `Receiver` will be ignored later if the corresponding
     /// `IpcSender` doesn't exist
     from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
 
-    navigation_start_precise: f64,
+    navigation_start_precise: u64,
     performance: MutNullableDom<Performance>,
 }
 
 impl WorkerGlobalScope {
     pub fn new_inherited(
         init: WorkerGlobalScopeInit,
         worker_url: ServoUrl,
         runtime: Runtime,
@@ -119,17 +119,17 @@ impl WorkerGlobalScope {
             worker_id: init.worker_id,
             worker_url,
             closing,
             runtime,
             location: Default::default(),
             navigator: Default::default(),
             from_devtools_sender: init.from_devtools_sender,
             from_devtools_receiver,
-            navigation_start_precise: precise_time_ns() as f64,
+            navigation_start_precise: precise_time_ns(),
             performance: Default::default(),
         }
     }
 
     pub fn from_devtools_sender(&self) -> Option<IpcSender<DevtoolScriptControlMsg>> {
         self.from_devtools_sender.clone()
     }
 
--- a/servo/components/script/script_thread.rs
+++ b/servo/components/script/script_thread.rs
@@ -164,31 +164,31 @@ struct InProgressLoad {
     is_visible: bool,
     /// The requested URL of the load.
     url: ServoUrl,
     /// The origin for the document
     origin: MutableOrigin,
     /// Timestamp reporting the time when the browser started this load.
     navigation_start: u64,
     /// High res timestamp reporting the time when the browser started this load.
-    navigation_start_precise: f64,
+    navigation_start_precise: u64,
 }
 
 impl InProgressLoad {
     /// Create a new InProgressLoad object.
     fn new(id: PipelineId,
            browsing_context_id: BrowsingContextId,
            top_level_browsing_context_id: TopLevelBrowsingContextId,
            parent_info: Option<(PipelineId, FrameType)>,
            layout_chan: Sender<message::Msg>,
            window_size: Option<WindowSizeData>,
            url: ServoUrl,
            origin: MutableOrigin) -> InProgressLoad {
         let current_time = get_time();
-        let navigation_start_precise = precise_time_ns() as f64;
+        let navigation_start_precise = precise_time_ns();
         layout_chan.send(message::Msg::SetNavigationStart(navigation_start_precise)).unwrap();
         InProgressLoad {
             pipeline_id: id,
             browsing_context_id: browsing_context_id,
             top_level_browsing_context_id: top_level_browsing_context_id,
             parent_info: parent_info,
             layout_chan: layout_chan,
             window_size: window_size,
@@ -2650,17 +2650,17 @@ impl ScriptThread {
             let vr = window.Navigator().Vr();
             vr.handle_webvr_events(events);
         }
     }
 
     fn handle_paint_metric(&self,
                            pipeline_id: PipelineId,
                            metric_type: ProgressiveWebMetricType,
-                           metric_value: f64) {
+                           metric_value: u64) {
         let window = self.documents.borrow().find_window(pipeline_id);
         if let Some(window) = window {
             let entry = PerformancePaintTiming::new(&window.upcast::<GlobalScope>(),
                                                     metric_type, metric_value);
             window.Performance().queue_entry(&entry.upcast::<PerformanceEntry>(),
                                              true /* buffer performance entry */);
         }
     }
--- a/servo/components/script_layout_interface/message.rs
+++ b/servo/components/script_layout_interface/message.rs
@@ -92,17 +92,17 @@ pub enum Msg {
     /// Tells layout about a single new scrolling offset from the script. The rest will
     /// remain untouched and layout won't forward this back to script.
     UpdateScrollStateFromScript(ScrollState),
 
     /// Tells layout that script has added some paint worklet modules.
     RegisterPaint(Atom, Vec<Atom>, Box<Painter>),
 
     /// Send to layout the precise time when the navigation started.
-    SetNavigationStart(f64),
+    SetNavigationStart(u64),
 }
 
 #[derive(Debug, PartialEq)]
 pub enum NodesFromPointQueryType {
     All,
     Topmost,
 }
 
--- a/servo/components/script_traits/lib.rs
+++ b/servo/components/script_traits/lib.rs
@@ -117,17 +117,17 @@ pub enum LayoutControlMsg {
     /// Asks layout to run another step in its animation.
     TickAnimations,
     /// Tells layout about the new scrolling offsets of each scrollable stacking context.
     SetScrollStates(Vec<ScrollState>),
     /// Requests the current load state of Web fonts. `true` is returned if fonts are still loading
     /// and `false` is returned if all fonts have loaded.
     GetWebFontLoadState(IpcSender<bool>),
     /// Send the paint time for a specific epoch to the layout thread.
-    PaintMetric(Epoch, f64),
+    PaintMetric(Epoch, u64),
 }
 
 /// can be passed to `LoadUrl` to load a page with GET/POST
 /// parameters or headers
 #[derive(Clone, Debug, Deserialize, Serialize)]
 pub struct LoadData {
     /// The URL.
     pub url: ServoUrl,
@@ -319,17 +319,17 @@ pub enum ConstellationControlMsg {
     DispatchStorageEvent(PipelineId, StorageType, ServoUrl, Option<String>, Option<String>, Option<String>),
     /// Report an error from a CSS parser for the given pipeline
     ReportCSSError(PipelineId, String, u32, u32, String),
     /// Reload the given page.
     Reload(PipelineId),
     /// Notifies the script thread of WebVR events.
     WebVREvents(PipelineId, Vec<WebVREvent>),
     /// Notifies the script thread about a new recorded paint metric.
-    PaintMetric(PipelineId, ProgressiveWebMetricType, f64),
+    PaintMetric(PipelineId, ProgressiveWebMetricType, u64),
 }
 
 impl fmt::Debug for ConstellationControlMsg {
     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         use self::ConstellationControlMsg::*;
         let variant = match *self {
             NavigationResponse(..) => "NavigationResponse",
             AttachLayout(..) => "AttachLayout",
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -611,180 +611,23 @@ macro_rules! impl_gecko_keyword_conversi
                                 extra_gecko_values="all-small-caps petite-caps all-petite-caps unicase titling-caps",
                                 gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
                                 gecko_ffi_name="mFont.variantCaps",
                                 spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
                                 custom_consts=font_variant_caps_custom_consts,
                                 flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
                                 animation_value_type="discrete")}
 
-<%helpers:longhand name="font-weight" animation_value_type="ComputedValue"
-                   flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
-                   spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight">
-    use properties::longhands::system_font::SystemFont;
-
-
-    #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
-    pub enum SpecifiedValue {
-        Normal,
-        Bold,
-        Bolder,
-        Lighter,
-        Weight(computed_value::T),
-        System(SystemFont),
-    }
-
-    /// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
-    pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-                         -> Result<SpecifiedValue, ParseError<'i>> {
-        let result = input.try(|input| {
-            let ident = input.expect_ident().map_err(|_| ())?;
-            match_ignore_ascii_case! { &ident,
-                "normal" => Ok(SpecifiedValue::Normal),
-                "bold" => Ok(SpecifiedValue::Bold),
-                "bolder" => Ok(SpecifiedValue::Bolder),
-                "lighter" => Ok(SpecifiedValue::Lighter),
-                _ => Err(())
-            }
-        });
-        result.or_else(|_| computed_value::T::parse(context, input).map(SpecifiedValue::Weight))
-    }
-
-    impl SpecifiedValue {
-        pub fn from_gecko_keyword(kw: u32) -> Self {
-            computed_value::T::from_int(kw as i32).map(SpecifiedValue::Weight)
-                .expect("Found unexpected value in style struct for font-weight property")
-        }
-    }
-
-    impl SpecifiedValue {
-        pub fn system_font(f: SystemFont) -> Self {
-            SpecifiedValue::System(f)
-        }
-        pub fn get_system(&self) -> Option<SystemFont> {
-            if let SpecifiedValue::System(s) = *self {
-                Some(s)
-            } else {
-                None
-            }
-        }
-    }
-
-    pub mod computed_value {
-        /// As of CSS Fonts Module Level 3, only the following values are
-        /// valid: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
-        ///
-        /// However, system fonts may provide other values. Pango
-        /// may provide 350, 380, and 1000 (on top of the existing values), for example.
-        #[derive(Clone, ComputeSquaredDistance, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq,
-                 ToCss)]
-        #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
-        pub struct T(pub u16);
-
-        impl T {
-            /// Value for normal
-            pub fn normal() -> Self {
-                T(400)
-            }
-
-            /// Value for bold
-            pub fn bold() -> Self {
-                T(700)
-            }
-
-            /// Convert from an integer to Weight
-            pub fn from_int(n: i32) -> Result<Self, ()> {
-                if n >= 100 && n <= 900 && n % 100 == 0 {
-                    Ok(T(n as u16))
-                } else {
-                    Err(())
-                }
-            }
-
-            /// Convert from an Gecko weight
-            pub fn from_gecko_weight(weight: u16) -> Self {
-                // we allow a wider range of weights than is parseable
-                // because system fonts may provide custom values
-                T(weight)
-            }
-
-            /// Weither this weight is bold
-            pub fn is_bold(&self) -> bool {
-                self.0 > 500
-            }
-
-            /// Return the bolder weight
-            pub fn bolder(self) -> Self {
-                if self.0 < 400 {
-                    T(400)
-                } else if self.0 < 600 {
-                    T(700)
-                } else {
-                    T(900)
-                }
-            }
-
-            /// Returns the lighter weight
-            pub fn lighter(self) -> Self {
-                if self.0 < 600 {
-                    T(100)
-                } else if self.0 < 800 {
-                    T(400)
-                } else {
-                    T(700)
-                }
-            }
-        }
-    }
-
-    impl Parse for computed_value::T {
-        fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>)
-            -> Result<Self, ParseError<'i>> {
-                Self::from_int(input.expect_integer()?)
-                    .map_err(|_| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
-            }
-    }
-
-    #[inline]
-    pub fn get_initial_value() -> computed_value::T {
-        computed_value::T::normal()
-    }
-
-    #[inline]
-    pub fn get_initial_specified_value() -> SpecifiedValue {
-        SpecifiedValue::Normal
-    }
-
-    impl ToComputedValue for SpecifiedValue {
-        type ComputedValue = computed_value::T;
-
-        #[inline]
-        fn to_computed_value(&self, context: &Context) -> computed_value::T {
-            match *self {
-                SpecifiedValue::Weight(weight) => weight,
-                SpecifiedValue::Normal => computed_value::T::normal(),
-                SpecifiedValue::Bold => computed_value::T::bold(),
-                SpecifiedValue::Bolder =>
-                    context.builder.get_parent_font().clone_font_weight().bolder(),
-                SpecifiedValue::Lighter =>
-                    context.builder.get_parent_font().clone_font_weight().lighter(),
-                SpecifiedValue::System(_) => {
-                    <%self:nongecko_unreachable>
-                        context.cached_system_font.as_ref().unwrap().font_weight.clone()
-                    </%self:nongecko_unreachable>
-                }
-            }
-        }
-
-        #[inline]
-        fn from_computed_value(computed: &computed_value::T) -> Self {
-            SpecifiedValue::Weight(*computed)
-        }
-    }
-</%helpers:longhand>
+${helpers.predefined_type("font-weight",
+                          "FontWeight",
+                          initial_value="computed::FontWeight::normal()",
+                          initial_specified_value="specified::FontWeight::Normal",
+                          animation_value_type="ComputedValue",
+                          flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
+                          spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight")}
 
 <%helpers:longhand name="font-size" animation_value_type="NonNegativeLength"
                    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
                    allow_quirks="True" spec="https://drafts.csswg.org/css-fonts/#propdef-font-size">
     use app_units::Au;
     use values::specified::AllowQuirks;
     use values::specified::length::FontBaseSize;
     use values::specified::font::{FONT_MEDIUM_PX, KeywordSize};
--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -10,16 +10,25 @@ use style_traits::ToCss;
 use values::animated::ToAnimatedValue;
 use values::computed::{Context, NonNegativeLength, ToComputedValue};
 use values::specified::font as specified;
 use values::specified::length::{FontBaseSize, NoCalcLength};
 
 pub use values::computed::Length as MozScriptMinSize;
 pub use values::specified::font::XTextZoom;
 
+/// As of CSS Fonts Module Level 3, only the following values are
+/// valid: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
+///
+/// However, system fonts may provide other values. Pango
+/// may provide 350, 380, and 1000 (on top of the existing values), for example.
+#[derive(Clone, ComputeSquaredDistance, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToCss)]
+#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
+pub struct FontWeight(pub u16);
+
 #[derive(Animate, ComputeSquaredDistance, MallocSizeOf, ToAnimatedZero)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 /// The computed value of font-size
 pub struct FontSize {
     /// The size.
     pub size: NonNegativeLength,
     /// If derived from a keyword, the keyword and additional transformations applied to it
     pub keyword_info: Option<KeywordInfo>,
@@ -65,16 +74,71 @@ impl From<specified::KeywordSize> for Ke
         KeywordInfo {
             kw: x,
             factor: 1.,
             offset: Au(0).into(),
         }
     }
 }
 
+impl FontWeight {
+    /// Value for normal
+    pub fn normal() -> Self {
+        FontWeight(400)
+    }
+
+    /// Value for bold
+    pub fn bold() -> Self {
+        FontWeight(700)
+    }
+
+    /// Convert from an integer to Weight
+    pub fn from_int(n: i32) -> Result<Self, ()> {
+        if n >= 100 && n <= 900 && n % 100 == 0 {
+            Ok(FontWeight(n as u16))
+        } else {
+            Err(())
+        }
+    }
+
+    /// Convert from an Gecko weight
+    pub fn from_gecko_weight(weight: u16) -> Self {
+        // we allow a wider range of weights than is parseable
+        // because system fonts may provide custom values
+        FontWeight(weight)
+    }
+
+    /// Weither this weight is bold
+    pub fn is_bold(&self) -> bool {
+        self.0 > 500
+    }
+
+    /// Return the bolder weight
+    pub fn bolder(self) -> Self {
+        if self.0 < 400 {
+            FontWeight(400)
+        } else if self.0 < 600 {
+            FontWeight(700)
+        } else {
+            FontWeight(900)
+        }
+    }
+
+    /// Returns the lighter weight
+    pub fn lighter(self) -> Self {
+        if self.0 < 600 {
+            FontWeight(100)
+        } else if self.0 < 800 {
+            FontWeight(400)
+        } else {
+            FontWeight(700)
+        }
+    }
+}
+
 impl FontSize {
     /// The actual computed font size.
     pub fn size(self) -> Au {
         self.size.into()
     }
 }
 
 impl ToCss for FontSize {
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -31,17 +31,17 @@ use super::specified;
 pub use app_units::Au;
 pub use properties::animated_properties::TransitionProperty;
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use self::angle::Angle;
 pub use self::background::{BackgroundSize, BackgroundRepeat};
 pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
 pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing};
-pub use self::font::{XTextZoom, MozScriptMinSize};
+pub use self::font::{FontWeight, MozScriptMinSize, XTextZoom};
 pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
 pub use self::color::{Color, ColorPropertyValue, RGBAColor};
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
 pub use self::rect::LengthOrNumberRect;
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -2,27 +2,118 @@
  * 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/. */
 
 //! Specified values for font properties
 
 #[cfg(feature = "gecko")]
 use Atom;
 use app_units::Au;
-use cssparser::Parser;
+use cssparser::{Parser, Token};
 use parser::{Parse, ParserContext};
 use properties::longhands::system_font::SystemFont;
 use std::fmt;
 use style_traits::{ToCss, StyleParseErrorKind, ParseError};
 use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue};
 use values::specified::{LengthOrPercentage, NoCalcLength};
 use values::specified::length::{AU_PER_PT, AU_PER_PX, FontBaseSize};
 
 const DEFAULT_SCRIPT_MIN_SIZE_PT: u32 = 8;
 
+#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToCss)]
+/// A specified font-weight value
+pub enum FontWeight {
+    /// Normal variant
+    Normal,
+    /// Bold variant
+    Bold,
+    /// Bolder variant
+    Bolder,
+    /// Lighter variant
+    Lighter,
+    /// Computed weight variant
+    Weight(computed::FontWeight),
+    /// System font varaint
+    System(SystemFont),
+}
+
+impl FontWeight {
+    /// Get a specified FontWeight from a gecko keyword
+    pub fn from_gecko_keyword(kw: u32) -> Self {
+        computed::FontWeight::from_int(kw as i32).map(FontWeight::Weight)
+            .expect("Found unexpected value in style struct for font-weight property")
+    }
+
+    /// Get a specified FontWeight from a SystemFont
+    pub fn system_font(f: SystemFont) -> Self {
+        FontWeight::System(f)
+    }
+
+    /// Retreive a SystemFont from FontWeight
+    pub fn get_system(&self) -> Option<SystemFont> {
+        if let FontWeight::System(s) = *self {
+            Some(s)
+        } else {
+            None
+        }
+    }
+}
+
+impl Parse for FontWeight {
+    fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<FontWeight, ParseError<'i>> {
+        let result = match *input.next()? {
+            Token::Ident(ref ident) => {
+                match_ignore_ascii_case! { ident,
+                    "normal" => Ok(FontWeight::Normal),
+                    "bold" => Ok(FontWeight::Bold),
+                    "bolder" => Ok(FontWeight::Bolder),
+                    "lighter" => Ok(FontWeight::Lighter),
+                    _ => Err(()),
+                }
+            }
+            Token::Number { int_value: Some(value), .. } => {
+                computed::FontWeight::from_int(value).map(FontWeight::Weight)
+            },
+            _ => Err(()),
+        };
+
+        result.map_err(|_| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
+    }
+}
+
+impl ToComputedValue for FontWeight {
+    type ComputedValue = computed::FontWeight;
+
+    #[inline]
+    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
+        match *self {
+            FontWeight::Weight(weight) => weight,
+            FontWeight::Normal => computed::FontWeight::normal(),
+            FontWeight::Bold => computed::FontWeight::bold(),
+            FontWeight::Bolder => {
+                context.builder.get_parent_font().clone_font_weight().bolder()
+            },
+            FontWeight::Lighter => {
+                context.builder.get_parent_font().clone_font_weight().lighter()
+            },
+            #[cfg(feature = "gecko")]
+            FontWeight::System(_) => {
+                context.cached_system_font.as_ref().unwrap().font_weight.clone()
+            },
+            #[cfg(not(feature = "gecko"))]
+            FontWeight::System(_) => unreachable!(),
+        }
+    }
+
+    #[inline]
+    fn from_computed_value(computed: &computed::FontWeight) -> Self {
+        FontWeight::Weight(*computed)
+    }
+}
+
 #[derive(Clone, Debug, MallocSizeOf, PartialEq)]
 /// A specified font-size value
 pub enum FontSize {
     /// A length; e.g. 10px.
     Length(LengthOrPercentage),
     /// A keyword value, along with a ratio and absolute offset.
     /// The ratio in any specified keyword value
     /// will be 1 (with offset 0), but we cascade keywordness even
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -25,17 +25,17 @@ use values::specified::calc::CalcNode;
 
 pub use properties::animated_properties::TransitionProperty;
 pub use self::angle::Angle;
 #[cfg(feature = "gecko")]
 pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
 pub use self::background::{BackgroundRepeat, BackgroundSize};
 pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
 pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
-pub use self::font::{XTextZoom, MozScriptMinSize};
+pub use self::font::{FontWeight, MozScriptMinSize, XTextZoom};
 pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
 pub use self::color::{Color, ColorPropertyValue, RGBAColor};
 pub use self::effects::{BoxShadow, Filter, SimpleShadow};
 pub use self::flex::FlexBasis;
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
 pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -960,17 +960,16 @@ pub extern "C" fn Servo_Element_HasPrima
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_Element_GetPrimaryComputedValues(element: RawGeckoElementBorrowed)
                                                          -> ServoStyleContextStrong
 {
     let element = GeckoElement(element);
     let data = element.borrow_data().expect("Getting CVs on unstyled element");
-    assert!(data.has_styles(), "Getting CVs on unstyled element");
     data.styles.primary().clone().into()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_Element_HasPseudoComputedValues(element: RawGeckoElementBorrowed,
                                                         index: usize) -> bool
 {
     let element = GeckoElement(element);
@@ -3450,18 +3449,16 @@ pub extern "C" fn Servo_ResolveStyle(
     element: RawGeckoElementBorrowed,
     _raw_data: RawServoStyleSetBorrowed,
 ) -> ServoStyleContextStrong {
     let element = GeckoElement(element);
     debug!("Servo_ResolveStyle: {:?}", element);
     let data =
         element.borrow_data().expect("Resolving style on unstyled element");
 
-    // TODO(emilio): Downgrade to debug assertions when close to release.
-    assert!(data.has_styles(), "Resolving style on unstyled element");
     debug_assert!(element.has_current_styles(&*data),
                   "Resolving style on {:?} without current styles: {:?}", element, data);
     data.styles.primary().clone().into()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ResolveStyleLazily(
     element: RawGeckoElementBorrowed,
--- a/servo/tests/unit/metrics/interactive_time.rs
+++ b/servo/tests/unit/metrics/interactive_time.rs
@@ -1,14 +1,14 @@
 /* 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/. */
 
 use ipc_channel::ipc;
-use metrics::{InteractiveMetrics, InteractiveFlag, InteractiveWindow};
+use metrics::{InteractiveMetrics, InteractiveFlag};
 use metrics::{ProfilerMetadataFactory, ProgressiveWebMetric};
 use profile_traits::time::{ProfilerChan, TimerMetadata};
 use time;
 
 struct DummyProfilerMetadataFactory {}
 impl ProfilerMetadataFactory for DummyProfilerMetadataFactory {
     fn new_metadata(&self) -> Option<TimerMetadata> {
         None
@@ -19,17 +19,17 @@ impl ProfilerMetadataFactory for DummyPr
 fn test_interactive() -> InteractiveMetrics {
     let (sender, _) = ipc::channel().unwrap();
     let profiler_chan = ProfilerChan(sender);
     let mut interactive = InteractiveMetrics::new(profiler_chan);
 
     assert_eq!((&interactive).get_navigation_start(), None);
     assert_eq!(interactive.get_tti(), None);
 
-    interactive.set_navigation_start(time::precise_time_ns() as f64);
+    interactive.set_navigation_start(time::precise_time_ns());
 
     interactive
 }
 
 #[test]
 fn test_set_dcl() {
     let profiler_metadata_factory = DummyProfilerMetadataFactory {};
 
@@ -47,40 +47,40 @@ fn test_set_dcl() {
 #[test]
 fn test_set_mta() {
     let profiler_metadata_factory = DummyProfilerMetadataFactory {};
 
     let interactive = test_interactive();
     let t = time::precise_time_ns();
     interactive.maybe_set_tti(
         &profiler_metadata_factory,
-        InteractiveFlag::TimeToInteractive(t as f64),
+        InteractiveFlag::TimeToInteractive(t),
     );
     let mta = interactive.get_main_thread_available();
     assert!(mta.is_some());
-    assert_eq!(mta, Some(t as f64));
+    assert_eq!(mta, Some(t));
 
     //try to overwrite
     interactive.maybe_set_tti(
         &profiler_metadata_factory,
-        InteractiveFlag::TimeToInteractive(time::precise_time_ns() as f64),
+        InteractiveFlag::TimeToInteractive(time::precise_time_ns()),
     );
     assert_eq!(interactive.get_main_thread_available(), mta);
     assert_eq!(interactive.get_tti(), None);
 }
 
 #[test]
 fn test_set_tti_dcl() {
     let profiler_metadata_factory = DummyProfilerMetadataFactory {};
 
     let interactive = test_interactive();
     let t = time::precise_time_ns();
     interactive.maybe_set_tti(
         &profiler_metadata_factory,
-        InteractiveFlag::TimeToInteractive(t as f64),
+        InteractiveFlag::TimeToInteractive(t),
     );
     let mta = interactive.get_main_thread_available();
     assert!(mta.is_some());
 
     interactive.maybe_set_tti(&profiler_metadata_factory, InteractiveFlag::DOMContentLoaded);
     let dcl = interactive.get_dom_content_loaded();
     assert!(dcl.is_some());
 
@@ -95,17 +95,17 @@ fn test_set_tti_mta() {
     let interactive = test_interactive();
     interactive.maybe_set_tti(&profiler_metadata_factory, InteractiveFlag::DOMContentLoaded);
     let dcl = interactive.get_dom_content_loaded();
     assert!(dcl.is_some());
 
     let t = time::precise_time_ns();
     interactive.maybe_set_tti(
         &profiler_metadata_factory,
-        InteractiveFlag::TimeToInteractive(t as f64),
+        InteractiveFlag::TimeToInteractive(t),
     );
     let mta = interactive.get_main_thread_available();
     assert!(mta.is_some());
 
     let interactive_time = mta.unwrap() - (&interactive).get_navigation_start().unwrap();
     assert_eq!(interactive.get_tti(), Some(interactive_time));
 }
 
--- a/servo/tests/unit/metrics/paint_time.rs
+++ b/servo/tests/unit/metrics/paint_time.rs
@@ -65,29 +65,29 @@ fn test_common(display_list: &DisplayLis
 
     paint_time_metrics.maybe_observe_paint_time(
         &dummy_profiler_metadata_factory,
         epoch,
         &display_list,
     );
 
     // Should not set any metric until navigation start is set.
-    paint_time_metrics.maybe_set_metric(epoch, 0.);
+    paint_time_metrics.maybe_set_metric(epoch, 0);
     assert_eq!(
         paint_time_metrics.get_first_paint(),
         None,
         "first paint is None"
     );
     assert_eq!(
         paint_time_metrics.get_first_contentful_paint(),
         None,
         "first contentful paint is None"
     );
 
-    let navigation_start = time::precise_time_ns() as f64;
+    let navigation_start = time::precise_time_ns();
     paint_time_metrics.set_navigation_start(navigation_start);
     assert_eq!(
         (&paint_time_metrics).get_navigation_start().unwrap(),
         navigation_start,
         "navigation start is set"
     );
 
     paint_time_metrics
@@ -96,17 +96,17 @@ fn test_common(display_list: &DisplayLis
 #[test]
 fn test_first_paint_setter() {
     let empty_display_list = DisplayList {
         list: Vec::new(),
         clip_scroll_nodes: Vec::new(),
     };
     let epoch = Epoch(0);
     let paint_time_metrics = test_common(&empty_display_list, epoch);
-    let now = time::precise_time_ns() as f64;
+    let now = time::precise_time_ns();
     paint_time_metrics.maybe_set_metric(epoch, now);
     assert!(
         paint_time_metrics.get_first_paint().is_some(),
         "first paint is set"
     );
     assert_eq!(
         paint_time_metrics.get_first_contentful_paint(),
         None,
@@ -130,17 +130,17 @@ fn test_first_contentful_paint_setter() 
         image_rendering: image_rendering::T::auto,
     }));
     let display_list = DisplayList {
         list: vec![image],
         clip_scroll_nodes: Vec::new(),
     };
     let epoch = Epoch(0);
     let paint_time_metrics = test_common(&display_list, epoch);
-    let now = time::precise_time_ns() as f64;
+    let now = time::precise_time_ns();
     paint_time_metrics.maybe_set_metric(epoch, now);
     assert!(
         paint_time_metrics.get_first_contentful_paint().is_some(),
         "first contentful paint is set"
     );
     assert!(
         paint_time_metrics.get_first_paint().is_some(),
         "first paint is set"
--- a/taskcluster/taskgraph/transforms/job/mozharness.py
+++ b/taskcluster/taskgraph/transforms/job/mozharness.py
@@ -33,25 +33,23 @@ mozharness_run_schema = Schema({
     # the mozharness script used to run this task, relative to the testing/
     # directory and using forward slashes even on Windows
     Required('script'): basestring,
 
     # the config files required for the task, relative to
     # testing/mozharness/configs and using forward slashes even on Windows
     Required('config'): [basestring],
 
-    # any additional actions to pass to the mozharness command; not supported
-    # on Windows
+    # any additional actions to pass to the mozharness command
     Optional('actions'): [basestring],
 
-    # any additional options (without leading --) to be passed to mozharness;
-    # not supported on Windows
+    # any additional options (without leading --) to be passed to mozharness
     Optional('options'): [basestring],
 
-    # --custom-build-variant-cfg value (not supported on Windows)
+    # --custom-build-variant-cfg value
     Optional('custom-build-variant-cfg'): basestring,
 
     # Extra metadata to use toward the workspace caching.
     # Only supported on docker-worker
     Optional('extra-workspace-cache-key'): basestring,
 
     # If not false, tooltool downloads will be enabled via relengAPIProxy
     # for either just public files, or all files.  Not supported on Windows
--- a/testing/marionette/element.js
+++ b/testing/marionette/element.js
@@ -844,35 +844,38 @@ element.inViewport = function(el, x = un
  *
  * @param {Element} el
  *     Element to get the container of.
  *
  * @return {Element}
  *     Container element of |el|.
  */
 element.getContainer = function(el) {
-  if (el.localName != "option") {
-    return el;
-  }
 
-  function validContext(ctx) {
-    return ctx.localName == "datalist" || ctx.localName == "select";
+  function findAncestralElement(startNode, validAncestors) {
+    let node = startNode;
+    while (node.parentNode) {
+      node = node.parentNode;
+      if (validAncestors.includes(node.localName)) {
+        return node;
+      }
+    }
+
+    return startNode;
   }
 
-  // does <option> have a valid context,
+  // Does <option> have a valid context,
   // meaning is it a child of <datalist> or <select>?
-  let parent = el;
-  while (parent.parentNode && !validContext(parent)) {
-    parent = parent.parentNode;
+  if (el.localName === "option") {
+    return findAncestralElement(el, ["datalist", "select"]);
   }
 
-  if (!validContext(parent)) {
-    return el;
-  }
-  return parent;
+  // Child nodes of button will not be part of the element tree for
+  // elementsFromPoint until bug 1089326 is fixed.
+  return findAncestralElement(el, ["button"]);
 };
 
 /**
  * An element is in view if it is a member of its own pointer-interactable
  * paint tree.
  *
  * This means an element is considered to be in view, but not necessarily
  * pointer-interactable, if it is found somewhere in the
@@ -888,19 +891,27 @@ element.getContainer = function(el) {
  * @param {Element} el
  *     Element to check if is in view.
  *
  * @return {boolean}
  *     True if <var>el</var> is inside the viewport, or false otherwise.
  */
 element.isInView = function(el) {
   let originalPointerEvents = el.style.pointerEvents;
+
   try {
     el.style.pointerEvents = "auto";
     const tree = element.getPointerInteractablePaintTree(el);
+
+    // Bug 1413493 - <tr> is not part of the returned paint tree yet. As
+    // workaround check the visibility based on the first contained cell.
+    if (el.localName === "tr" && el.cells && el.cells.length > 0) {
+      return tree.includes(el.cells[0]);
+    }
+
     return tree.includes(el);
   } finally {
     el.style.pointerEvents = originalPointerEvents;
   }
 };
 
 /**
  * This function throws the visibility of the element error if the element is
--- a/testing/marionette/harness/marionette_harness/tests/unit/test_click.py
+++ b/testing/marionette/harness/marionette_harness/tests/unit/test_click.py
@@ -118,16 +118,76 @@ class TestLegacyClick(MarionetteTestCase
         self.assertEqual(self.marionette.title, "Marionette Test")
 
     def test_scroll_into_view_near_end(self):
         self.marionette.navigate(fixed_overlay)
         link = self.marionette.find_element(By.TAG_NAME, "a")
         link.click()
         self.assertTrue(self.marionette.execute_script("return window.clicked", sandbox=None))
 
+    def test_inclusive_descendant(self):
+        self.marionette.navigate(inline("""
+            <select multiple>
+              <option>first
+              <option>second
+              <option>third
+             </select>"""))
+        select = self.marionette.find_element(By.TAG_NAME, "select")
+
+        # This tests that the pointer-interactability test does not
+        # cause an ElementClickInterceptedException.
+        #
+        # At a <select multiple>'s in-view centre point, you might
+        # find a fully rendered <option>.  Marionette should test that
+        # the paint tree at this point _contains_ <option>, not that the
+        # first element of the paint tree is _equal_ to <select>.
+        select.click()
+
+        # Bug 1413821 - Click does not select an option on Android
+        if self.marionette.session_capabilities["browserName"] != "fennec":
+            self.assertNotEqual(select.get_property("selectedIndex"), -1)
+
+    def test_container_is_select(self):
+        self.marionette.navigate(inline("""
+            <select>
+              <option>foo</option>
+            </select>"""))
+        option = self.marionette.find_element(By.TAG_NAME, "option")
+        option.click()
+        self.assertTrue(option.get_property("selected"))
+
+    def test_container_is_button(self):
+        self.marionette.navigate(inline("""
+          <button onclick="window.clicked = true;">
+            <span><em>foo</em></span>
+          </button>"""))
+        span = self.marionette.find_element(By.TAG_NAME, "span")
+        span.click()
+        self.assertTrue(self.marionette.execute_script("return window.clicked", sandbox=None))
+
+    def test_container_element_outside_view(self):
+        self.marionette.navigate(inline("""
+            <select style="margin-top: 100vh">
+              <option>foo</option>
+            </select>"""))
+        option = self.marionette.find_element(By.TAG_NAME, "option")
+        option.click()
+        self.assertTrue(option.get_property("selected"))
+
+    def test_table_tr(self):
+        self.marionette.navigate(inline("""
+          <table>
+            <tr><td onclick="window.clicked = true;">
+              foo
+            </td></tr>
+          </table>"""))
+        tr = self.marionette.find_element(By.TAG_NAME, "tr")
+        tr.click()
+        self.assertTrue(self.marionette.execute_script("return window.clicked", sandbox=None))
+
 
 class TestClick(TestLegacyClick):
     """Uses WebDriver specification compatible element interactability
     checks.
     """
 
     def setUp(self):
         TestLegacyClick.setUp(self)
@@ -154,19 +214,20 @@ class TestClick(TestLegacyClick):
              width: 200px;
              height: 200px;
 
              /* move centre point off viewport vertically */
              top: -105px;
             }
             </style>
 
-            <div></div>"""))
+            <div onclick="window.clicked = true;"></div>"""))
 
         self.marionette.find_element(By.TAG_NAME, "div").click()
+        self.assertTrue(self.marionette.execute_script("return window.clicked", sandbox=None))
 
     def test_centre_outside_viewport_horizontally(self):
         self.marionette.navigate(inline("""
             <style>
             * { margin: 0; padding: 0; }
             div {
              display: block;
              position: absolute;
@@ -174,19 +235,20 @@ class TestClick(TestLegacyClick):
              width: 200px;
              height: 200px;
 
              /* move centre point off viewport horizontally */
              left: -105px;
             }
             </style>
 
-            <div></div>"""))
+            <div onclick="window.clicked = true;"></div>"""))
 
         self.marionette.find_element(By.TAG_NAME, "div").click()
+        self.assertTrue(self.marionette.execute_script("return window.clicked", sandbox=None))
 
     def test_centre_outside_viewport(self):
         self.marionette.navigate(inline("""
             <style>
             * { margin: 0; padding: 0; }
             div {
              display: block;
              position: absolute;
@@ -195,61 +257,45 @@ class TestClick(TestLegacyClick):
              height: 200px;
 
              /* move centre point off viewport */
              left: -105px;
              top: -105px;
             }
             </style>
 
-            <div></div>"""))
+            <div onclick="window.clicked = true;"></div>"""))
 
         self.marionette.find_element(By.TAG_NAME, "div").click()
+        self.assertTrue(self.marionette.execute_script("return window.clicked", sandbox=None))
 
     def test_css_transforms(self):
         self.marionette.navigate(inline("""
             <style>
             * { margin: 0; padding: 0; }
             div {
              display: block;
              background-color: blue;
              width: 200px;
              height: 200px;
 
              transform: translateX(-105px);
             }
             </style>
 
-            <div></div>"""))
+            <div onclick="window.clicked = true;"></div>"""))
 
         self.marionette.find_element(By.TAG_NAME, "div").click()
+        self.assertTrue(self.marionette.execute_script("return window.clicked", sandbox=None))
 
     def test_input_file(self):
         self.marionette.navigate(inline("<input type=file>"))
         with self.assertRaises(errors.InvalidArgumentException):
             self.marionette.find_element(By.TAG_NAME, "input").click()
 
-    def test_container_element(self):
-        self.marionette.navigate(inline("""
-            <select>
-              <option>foo</option>
-            </select>"""))
-        option = self.marionette.find_element(By.TAG_NAME, "option")
-        option.click()
-        self.assertTrue(option.get_property("selected"))
-
-    def test_container_element_outside_view(self):
-        self.marionette.navigate(inline("""
-            <select style="margin-top: 100vh">
-              <option>foo</option>
-            </select>"""))
-        option = self.marionette.find_element(By.TAG_NAME, "option")
-        option.click()
-        self.assertTrue(option.get_property("selected"))
-
     def test_obscured_element(self):
         self.marionette.navigate(obscured_overlay)
         overlay = self.marionette.find_element(By.ID, "overlay")
         obscured = self.marionette.find_element(By.ID, "obscured")
 
         overlay.click()
         with self.assertRaises(errors.ElementClickInterceptedException):
             obscured.click()
@@ -267,33 +313,16 @@ class TestClick(TestLegacyClick):
         button = self.marionette.find_element(By.TAG_NAME, "button")
         self.assertEqual("none", button.value_of_css_property("pointer-events"))
 
         with self.assertRaisesRegexp(errors.ElementClickInterceptedException,
                                      "does not have pointer events enabled"):
             button.click()
         self.assertFalse(self.marionette.execute_script("return window.clicked", sandbox=None))
 
-    def test_inclusive_descendant(self):
-        self.marionette.navigate(inline("""
-            <select multiple>
-              <option>first
-              <option>second
-              <option>third
-             </select>"""))
-        select = self.marionette.find_element(By.TAG_NAME, "select")
-
-        # This tests that the pointer-interactability test does not
-        # cause an ElementClickInterceptedException.
-        #
-        # At a <select multiple>'s in-view centre point, you might
-        # find a fully rendered <option>.  Marionette should test that
-        # the paint tree at this point _contains_ <option>, not that the
-        # first element of the paint tree is _equal_ to <select>.
-        select.click()
 
 
 class TestClickNavigation(MarionetteTestCase):
 
     def setUp(self):
         super(TestClickNavigation, self).setUp()
 
         self.test_page = self.marionette.absolute_url("clicks.html")
--- a/testing/mozharness/mozharness/mozilla/l10n/multi_locale_build.py
+++ b/testing/mozharness/mozharness/mozilla/l10n/multi_locale_build.py
@@ -122,19 +122,20 @@ class MultiLocaleBuild(LocalesMixin, Mer
     # pull_locale_source() defined in LocalesMixin.
 
     def build(self):
         c = self.config
         dirs = self.query_abs_dirs()
         self.copyfile(os.path.join(dirs['abs_work_dir'], c['mozconfig']),
                       os.path.join(dirs['abs_mozilla_dir'], 'mozconfig'),
                       error_level=FATAL)
-        command = "make -f client.mk build"
+
+        mach = os.path.join(dirs['abs_mozilla_dir'], 'mach')
         env = self.query_env()
-        if self._process_command(command=command,
+        if self._process_command(command=[sys.executable, mach, 'build'],
                                  cwd=dirs['abs_mozilla_dir'],
                                  env=env, error_list=MakefileErrorList):
             self.fatal("Erroring out after the build failed.")
 
     def add_locales(self):
         c = self.config
         dirs = self.query_abs_dirs()
         locales = self.query_locales()
--- a/testing/mozharness/scripts/mobile_l10n.py
+++ b/testing/mozharness/scripts/mobile_l10n.py
@@ -421,36 +421,38 @@ class MobileSingleLocale(MockMixin, Loca
     def clone_locales(self):
         self.pull_locale_source()
 
     # list_locales() is defined in LocalesMixin.
 
     def _setup_configure(self, buildid=None):
         dirs = self.query_abs_dirs()
         env = self.query_repack_env()
-        make = self.query_exe("make")
-        if self.run_command_m([make, "-f", "client.mk", "configure"],
+
+        mach = os.path.join(dirs['abs_mozilla_dir'], 'mach')
+
+        if self.run_command_m([sys.executable, mach, 'configure'],
                               cwd=dirs['abs_mozilla_dir'],
                               env=env,
                               error_list=MakefileErrorList):
             self.fatal("Configure failed!")
 
-        # Run 'make export' in objdir/config to get nsinstall
-        self.run_command_m([make, 'export'],
-                           cwd=os.path.join(dirs['abs_objdir'], 'config'),
-                           env=env,
-                           error_list=MakefileErrorList,
-                           halt_on_failure=True)
+        # Invoke the build system to get nsinstall and buildid.h.
+        targets = [
+            'config/export',
+            'buildid.h',
+        ]
 
-        # Run 'make buildid.h' in objdir/ to get the buildid.h file
-        cmd = [make, 'buildid.h']
+        # Force the buildid if one is defined.
         if buildid:
-            cmd.append('MOZ_BUILD_DATE=%s' % str(buildid))
-        self.run_command_m(cmd,
-                           cwd=dirs['abs_objdir'],
+            env = dict(env)
+            env['MOZ_BUILD_DATE'] = str(buildid)
+
+        self.run_command_m([sys.executable, mach, 'build'] + targets,
+                           cwd=dirs['abs_mozilla_dir'],
                            env=env,
                            error_list=MakefileErrorList,
                            halt_on_failure=True)
 
     def setup(self):
         c = self.config
         dirs = self.query_abs_dirs()
         mozconfig_path = os.path.join(dirs['abs_mozilla_dir'], '.mozconfig')
--- a/testing/web-platform/mach_test_package_commands.py
+++ b/testing/web-platform/mach_test_package_commands.py
@@ -1,15 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import unicode_literals
 
 import os
+import sys
 
 from mach_commands_base import WebPlatformTestsRunner, create_parser_wpt
 from mach.decorators import (
     CommandProvider,
     Command,
 )
 
 
@@ -41,17 +42,17 @@ class WebPlatformTestsRunnerSetup(object
         kwargs["capture_stdio"] = True
 
         if kwargs["exclude"] is None and kwargs["include"] is None and not sys.platform.startswith("linux"):
             kwargs["exclude"] = ["css"]
 
         if kwargs["webdriver_binary"] is None:
             kwargs["webdriver_binary"] = os.path.join(self.context.bin_dir, "geckodriver")
 
-        kwargs = wptcommandline.check_args(kwargs)
+        return wptcommandline.check_args(kwargs)
 
     def kwargs_wptrun(self, kwargs):
         raise NotImplementedError
 
 
 @CommandProvider
 class MachCommands(object):
     def __init__(self, context):
--- a/toolkit/crashreporter/CrashSubmit.jsm
+++ b/toolkit/crashreporter/CrashSubmit.jsm
@@ -486,24 +486,24 @@ this.CrashSubmit = {
   pendingIDs: async function CrashSubmit_pendingIDs(minFileDate) {
     let ids = [];
     let dirIter = null;
     let pendingDir = getDir("pending");
 
     try {
       dirIter = new OS.File.DirectoryIterator(pendingDir);
     } catch (ex) {
-      if (ex.becauseNoSuchFile) {
-        return ids;
-      }
-
       Cu.reportError(ex);
       throw ex;
     }
 
+    if (!(await dirIter.exists())) {
+      return ids;
+    }
+
     try {
       let entries = Object.create(null);
       let ignored = Object.create(null);
 
       // `await` in order to ensure all callbacks are called
       await dirIter.forEach(entry => {
         if (!entry.isDir /* is file */) {
           let matches = entry.name.match(/(.+)\.dmp$/);
--- a/widget/cocoa/nsPrintOptionsX.h
+++ b/widget/cocoa/nsPrintOptionsX.h
@@ -34,11 +34,22 @@ public:
                                      mozilla::embedding::PrintData* data);
   NS_IMETHODIMP DeserializeToPrintSettings(const mozilla::embedding::PrintData& data,
                                            nsIPrintSettings* settings);
 
 protected:
   nsresult   _CreatePrintSettings(nsIPrintSettings **_retval);
   nsresult   ReadPrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags);
   nsresult   WritePrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags);
+
+private:
+  /* Serialization done in child to be deserialized in the parent */
+  nsresult SerializeToPrintDataChild(nsIPrintSettings* aSettings,
+                                     nsIWebBrowserPrint* aWBP,
+                                     mozilla::embedding::PrintData* data);
+
+  /* Serialization done in parent to be deserialized in the child */
+  nsresult SerializeToPrintDataParent(nsIPrintSettings* aSettings,
+                                      nsIWebBrowserPrint* aWBP,
+                                      mozilla::embedding::PrintData* data);
 };
 
 #endif // nsPrintOptionsX_h_
--- a/widget/cocoa/nsPrintOptionsX.mm
+++ b/widget/cocoa/nsPrintOptionsX.mm
@@ -26,52 +26,82 @@ nsPrintOptionsX::SerializeToPrintData(ns
                                       nsIWebBrowserPrint* aWBP,
                                       PrintData* data)
 {
   nsresult rv = nsPrintOptions::SerializeToPrintData(aSettings, aWBP, data);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  RefPtr<nsPrintSettingsX> settingsX(do_QueryObject(aSettings));
+  if (NS_WARN_IF(!settingsX)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  double adjustedWidth, adjustedHeight;
+  settingsX->GetAdjustedPaperSize(&adjustedWidth, &adjustedHeight);
+  data->adjustedPaperWidth() = adjustedWidth;
+  data->adjustedPaperHeight() = adjustedHeight;
+
+  if (XRE_IsParentProcess()) {
+    return SerializeToPrintDataParent(aSettings, aWBP, data);
+  }
+
+  return SerializeToPrintDataChild(aSettings, aWBP, data);
+}
+
+nsresult
+nsPrintOptionsX::SerializeToPrintDataChild(nsIPrintSettings* aSettings,
+                                           nsIWebBrowserPrint* aWBP,
+                                           PrintData* data)
+{
+  // If we are in the child process, we don't need to populate
+  // nsPrintSettingsX completely. The parent discards almost all of
+  // this data (bug 1328975). Furthermore, reading some of the
+  // printer/printing settings from the OS causes a connection to the
+  // printer to be made which is blocked by sandboxing and results in hangs.
   if (aWBP) {
     // When serializing an nsIWebBrowserPrint, we need to pass up the first
     // document name. We could pass up the entire collection of document
     // names, but the OS X printing prompt code only really cares about
     // the first one, so we just send the first to save IPC traffic.
     char16_t** docTitles;
     uint32_t titleCount;
-    rv = aWBP->EnumerateDocumentNames(&titleCount, &docTitles);
+    nsresult rv = aWBP->EnumerateDocumentNames(&titleCount, &docTitles);
     if (NS_SUCCEEDED(rv)) {
       if (titleCount > 0) {
         data->printJobName().Assign(docTitles[0]);
       }
 
       for (int32_t i = titleCount - 1; i >= 0; i--) {
         free(docTitles[i]);
       }
       free(docTitles);
       docTitles = nullptr;
     }
   }
 
+  return NS_OK;
+}
+
+nsresult
+nsPrintOptionsX::SerializeToPrintDataParent(nsIPrintSettings* aSettings,
+                                            nsIWebBrowserPrint* aWBP,
+                                            PrintData* data)
+{
   RefPtr<nsPrintSettingsX> settingsX(do_QueryObject(aSettings));
   if (NS_WARN_IF(!settingsX)) {
     return NS_ERROR_FAILURE;
   }
 
   NSPrintInfo* printInfo = settingsX->GetCocoaPrintInfo();
   if (NS_WARN_IF(!printInfo)) {
     return NS_ERROR_FAILURE;
   }
 
-  double adjustedWidth, adjustedHeight;
-  settingsX->GetAdjustedPaperSize(&adjustedWidth, &adjustedHeight);
-  data->adjustedPaperWidth() = adjustedWidth;
-  data->adjustedPaperHeight() = adjustedHeight;
-
   NSDictionary* dict = [printInfo dictionary];
   if (NS_WARN_IF(!dict)) {
     return NS_ERROR_FAILURE;
   }
 
   NSString* printerName = [dict objectForKey: NSPrintPrinterName];
   if (printerName) {
     nsCocoaUtils::GetStringForNSString(printerName, data->printerName());
@@ -151,136 +181,26 @@ NS_IMETHODIMP
 nsPrintOptionsX::DeserializeToPrintSettings(const PrintData& data,
                                             nsIPrintSettings* settings)
 {
   nsresult rv = nsPrintOptions::DeserializeToPrintSettings(data, settings);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  if (data.orientation() == nsIPrintSettings::kPortraitOrientation) {
+    settings->SetOrientation(nsIPrintSettings::kPortraitOrientation);
+  } else {
+    settings->SetOrientation(nsIPrintSettings::kLandscapeOrientation);
+  }
+
   RefPtr<nsPrintSettingsX> settingsX(do_QueryObject(settings));
   if (NS_WARN_IF(!settingsX)) {
     return NS_ERROR_FAILURE;
   }
-
-  NSPrintInfo* sharedPrintInfo = [NSPrintInfo sharedPrintInfo];
-  if (NS_WARN_IF(!sharedPrintInfo)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  NSDictionary* sharedDict = [sharedPrintInfo dictionary];
-  if (NS_WARN_IF(!sharedDict)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  // We need to create a new NSMutableDictionary to pass to NSPrintInfo with
-  // the values that we got from the other process.
-  NSMutableDictionary* newPrintInfoDict =
-    [NSMutableDictionary dictionaryWithDictionary:sharedDict];
-  if (NS_WARN_IF(!newPrintInfoDict)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  NSString* printerName = nsCocoaUtils::ToNSString(data.printerName());
-  if (printerName) {
-    NSPrinter* printer = [NSPrinter printerWithName: printerName];
-    if (printer) {
-      [newPrintInfoDict setObject: printer forKey: NSPrintPrinter];
-      [newPrintInfoDict setObject: printerName forKey: NSPrintPrinterName];
-    }
-  }
-
-  [newPrintInfoDict setObject: [NSNumber numberWithInt: data.numCopies()]
-                    forKey: NSPrintCopies];
-  [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printAllPages()]
-                    forKey: NSPrintAllPages];
-  [newPrintInfoDict setObject: [NSNumber numberWithInt: data.startPageRange()]
-                    forKey: NSPrintFirstPage];
-  [newPrintInfoDict setObject: [NSNumber numberWithInt: data.endPageRange()]
-                    forKey: NSPrintLastPage];
-  [newPrintInfoDict setObject: [NSNumber numberWithBool: data.mustCollate()]
-                    forKey: NSPrintMustCollate];
-  [newPrintInfoDict setObject: [NSNumber numberWithBool: data.printReversed()]
-                    forKey: NSPrintReversePageOrder];
-
-  [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.disposition())
-                    forKey: NSPrintJobDisposition];
-
-  [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.paperName())
-                    forKey: NSPrintPaperName];
-
-  [newPrintInfoDict setObject: [NSNumber numberWithFloat: data.scalingFactor()]
-                    forKey: NSPrintScalingFactor];
-
-  CGFloat width = data.paperWidth() * data.widthScale();
-  CGFloat height = data.paperHeight() * data.heightScale();
-  [newPrintInfoDict setObject: [NSValue valueWithSize:NSMakeSize(width,height)]
-                    forKey: NSPrintPaperSize];
-
-  int paperOrientation;
-  if (data.orientation() == nsIPrintSettings::kPortraitOrientation) {
-    paperOrientation = NS_PAPER_ORIENTATION_PORTRAIT;
-    settings->SetOrientation(nsIPrintSettings::kPortraitOrientation);
-  } else {
-    paperOrientation = NS_PAPER_ORIENTATION_LANDSCAPE;
-    settings->SetOrientation(nsIPrintSettings::kLandscapeOrientation);
-  }
-  [newPrintInfoDict setObject: [NSNumber numberWithInt:paperOrientation]
-                    forKey: NSPrintOrientation];
-
-  [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesAcross()]
-                    forKey: NSPrintPagesAcross];
-  [newPrintInfoDict setObject: [NSNumber numberWithShort: data.pagesDown()]
-                    forKey: NSPrintPagesDown];
-  [newPrintInfoDict setObject: [NSNumber numberWithBool: data.detailedErrorReporting()]
-                    forKey: NSPrintDetailedErrorReporting];
-  [newPrintInfoDict setObject: nsCocoaUtils::ToNSString(data.faxNumber())
-                    forKey: NSPrintFaxNumber];
-  [newPrintInfoDict setObject: [NSNumber numberWithBool: data.addHeaderAndFooter()]
-                    forKey: NSPrintHeaderAndFooter];
-  [newPrintInfoDict setObject: [NSNumber numberWithBool: data.fileNameExtensionHidden()]
-                    forKey: NSPrintJobSavingFileNameExtensionHidden];
-
-  // At this point, the base class should have properly deserialized the print
-  // options bitfield for nsIPrintSettings, so that it holds the correct value
-  // for kEnableSelectionRB, which we use to set NSPrintSelectionOnly.
-
-  bool printSelectionOnly = false;
-  rv = settings->GetPrintOptions(nsIPrintSettings::kEnableSelectionRB, &printSelectionOnly);
-  if (NS_SUCCEEDED(rv)) {
-    [newPrintInfoDict setObject: [NSNumber numberWithBool: printSelectionOnly]
-                      forKey: NSPrintSelectionOnly];
-  } else {
-    [newPrintInfoDict setObject: [NSNumber numberWithBool: NO]
-                      forKey: NSPrintSelectionOnly];
-  }
-
-  NSURL* jobSavingURL =
-    [NSURL URLWithString: nsCocoaUtils::ToNSString(data.toFileName())];
-  if (jobSavingURL) {
-    [newPrintInfoDict setObject: jobSavingURL forKey: NSPrintJobSavingURL];
-  }
-
-  NSTimeInterval timestamp = data.printTime();
-  NSDate* printTime = [NSDate dateWithTimeIntervalSinceReferenceDate: timestamp];
-  if (printTime) {
-    [newPrintInfoDict setObject: printTime forKey: NSPrintTime];
-  }
-
-  // Next, we create a new NSPrintInfo with the values in our dictionary.
-  NSPrintInfo* newPrintInfo =
-    [[NSPrintInfo alloc] initWithDictionary: newPrintInfoDict];
-  if (NS_WARN_IF(!newPrintInfo)) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-
-  // And now swap in the new NSPrintInfo we've just populated.
-  settingsX->SetCocoaPrintInfo(newPrintInfo);
-  [newPrintInfo release];
-
   settingsX->SetAdjustedPaperSize(data.adjustedPaperWidth(),
                                   data.adjustedPaperHeight());
 
   return NS_OK;
 }
 
 nsresult
 nsPrintOptionsX::ReadPrefs(nsIPrintSettings* aPS, const nsAString& aPrinterName, uint32_t aFlags)
--- a/widget/cocoa/nsPrintSettingsX.mm
+++ b/widget/cocoa/nsPrintSettingsX.mm
@@ -291,43 +291,57 @@ void nsPrintSettingsX::GetAdjustedPaperS
   *aHeight = mAdjustedPaperHeight;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::SetScaling(double aScaling)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
-  [printInfoDict setObject: [NSNumber numberWithFloat: aScaling]
-   forKey: NSPrintScalingFactor];
-  NSPrintInfo* newPrintInfo =
-      [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
-  if (NS_WARN_IF(!newPrintInfo)) {
-    return NS_ERROR_OUT_OF_MEMORY;
+  // Only use NSPrintInfo data in the parent process. The
+  // child process' instance is not needed or used.
+  if (XRE_IsParentProcess()) {
+    NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
+    [printInfoDict setObject: [NSNumber numberWithFloat: aScaling]
+     forKey: NSPrintScalingFactor];
+    NSPrintInfo* newPrintInfo =
+        [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
+    if (NS_WARN_IF(!newPrintInfo)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    SetCocoaPrintInfo(newPrintInfo);
+    [newPrintInfo release];
+  } else {
+    nsPrintSettings::SetScaling(aScaling);
   }
 
-  SetCocoaPrintInfo(newPrintInfo);
-  [newPrintInfo release];
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::GetScaling(double *aScaling)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  NSDictionary* printInfoDict = [mPrintInfo dictionary];
+  // Only use NSPrintInfo data in the parent process. The
+  // child process' instance is not needed or used.
+  if (XRE_IsParentProcess()) {
+    NSDictionary* printInfoDict = [mPrintInfo dictionary];
 
-  *aScaling = [[printInfoDict objectForKey: NSPrintScalingFactor] doubleValue];
+    *aScaling =
+      [[printInfoDict objectForKey: NSPrintScalingFactor] doubleValue];
 
-  // Limit scaling precision to whole number percent values
-  *aScaling = round(*aScaling * 100.0) / 100.0;
+    // Limit scaling precision to whole number percent values
+    *aScaling = round(*aScaling * 100.0) / 100.0;
+  } else {
+    nsPrintSettings::GetScaling(aScaling);
+  }
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::SetToFileName(const nsAString& aToFileName)
@@ -366,133 +380,171 @@ nsPrintSettingsX::SetToFileName(const ns
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::GetOrientation(int32_t *aOrientation)
 {
-  if ([mPrintInfo orientation] == NS_PAPER_ORIENTATION_PORTRAIT) {
-    *aOrientation = nsIPrintSettings::kPortraitOrientation;
+  // Only use NSPrintInfo data in the parent process. The
+  // child process' instance is not needed or used.
+  if (XRE_IsParentProcess()) {
+    if ([mPrintInfo orientation] == NS_PAPER_ORIENTATION_PORTRAIT) {
+      *aOrientation = nsIPrintSettings::kPortraitOrientation;
+    } else {
+      *aOrientation = nsIPrintSettings::kLandscapeOrientation;
+    }
   } else {
-    *aOrientation = nsIPrintSettings::kLandscapeOrientation;
+    nsPrintSettings::GetOrientation(aOrientation);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::SetOrientation(int32_t aOrientation)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
-  if (aOrientation == nsIPrintSettings::kPortraitOrientation) {
-    [printInfoDict setObject: [NSNumber numberWithInt: NS_PAPER_ORIENTATION_PORTRAIT]
-     forKey: NSPrintOrientation];
+  // Only use NSPrintInfo data in the parent process. The
+  // child process' instance is not needed or used.
+  if (XRE_IsParentProcess()) {
+    NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
+    if (aOrientation == nsIPrintSettings::kPortraitOrientation) {
+      [printInfoDict setObject: [NSNumber numberWithInt: NS_PAPER_ORIENTATION_PORTRAIT]
+       forKey: NSPrintOrientation];
+    } else {
+      [printInfoDict setObject: [NSNumber numberWithInt: NS_PAPER_ORIENTATION_LANDSCAPE]
+       forKey: NSPrintOrientation];
+    }
+    NSPrintInfo* newPrintInfo =
+        [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
+    if (NS_WARN_IF(!newPrintInfo)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    SetCocoaPrintInfo(newPrintInfo);
+    [newPrintInfo release];
   } else {
-    [printInfoDict setObject: [NSNumber numberWithInt: NS_PAPER_ORIENTATION_LANDSCAPE]
-     forKey: NSPrintOrientation];
-  }
-  NSPrintInfo* newPrintInfo =
-      [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
-  if (NS_WARN_IF(!newPrintInfo)) {
-    return NS_ERROR_OUT_OF_MEMORY;
+    nsPrintSettings::SetOrientation(aOrientation);
   }
 
-  SetCocoaPrintInfo(newPrintInfo);
-  [newPrintInfo release];
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::SetUnwriteableMarginTop(double aUnwriteableMarginTop)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   nsPrintSettings::SetUnwriteableMarginTop(aUnwriteableMarginTop);
-  NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
-  [printInfoDict setObject : [NSNumber numberWithDouble: aUnwriteableMarginTop]
-   forKey : NSPrintTopMargin];
-  NSPrintInfo* newPrintInfo =
-      [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
-  if (NS_WARN_IF(!newPrintInfo)) {
-    return NS_ERROR_OUT_OF_MEMORY;
+
+  // Only use NSPrintInfo data in the parent process. The
+  // child process' instance is not needed or used.
+  if (XRE_IsParentProcess()) {
+    NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
+    [printInfoDict setObject :
+        [NSNumber numberWithDouble: aUnwriteableMarginTop]
+        forKey : NSPrintTopMargin];
+    NSPrintInfo* newPrintInfo =
+        [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
+    if (NS_WARN_IF(!newPrintInfo)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    SetCocoaPrintInfo(newPrintInfo);
+    [newPrintInfo release];
   }
 
-  SetCocoaPrintInfo(newPrintInfo);
-  [newPrintInfo release];
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::SetUnwriteableMarginLeft(double aUnwriteableMarginLeft)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   nsPrintSettings::SetUnwriteableMarginLeft(aUnwriteableMarginLeft);
-  NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
-  [printInfoDict setObject : [NSNumber numberWithDouble: aUnwriteableMarginLeft]
-   forKey : NSPrintLeftMargin];
-  NSPrintInfo* newPrintInfo =
-      [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
-  if (NS_WARN_IF(!newPrintInfo)) {
-    return NS_ERROR_OUT_OF_MEMORY;
+
+  // Only use NSPrintInfo data in the parent process. The
+  // child process' instance is not needed or used.
+  if (XRE_IsParentProcess()) {
+    NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
+    [printInfoDict setObject : [NSNumber numberWithDouble: aUnwriteableMarginLeft]
+     forKey : NSPrintLeftMargin];
+    NSPrintInfo* newPrintInfo =
+        [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
+    if (NS_WARN_IF(!newPrintInfo)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    SetCocoaPrintInfo(newPrintInfo);
+    [newPrintInfo release];
   }
 
-  SetCocoaPrintInfo(newPrintInfo);
-  [newPrintInfo release];
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::SetUnwriteableMarginBottom(double aUnwriteableMarginBottom)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   nsPrintSettings::SetUnwriteableMarginBottom(aUnwriteableMarginBottom);
-  NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
-  [printInfoDict setObject : [NSNumber numberWithDouble: aUnwriteableMarginBottom]
-   forKey : NSPrintBottomMargin];
-  NSPrintInfo* newPrintInfo =
-      [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
-  if (NS_WARN_IF(!newPrintInfo)) {
-    return NS_ERROR_OUT_OF_MEMORY;
+
+  // Only use NSPrintInfo data in the parent process. The
+  // child process' instance is not needed or used.
+  if (XRE_IsParentProcess()) {
+    NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
+    [printInfoDict setObject : [NSNumber numberWithDouble: aUnwriteableMarginBottom]
+     forKey : NSPrintBottomMargin];
+    NSPrintInfo* newPrintInfo =
+        [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
+    if (NS_WARN_IF(!newPrintInfo)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    SetCocoaPrintInfo(newPrintInfo);
+    [newPrintInfo release];
   }
 
-  SetCocoaPrintInfo(newPrintInfo);
-  [newPrintInfo release];
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 NS_IMETHODIMP
 nsPrintSettingsX::SetUnwriteableMarginRight(double aUnwriteableMarginRight)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   nsPrintSettings::SetUnwriteableMarginRight(aUnwriteableMarginRight);
-  NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
-  [printInfoDict setObject : [NSNumber numberWithDouble: aUnwriteableMarginRight]
-   forKey : NSPrintRightMargin];
-  NSPrintInfo* newPrintInfo =
-      [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
-  if (NS_WARN_IF(!newPrintInfo)) {
-    return NS_ERROR_OUT_OF_MEMORY;
+
+  // Only use NSPrintInfo data in the parent process. The
+  // child process' instance is not needed or used.
+  if (XRE_IsParentProcess()) {
+    NSMutableDictionary* printInfoDict = [mPrintInfo dictionary];
+    [printInfoDict setObject : [NSNumber numberWithDouble: aUnwriteableMarginRight]
+     forKey : NSPrintRightMargin];
+    NSPrintInfo* newPrintInfo =
+        [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
+    if (NS_WARN_IF(!newPrintInfo)) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    SetCocoaPrintInfo(newPrintInfo);
+    [newPrintInfo release];
   }
 
-  SetCocoaPrintInfo(newPrintInfo);
-  [newPrintInfo release];
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 int
 nsPrintSettingsX::GetCocoaUnit(int16_t aGeckoUnit)
 {