merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 27 Jan 2017 10:42:54 +0100
changeset 331381 8dbe8993536645eceeeaf8cb6fc53c03602d7c84
parent 331380 dad46f4125887d88734759a91595738105f85b37 (current diff)
parent 331322 818d639bfe3e3b0f552cba9b0efa0da6dc323511 (diff)
child 331382 3703867c611a64c40472658a56912eb35670fe2e
child 331389 07d7ecbf77e3be59797f16234d357a02bb38ed8b
child 331472 cfec9f1d71cc2f0fa4667a5a9b6a099bf4340540
push id86225
push usercbook@mozilla.com
push dateFri, 27 Jan 2017 10:16:50 +0000
treeherdermozilla-inbound@3703867c611a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone54.0a1
first release with
nightly linux32
8dbe89935366 / 54.0a1 / 20170127110036 / files
nightly linux64
8dbe89935366 / 54.0a1 / 20170127110036 / files
nightly mac
8dbe89935366 / 54.0a1 / 20170127030206 / files
nightly win32
8dbe89935366 / 54.0a1 / 20170127030206 / files
nightly win64
8dbe89935366 / 54.0a1 / 20170127030206 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
browser/extensions/pdfjs/content/network.js
devtools/client/netmonitor/test/browser.ini
dom/ipc/PMemoryReportRequest.ipdl
js/src/vm/SPSProfiler.cpp
js/src/vm/SPSProfiler.h
testing/web-platform/meta/XMLHttpRequest/setrequestheader-bogus-value.htm.ini
xpcom/tests/MoreTestingAtomList.h
xpcom/tests/MoreTestingAtoms.cpp
xpcom/tests/MoreTestingAtoms.h
xpcom/tests/TestStaticAtoms.cpp
xpcom/tests/TestingAtoms.cpp
xpcom/tests/TestingAtoms.h
--- a/accessible/tests/browser/e10s/browser.ini
+++ b/accessible/tests/browser/e10s/browser.ini
@@ -33,17 +33,17 @@ support-files =
 [browser_treeupdate_ariadialog.js]
 [browser_treeupdate_ariaowns.js]
 [browser_treeupdate_canvas.js]
 [browser_treeupdate_cssoverflow.js]
 [browser_treeupdate_doc.js]
 [browser_treeupdate_gencontent.js]
 [browser_treeupdate_hidden.js]
 [browser_treeupdate_imagemap.js]
-skip-if = (os == 'mac' && debug && e10s) # Bug 1318569
+skip-if = e10s # Bug 1318569
 [browser_treeupdate_list.js]
 [browser_treeupdate_list_editabledoc.js]
 [browser_treeupdate_listener.js]
 [browser_treeupdate_optgroup.js]
 [browser_treeupdate_removal.js]
 [browser_treeupdate_table.js]
 [browser_treeupdate_textleaf.js]
 [browser_treeupdate_visibility.js]
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1024,18 +1024,22 @@ pref("security.sandbox.content.level", 2
 // when a temporary writable file is required in a level 1 sandbox.
 pref("security.sandbox.content.tempDirSuffix", "");
 #endif
 #endif
 
 #if defined(MOZ_SANDBOX)
 // This pref determines if messages relevant to sandbox violations are
 // logged.
+#if defined(XP_WIN)
+pref("security.sandbox.logging.enabled", false);
+#else
 pref("security.sandbox.logging.enabled", true);
 #endif
+#endif
 
 // This pref governs whether we attempt to work around problems caused by
 // plugins using OS calls to manipulate the cursor while running out-of-
 // process.  These workarounds all involve intercepting (hooking) certain
 // OS calls in the plugin process, then arranging to make certain OS calls
 // in the browser process.  Eventually plugins will be required to use the
 // NPAPI to manipulate the cursor, and these workarounds will be removed.
 // See bug 621117.
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,3 +1,3 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 1.6.467
+Current extension version is: 1.7.227
--- a/browser/extensions/pdfjs/content/PdfJsNetwork.jsm
+++ b/browser/extensions/pdfjs/content/PdfJsNetwork.jsm
@@ -16,75 +16,75 @@
 
 'use strict';
 
 Components.utils.import('resource://gre/modules/Services.jsm');
 
 var EXPORTED_SYMBOLS = ['NetworkManager'];
 
 function log(aMsg) {
-  var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
+  var msg = 'PdfJsNetwork.jsm: ' + (aMsg.join ? aMsg.join('') : aMsg);
   Services.console.logStringMessage(msg);
 }
 
 var NetworkManager = (function NetworkManagerClosure() {
 
-  var OK_RESPONSE = 200;
-  var PARTIAL_CONTENT_RESPONSE = 206;
-
-  function NetworkManager(url, args) {
-    this.url = url;
-    args = args || {};
-    this.isHttp = /^https?:/i.test(url);
-    this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
-    this.withCredentials = args.withCredentials || false;
-    this.getXhr = args.getXhr ||
-      function NetworkManager_getXhr() {
-        return new XMLHttpRequest();
-      };
-
-    this.currXhrId = 0;
-    this.pendingRequests = Object.create(null);
-    this.loadedRequests = Object.create(null);
-  }
+  const OK_RESPONSE = 200;
+  const PARTIAL_CONTENT_RESPONSE = 206;
 
   function getArrayBuffer(xhr) {
     var data = xhr.response;
     if (typeof data !== 'string') {
       return data;
     }
     var length = data.length;
     var array = new Uint8Array(length);
     for (var i = 0; i < length; i++) {
       array[i] = data.charCodeAt(i) & 0xFF;
     }
     return array.buffer;
   }
 
-  NetworkManager.prototype = {
-    requestRange: function NetworkManager_requestRange(begin, end, listeners) {
+  class NetworkManagerClass {
+    constructor(url, args) {
+      this.url = url;
+      args = args || {};
+      this.isHttp = /^https?:/i.test(url);
+      this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
+      this.withCredentials = args.withCredentials || false;
+      this.getXhr = args.getXhr ||
+        function NetworkManager_getXhr() {
+          return new XMLHttpRequest();
+        };
+
+      this.currXhrId = 0;
+      this.pendingRequests = Object.create(null);
+      this.loadedRequests = Object.create(null);
+    }
+
+    requestRange(begin, end, listeners) {
       var args = {
-        begin: begin,
-        end: end
+        begin,
+        end,
       };
       for (var prop in listeners) {
         args[prop] = listeners[prop];
       }
       return this.request(args);
-    },
+    }
 
-    requestFull: function NetworkManager_requestFull(listeners) {
+    requestFull(listeners) {
       return this.request(listeners);
-    },
+    }
 
-    request: function NetworkManager_request(args) {
+    request(args) {
       var xhr = this.getXhr();
       var xhrId = this.currXhrId++;
       var pendingRequest = this.pendingRequests[xhrId] = {
-        xhr: xhr
+        xhr,
       };
 
       xhr.open('GET', this.url);
       xhr.withCredentials = this.withCredentials;
       for (var property in this.httpHeaders) {
         var value = this.httpHeaders[property];
         if (typeof value === 'undefined') {
           continue;
@@ -119,37 +119,37 @@ var NetworkManager = (function NetworkMa
       pendingRequest.onHeadersReceived = args.onHeadersReceived;
       pendingRequest.onDone = args.onDone;
       pendingRequest.onError = args.onError;
       pendingRequest.onProgress = args.onProgress;
 
       xhr.send(null);
 
       return xhrId;
-    },
+    }
 
-    onProgress: function NetworkManager_onProgress(xhrId, evt) {
+    onProgress(xhrId, evt) {
       var pendingRequest = this.pendingRequests[xhrId];
       if (!pendingRequest) {
         // Maybe abortRequest was called...
         return;
       }
 
       if (pendingRequest.mozChunked) {
         var chunk = getArrayBuffer(pendingRequest.xhr);
         pendingRequest.onProgressiveData(chunk);
       }
 
       var onProgress = pendingRequest.onProgress;
       if (onProgress) {
         onProgress(evt);
       }
-    },
+    }
 
-    onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
+    onStateChange(xhrId, evt) {
       var pendingRequest = this.pendingRequests[xhrId];
       if (!pendingRequest) {
         // Maybe abortRequest was called...
         return;
       }
 
       var xhr = pendingRequest.xhr;
       if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
@@ -196,62 +196,62 @@ var NetworkManager = (function NetworkMa
       this.loadedRequests[xhrId] = true;
 
       var chunk = getArrayBuffer(xhr);
       if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
         var rangeHeader = xhr.getResponseHeader('Content-Range');
         var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
         var begin = parseInt(matches[1], 10);
         pendingRequest.onDone({
-          begin: begin,
-          chunk: chunk
+          begin,
+          chunk,
         });
       } else if (pendingRequest.onProgressiveData) {
         pendingRequest.onDone(null);
       } else if (chunk) {
         pendingRequest.onDone({
           begin: 0,
-          chunk: chunk
+          chunk,
         });
       } else if (pendingRequest.onError) {
         pendingRequest.onError(xhr.status);
       }
-    },
+    }
 
-    hasPendingRequests: function NetworkManager_hasPendingRequests() {
+    hasPendingRequests() {
       for (var xhrId in this.pendingRequests) {
         return true;
       }
       return false;
-    },
+    }
 
-    getRequestXhr: function NetworkManager_getXhr(xhrId) {
+    getRequestXhr(xhrId) {
       return this.pendingRequests[xhrId].xhr;
-    },
+    }
 
-    isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
+    isStreamingRequest(xhrId) {
       return !!(this.pendingRequests[xhrId].onProgressiveData);
-    },
+    }
 
-    isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
+    isPendingRequest(xhrId) {
       return xhrId in this.pendingRequests;
-    },
+    }
 
-    isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
+    isLoadedRequest(xhrId) {
       return xhrId in this.loadedRequests;
-    },
+    }
 
-    abortAllRequests: function NetworkManager_abortAllRequests() {
+    abortAllRequests() {
       for (var xhrId in this.pendingRequests) {
         this.abortRequest(xhrId | 0);
       }
-    },
+    }
 
-    abortRequest: function NetworkManager_abortRequest(xhrId) {
+    abortRequest(xhrId) {
       var xhr = this.pendingRequests[xhrId].xhr;
       delete this.pendingRequests[xhrId];
       xhr.abort();
     }
-  };
+  }
 
-  return NetworkManager;
+  return NetworkManagerClass;
 })();
 
--- a/browser/extensions/pdfjs/content/PdfJsTelemetry.jsm
+++ b/browser/extensions/pdfjs/content/PdfJsTelemetry.jsm
@@ -18,53 +18,53 @@
 'use strict';
 
 this.EXPORTED_SYMBOLS = ['PdfJsTelemetry'];
 
 const Cu = Components.utils;
 Cu.import('resource://gre/modules/Services.jsm');
 
 this.PdfJsTelemetry = {
-  onViewerIsUsed: function () {
+  onViewerIsUsed() {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_USED');
     histogram.add(true);
   },
-  onFallback: function () {
+  onFallback() {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FALLBACK_SHOWN');
     histogram.add(true);
   },
-  onDocumentSize: function (size) {
+  onDocumentSize(size) {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_SIZE_KB');
     histogram.add(size / 1024);
   },
-  onDocumentVersion: function (versionId) {
+  onDocumentVersion(versionId) {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_VERSION');
     histogram.add(versionId);
   },
-  onDocumentGenerator: function (generatorId) {
+  onDocumentGenerator(generatorId) {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_GENERATOR');
     histogram.add(generatorId);
   },
-  onEmbed: function (isObject) {
+  onEmbed(isObject) {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_EMBED');
     histogram.add(isObject);
   },
-  onFontType: function (fontTypeId) {
+  onFontType(fontTypeId) {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FONT_TYPES');
     histogram.add(fontTypeId);
   },
-  onForm: function (isAcroform) {
+  onForm(isAcroform) {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FORM');
     histogram.add(isAcroform);
   },
-  onPrint: function () {
+  onPrint() {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_PRINT');
     histogram.add(true);
   },
-  onStreamType: function (streamTypeId) {
+  onStreamType(streamTypeId) {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_STREAM_TYPES');
     histogram.add(streamTypeId);
   },
-  onTimeToView: function (ms) {
+  onTimeToView(ms) {
     let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_TIME_TO_VIEW_MS');
     histogram.add(ms);
   }
 };
--- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
+++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm
@@ -185,49 +185,52 @@ PdfDataListener.prototype = {
     }
   },
   error: function PdfDataListener_error(errorCode) {
     this.errorCode = errorCode;
     if (this.oncompleteCallback) {
       this.oncompleteCallback(null, errorCode);
     }
   },
-  onprogress: function() {},
+  onprogress() {},
   get oncomplete() {
     return this.oncompleteCallback;
   },
   set oncomplete(value) {
     this.oncompleteCallback = value;
     if (this.isDataReady) {
       value(this.readData());
     }
     if (this.errorCode) {
       value(null, this.errorCode);
     }
   }
 };
 
-// All the priviledged actions.
-function ChromeActions(domWindow, contentDispositionFilename) {
-  this.domWindow = domWindow;
-  this.contentDispositionFilename = contentDispositionFilename;
-  this.telemetryState = {
-    documentInfo: false,
-    firstPageInfo: false,
-    streamTypesUsed: [],
-    fontTypesUsed: [],
-    startAt: Date.now()
-  };
-}
+/**
+ * All the privileged actions.
+ */
+class ChromeActions {
+  constructor(domWindow, contentDispositionFilename) {
+    this.domWindow = domWindow;
+    this.contentDispositionFilename = contentDispositionFilename;
+    this.telemetryState = {
+      documentInfo: false,
+      firstPageInfo: false,
+      streamTypesUsed: [],
+      fontTypesUsed: [],
+      startAt: Date.now()
+    };
+  }
 
-ChromeActions.prototype = {
-  isInPrivateBrowsing: function() {
+  isInPrivateBrowsing() {
     return PrivateBrowsingUtils.isContentWindowPrivate(this.domWindow);
-  },
-  download: function(data, sendResponse) {
+  }
+
+  download(data, sendResponse) {
     var self = this;
     var originalUrl = data.originalUrl;
     var blobUrl = data.blobUrl || originalUrl;
     // The data may not be downloaded so we need just retry getting the pdf with
     // the original url.
     var originalUri = NetUtil.newURI(originalUrl);
     var filename = data.filename;
     if (typeof filename !== 'string' ||
@@ -274,92 +277,98 @@ ChromeActions.prototype = {
       channel.contentStream = aInputStream;
       if ('nsIPrivateBrowsingChannel' in Ci &&
           channel instanceof Ci.nsIPrivateBrowsingChannel) {
         channel.setPrivate(docIsPrivate);
       }
 
       var listener = {
         extListener: null,
-        onStartRequest: function(aRequest, aContext) {
+        onStartRequest(aRequest, aContext) {
           var loadContext = self.domWindow
                                 .QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsIWebNavigation)
                                 .QueryInterface(Ci.nsILoadContext);
           this.extListener = extHelperAppSvc.doContent(
             (data.isAttachment ? 'application/octet-stream' :
                                  'application/pdf'),
             aRequest, loadContext, false);
           this.extListener.onStartRequest(aRequest, aContext);
         },
-        onStopRequest: function(aRequest, aContext, aStatusCode) {
+        onStopRequest(aRequest, aContext, aStatusCode) {
           if (this.extListener) {
             this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
           }
           // Notify the content code we're done downloading.
           if (sendResponse) {
             sendResponse(false);
           }
         },
-        onDataAvailable: function(aRequest, aContext, aInputStream, aOffset,
-                                  aCount) {
-          this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
+        onDataAvailable(aRequest, aContext, aDataInputStream, aOffset, aCount) {
+          this.extListener.onDataAvailable(aRequest, aContext, aDataInputStream,
                                            aOffset, aCount);
         }
       };
 
       channel.asyncOpen2(listener);
     });
-  },
-  getLocale: function() {
+  }
+
+  getLocale() {
     return getStringPref('general.useragent.locale', 'en-US');
-  },
-  getStrings: function(data) {
+  }
+
+  getStrings(data) {
     try {
       // Lazy initialization of localizedStrings
       if (!('localizedStrings' in this)) {
         this.localizedStrings = getLocalizedStrings('viewer.properties');
       }
       var result = this.localizedStrings[data];
       return JSON.stringify(result || null);
     } catch (e) {
       log('Unable to retrieve localized strings: ' + e);
       return 'null';
     }
-  },
-  supportsIntegratedFind: function() {
+  }
+
+  supportsIntegratedFind() {
     // Integrated find is only supported when we're not in a frame
     if (this.domWindow.frameElement !== null) {
       return false;
     }
 
     // ... and we are in a child process
     if (PdfjsContentUtils.isRemote) {
       return true;
     }
 
     // ... or when the new find events code exists.
     var findBar = getFindBar(this.domWindow);
     return !!findBar && ('updateControlState' in findBar);
-  },
-  supportsDocumentFonts: function() {
+  }
+
+  supportsDocumentFonts() {
     var prefBrowser = getIntPref('browser.display.use_document_fonts', 1);
     var prefGfx = getBoolPref('gfx.downloadable_fonts.enabled', true);
     return (!!prefBrowser && prefGfx);
-  },
-  supportsDocumentColors: function() {
+  }
+
+  supportsDocumentColors() {
     return getIntPref('browser.display.document_color_use', 0) !== 2;
-  },
-  supportedMouseWheelZoomModifierKeys: function() {
+  }
+
+  supportedMouseWheelZoomModifierKeys() {
     return {
       ctrlKey: getIntPref('mousewheel.with_control.action', 3) === 3,
       metaKey: getIntPref('mousewheel.with_meta.action', 1) === 3,
     };
-  },
-  reportTelemetry: function (data) {
+  }
+
+  reportTelemetry(data) {
     var probeInfo = JSON.parse(data);
     switch (probeInfo.type) {
       case 'documentInfo':
         if (!this.telemetryState.documentInfo) {
           PdfJsTelemetry.onDocumentVersion(probeInfo.version | 0);
           PdfJsTelemetry.onDocumentGenerator(probeInfo.generator | 0);
           if (probeInfo.formType) {
             PdfJsTelemetry.onForm(probeInfo.formType === 'acroform');
@@ -404,22 +413,25 @@ ChromeActions.prototype = {
             }
           }
         }
         break;
       case 'print':
         PdfJsTelemetry.onPrint();
         break;
     }
-  },
-  fallback: function(args, sendResponse) {
+  }
+
+  /**
+   * @param {Object} args - Object with `featureId` and `url` properties.
+   * @param {function} sendResponse - Callback function.
+   */
+  fallback(args, sendResponse) {
     var featureId = args.featureId;
-    var url = args.url;
 
-    var self = this;
     var domWindow = this.domWindow;
     var strings = getLocalizedStrings('chrome.properties');
     var message;
     if (featureId === 'forms') {
       message = getLocalizedString(strings, 'unsupported_feature_forms');
     } else {
       message = getLocalizedString(strings, 'unsupported_feature');
     }
@@ -436,18 +448,19 @@ ChromeActions.prototype = {
     winmm.addMessageListener('PDFJS:Child:fallbackDownload',
       function fallbackDownload(msg) {
         let data = msg.data;
         sendResponse(data.download);
 
         winmm.removeMessageListener('PDFJS:Child:fallbackDownload',
                                     fallbackDownload);
       });
-  },
-  updateFindControlState: function(data) {
+  }
+
+  updateFindControlState(data) {
     if (!this.supportsIntegratedFind()) {
       return;
     }
     // Verify what we're sending to the findbar.
     var result = data.result;
     var findPrevious = data.findPrevious;
     var findPreviousType = typeof findPrevious;
     if ((typeof result !== 'number' || result < 0 || result > 3) ||
@@ -456,18 +469,19 @@ ChromeActions.prototype = {
     }
 
     var winmm = this.domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIDocShell)
                               .QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIContentFrameMessageManager);
 
     winmm.sendAsyncMessage('PDFJS:Parent:updateControlState', data);
-  },
-  setPreferences: function(prefs, sendResponse) {
+  }
+
+  setPreferences(prefs, sendResponse) {
     var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
     var numberOfPrefs = 0;
     var prefValue, prefName;
     for (var key in prefs) {
       if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
         log('setPreferences - Exceeded the maximum number of preferences ' +
             'that is allowed to be set at once.');
         break;
@@ -491,18 +505,19 @@ ChromeActions.prototype = {
             PdfjsContentUtils.setStringPref(prefName, prefValue);
           }
           break;
       }
     }
     if (sendResponse) {
       sendResponse(true);
     }
-  },
-  getPreferences: function(prefs, sendResponse) {
+  }
+
+  getPreferences(prefs, sendResponse) {
     var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
     var currentPrefs = {}, numberOfPrefs = 0;
     var prefValue, prefName;
     for (var key in prefs) {
       if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
         log('getPreferences - Exceeded the maximum number of preferences ' +
             'that is allowed to be fetched at once.');
         break;
@@ -524,39 +539,38 @@ ChromeActions.prototype = {
       }
     }
     if (sendResponse) {
       sendResponse(JSON.stringify(currentPrefs));
     } else {
       return JSON.stringify(currentPrefs);
     }
   }
-};
+}
 
-var RangedChromeActions = (function RangedChromeActionsClosure() {
-  /**
-   * This is for range requests
-   */
-  function RangedChromeActions(
-              domWindow, contentDispositionFilename, originalRequest,
+/**
+ * This is for range requests.
+ */
+class RangedChromeActions extends ChromeActions {
+  constructor(domWindow, contentDispositionFilename, originalRequest,
               rangeEnabled, streamingEnabled, dataListener) {
 
-    ChromeActions.call(this, domWindow, contentDispositionFilename);
+    super(domWindow, contentDispositionFilename);
     this.dataListener = dataListener;
     this.originalRequest = originalRequest;
     this.rangeEnabled = rangeEnabled;
     this.streamingEnabled = streamingEnabled;
 
     this.pdfUrl = originalRequest.URI.spec;
     this.contentLength = originalRequest.contentLength;
 
     // Pass all the headers from the original request through
     var httpHeaderVisitor = {
       headers: {},
-      visitHeader: function(aHeader, aValue) {
+      visitHeader(aHeader, aValue) {
         if (aHeader === 'Range') {
           // When loading the PDF from cache, firefox seems to set the Range
           // request header to fetch only the unfetched portions of the file
           // (e.g. 'Range: bytes=1024-'). However, we want to set this header
           // manually to fetch the PDF in chunks.
           return;
         }
         this.headers[aHeader] = aValue;
@@ -582,249 +596,237 @@ var RangedChromeActions = (function Rang
           '@mozilla.org/xmlextras/xmlhttprequest;1');
       var xhr = new XMLHttpRequest();
       xhr.addEventListener('readystatechange', xhr_onreadystatechange);
       return xhr;
     };
 
     this.networkManager = new NetworkManager(this.pdfUrl, {
       httpHeaders: httpHeaderVisitor.headers,
-      getXhr: getXhr
+      getXhr,
     });
 
     // If we are in range request mode, this means we manually issued xhr
     // requests, which we need to abort when we leave the page
     domWindow.addEventListener('unload', function unload(e) {
       domWindow.removeEventListener(e.type, unload);
       self.abortLoading();
     });
   }
 
-  RangedChromeActions.prototype = Object.create(ChromeActions.prototype);
-  var proto = RangedChromeActions.prototype;
-  proto.constructor = RangedChromeActions;
-
-  proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
-    var self = this;
+  initPassiveLoading() {
     var data;
     if (!this.streamingEnabled) {
       this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
       this.originalRequest = null;
       data = this.dataListener.readData();
       this.dataListener = null;
     } else {
       data = this.dataListener.readData();
 
-      this.dataListener.onprogress = function (loaded, total) {
-        self.domWindow.postMessage({
+      this.dataListener.onprogress = (loaded, total) => {
+        this.domWindow.postMessage({
           pdfjsLoadAction: 'progressiveRead',
-          loaded: loaded,
-          total: total,
-          chunk: self.dataListener.readData()
+          loaded,
+          total,
+          chunk: this.dataListener.readData(),
         }, '*');
       };
-      this.dataListener.oncomplete = function () {
-        self.dataListener = null;
+      this.dataListener.oncomplete = () => {
+        this.dataListener = null;
       };
     }
 
     this.domWindow.postMessage({
       pdfjsLoadAction: 'supportsRangedLoading',
       rangeEnabled: this.rangeEnabled,
       streamingEnabled: this.streamingEnabled,
       pdfUrl: this.pdfUrl,
       length: this.contentLength,
-      data: data
+      data,
     }, '*');
 
     return true;
-  };
+  }
 
-  proto.requestDataRange = function RangedChromeActions_requestDataRange(args) {
+  requestDataRange(args) {
     if (!this.rangeEnabled) {
       return;
     }
 
     var begin = args.begin;
     var end = args.end;
     var domWindow = this.domWindow;
     // TODO(mack): Support error handler. We're not currently not handling
     // errors from chrome code for non-range requests, so this doesn't
     // seem high-pri
     this.networkManager.requestRange(begin, end, {
-      onDone: function RangedChromeActions_onDone(args) {
+      onDone: function RangedChromeActions_onDone(aArgs) {
         domWindow.postMessage({
           pdfjsLoadAction: 'range',
-          begin: args.begin,
-          chunk: args.chunk
+          begin: aArgs.begin,
+          chunk: aArgs.chunk,
         }, '*');
       },
       onProgress: function RangedChromeActions_onProgress(evt) {
         domWindow.postMessage({
           pdfjsLoadAction: 'rangeProgress',
           loaded: evt.loaded,
         }, '*');
       }
     });
-  };
+  }
 
-  proto.abortLoading = function RangedChromeActions_abortLoading() {
+  abortLoading() {
     this.networkManager.abortAllRequests();
     if (this.originalRequest) {
       this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
       this.originalRequest = null;
     }
     this.dataListener = null;
-  };
-
-  return RangedChromeActions;
-})();
-
-var StandardChromeActions = (function StandardChromeActionsClosure() {
+  }
+}
 
-  /**
-   * This is for a single network stream
-   */
-  function StandardChromeActions(domWindow, contentDispositionFilename,
-                                 originalRequest, dataListener) {
-
-    ChromeActions.call(this, domWindow, contentDispositionFilename);
+/**
+ * This is for a single network stream.
+ */
+class StandardChromeActions extends ChromeActions {
+  constructor(domWindow, contentDispositionFilename, originalRequest,
+              dataListener) {
+    super(domWindow, contentDispositionFilename);
     this.originalRequest = originalRequest;
     this.dataListener = dataListener;
   }
 
-  StandardChromeActions.prototype = Object.create(ChromeActions.prototype);
-  var proto = StandardChromeActions.prototype;
-  proto.constructor = StandardChromeActions;
-
-  proto.initPassiveLoading =
-      function StandardChromeActions_initPassiveLoading() {
-
+  initPassiveLoading() {
     if (!this.dataListener) {
       return false;
     }
 
-    var self = this;
-
-    this.dataListener.onprogress = function ChromeActions_dataListenerProgress(
-                                      loaded, total) {
-      self.domWindow.postMessage({
+    this.dataListener.onprogress = (loaded, total) => {
+      this.domWindow.postMessage({
         pdfjsLoadAction: 'progress',
-        loaded: loaded,
-        total: total
+        loaded,
+        total,
       }, '*');
     };
 
-    this.dataListener.oncomplete =
-        function StandardChromeActions_dataListenerComplete(data, errorCode) {
-      self.domWindow.postMessage({
+    this.dataListener.oncomplete = (data, errorCode) => {
+      this.domWindow.postMessage({
         pdfjsLoadAction: 'complete',
-        data: data,
-        errorCode: errorCode
+        data,
+        errorCode,
       }, '*');
 
-      self.dataListener = null;
-      self.originalRequest = null;
+      this.dataListener = null;
+      this.originalRequest = null;
     };
 
     return true;
-  };
+  }
 
-  proto.abortLoading = function StandardChromeActions_abortLoading() {
+  abortLoading() {
     if (this.originalRequest) {
       this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
       this.originalRequest = null;
     }
     this.dataListener = null;
-  };
-
-  return StandardChromeActions;
-})();
-
-// Event listener to trigger chrome privileged code.
-function RequestListener(actions) {
-  this.actions = actions;
-}
-// Receive an event and synchronously or asynchronously responds.
-RequestListener.prototype.receive = function(event) {
-  var message = event.target;
-  var doc = message.ownerDocument;
-  var action = event.detail.action;
-  var data = event.detail.data;
-  var sync = event.detail.sync;
-  var actions = this.actions;
-  if (!(action in actions)) {
-    log('Unknown action: ' + action);
-    return;
   }
-  var response;
-  if (sync) {
-    response = actions[action].call(this.actions, data);
-    event.detail.response = Cu.cloneInto(response, doc.defaultView);
-  } else {
-    if (!event.detail.responseExpected) {
-      doc.documentElement.removeChild(message);
-      response = null;
-    } else {
-      response = function sendResponse(response) {
-        try {
-          var listener = doc.createEvent('CustomEvent');
-          let detail = Cu.cloneInto({ response: response }, doc.defaultView);
-          listener.initCustomEvent('pdf.js.response', true, false, detail);
-          return message.dispatchEvent(listener);
-        } catch (e) {
-          // doc is no longer accessible because the requestor is already
-          // gone. unloaded content cannot receive the response anyway.
-          return false;
-        }
-      };
-    }
-    actions[action].call(this.actions, data, response);
-  }
-};
-
-// Forwards events from the eventElement to the contentWindow only if the
-// content window matches the currently selected browser window.
-function FindEventManager(contentWindow) {
-  this.contentWindow = contentWindow;
-  this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIDocShell)
-                            .QueryInterface(Ci.nsIInterfaceRequestor)
-                            .getInterface(Ci.nsIContentFrameMessageManager);
 }
 
-FindEventManager.prototype.bind = function() {
-  var unload = function(e) {
-    this.unbind();
-    this.contentWindow.removeEventListener(e.type, unload);
-  }.bind(this);
-  this.contentWindow.addEventListener('unload', unload);
-
-  // We cannot directly attach listeners to for the find events
-  // since the FindBar is in the parent process. Instead we're
-  // asking the PdfjsChromeUtils to do it for us and forward
-  // all the find events to us.
-  this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener');
-  this.winmm.addMessageListener('PDFJS:Child:handleEvent', this);
-};
+/**
+ * Event listener to trigger chrome privileged code.
+ */
+class RequestListener {
+  constructor(actions) {
+    this.actions = actions;
+  }
 
-FindEventManager.prototype.receiveMessage = function(msg) {
-  var detail = msg.data.detail;
-  var type = msg.data.type;
-  var contentWindow = this.contentWindow;
+  // Receive an event and synchronously or asynchronously responds.
+  receive(event) {
+    var message = event.target;
+    var doc = message.ownerDocument;
+    var action = event.detail.action;
+    var data = event.detail.data;
+    var sync = event.detail.sync;
+    var actions = this.actions;
+    if (!(action in actions)) {
+      log('Unknown action: ' + action);
+      return;
+    }
+    var response;
+    if (sync) {
+      response = actions[action].call(this.actions, data);
+      event.detail.response = Cu.cloneInto(response, doc.defaultView);
+    } else {
+      if (!event.detail.responseExpected) {
+        doc.documentElement.removeChild(message);
+        response = null;
+      } else {
+        response = function sendResponse(aResponse) {
+          try {
+            var listener = doc.createEvent('CustomEvent');
+            let detail = Cu.cloneInto({ response: aResponse }, doc.defaultView);
+            listener.initCustomEvent('pdf.js.response', true, false, detail);
+            return message.dispatchEvent(listener);
+          } catch (e) {
+            // doc is no longer accessible because the requestor is already
+            // gone. unloaded content cannot receive the response anyway.
+            return false;
+          }
+        };
+      }
+      actions[action].call(this.actions, data, response);
+    }
+  }
+}
 
-  detail = Cu.cloneInto(detail, contentWindow);
-  var forward = contentWindow.document.createEvent('CustomEvent');
-  forward.initCustomEvent(type, true, true, detail);
-  contentWindow.dispatchEvent(forward);
-};
+/**
+ * Forwards events from the eventElement to the contentWindow only if the
+ * content window matches the currently selected browser window.
+ */
+class FindEventManager {
+  constructor(contentWindow) {
+    this.contentWindow = contentWindow;
+    this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIDocShell)
+                              .QueryInterface(Ci.nsIInterfaceRequestor)
+                              .getInterface(Ci.nsIContentFrameMessageManager);
+  }
+
+  bind() {
+    var unload = function(e) {
+      this.unbind();
+      this.contentWindow.removeEventListener(e.type, unload);
+    }.bind(this);
+    this.contentWindow.addEventListener('unload', unload);
 
-FindEventManager.prototype.unbind = function() {
-  this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener');
-};
+    // We cannot directly attach listeners to for the find events
+    // since the FindBar is in the parent process. Instead we're
+    // asking the PdfjsChromeUtils to do it for us and forward
+    // all the find events to us.
+    this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener');
+    this.winmm.addMessageListener('PDFJS:Child:handleEvent', this);
+  }
+
+  receiveMessage(msg) {
+    var detail = msg.data.detail;
+    var type = msg.data.type;
+    var contentWindow = this.contentWindow;
+
+    detail = Cu.cloneInto(detail, contentWindow);
+    var forward = contentWindow.document.createEvent('CustomEvent');
+    forward.initCustomEvent(type, true, true, detail);
+    contentWindow.dispatchEvent(forward);
+  }
+
+  unbind() {
+    this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener');
+  }
+}
 
 function PdfStreamConverter() {
 }
 
 PdfStreamConverter.prototype = {
 
   // properties required for XPCOM registration:
   classID: Components.ID('{d0c5195d-e798-49d4-b1d3-9324328b2291}'),
@@ -853,40 +855,40 @@ PdfStreamConverter.prototype = {
    *      3.1. Read the stream as it's loaded in onDataAvailable to send
    *           to the viewer
    *
    * The convert function just returns the stream, it's just the synchronous
    * version of asyncConvertData.
    */
 
   // nsIStreamConverter::convert
-  convert: function(aFromStream, aFromType, aToType, aCtxt) {
+  convert(aFromStream, aFromType, aToType, aCtxt) {
     throw Cr.NS_ERROR_NOT_IMPLEMENTED;
   },
 
   // nsIStreamConverter::asyncConvertData
-  asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
+  asyncConvertData(aFromType, aToType, aListener, aCtxt) {
     // Store the listener passed to us
     this.listener = aListener;
   },
 
   // nsIStreamListener::onDataAvailable
-  onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
+  onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) {
     if (!this.dataListener) {
       return;
     }
 
     var binaryStream = this.binaryStream;
     binaryStream.setInputStream(aInputStream);
     var chunk = binaryStream.readByteArray(aCount);
     this.dataListener.append(chunk);
   },
 
   // nsIRequestObserver::onStartRequest
-  onStartRequest: function(aRequest, aContext) {
+  onStartRequest(aRequest, aContext) {
     // Setup the request so we can use it below.
     var isHttpRequest = false;
     try {
       aRequest.QueryInterface(Ci.nsIHttpChannel);
       isHttpRequest = true;
     } catch (e) {}
 
     var rangeRequest = false;
@@ -955,24 +957,24 @@ PdfStreamConverter.prototype = {
 
     var listener = this.listener;
     var dataListener = this.dataListener;
     // Proxy all the request observer calls, when it gets to onStopRequest
     // we can get the dom window.  We also intentionally pass on the original
     // request(aRequest) below so we don't overwrite the original channel and
     // trigger an assertion.
     var proxy = {
-      onStartRequest: function(request, context) {
+      onStartRequest(request, context) {
         listener.onStartRequest(aRequest, aContext);
       },
-      onDataAvailable: function(request, context, inputStream, offset, count) {
+      onDataAvailable(request, context, inputStream, offset, count) {
         listener.onDataAvailable(aRequest, aContext, inputStream,
                                  offset, count);
       },
-      onStopRequest: function(request, context, statusCode) {
+      onStopRequest(request, context, statusCode) {
         // We get the DOM window here instead of before the request since it
         // may have changed during a redirect.
         var domWindow = getDOMWindow(channel);
         var actions;
         if (rangeRequest || streamRequest) {
           actions = new RangedChromeActions(
             domWindow, contentDispositionFilename, aRequest,
             rangeRequest, streamRequest, dataListener);
@@ -1012,17 +1014,17 @@ PdfStreamConverter.prototype = {
     var resourcePrincipal =
       ssm.createCodebasePrincipal(uri, aRequest.loadInfo.originAttributes);
     aRequest.owner = resourcePrincipal;
 
     channel.asyncOpen2(proxy);
   },
 
   // nsIRequestObserver::onStopRequest
-  onStopRequest: function(aRequest, aContext, aStatusCode) {
+  onStopRequest(aRequest, aContext, aStatusCode) {
     if (!this.dataListener) {
       // Do nothing
       return;
     }
 
     if (Components.isSuccessCode(aStatusCode)) {
       this.dataListener.finish();
     } else {
--- a/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm
+++ b/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm
@@ -62,17 +62,17 @@ var PdfjsChromeUtils = {
   _allowedPrefNames: Object.keys(DEFAULT_PREFERENCES),
   _ppmm: null,
   _mmg: null,
 
   /*
    * Public API
    */
 
-  init: function () {
+  init() {
     this._browsers = new WeakSet();
     if (!this._ppmm) {
       // global parent process message manager (PPMM)
       this._ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1'].
         getService(Ci.nsIMessageBroadcaster);
       this._ppmm.addMessageListener('PDFJS:Parent:clearUserPref', this);
       this._ppmm.addMessageListener('PDFJS:Parent:setIntPref', this);
       this._ppmm.addMessageListener('PDFJS:Parent:setBoolPref', this);
@@ -89,17 +89,17 @@ var PdfjsChromeUtils = {
       this._mmg.addMessageListener('PDFJS:Parent:removeEventListener', this);
       this._mmg.addMessageListener('PDFJS:Parent:updateControlState', this);
 
       // observer to handle shutdown
       Services.obs.addObserver(this, 'quit-application', false);
     }
   },
 
-  uninit: function () {
+  uninit() {
     if (this._ppmm) {
       this._ppmm.removeMessageListener('PDFJS:Parent:clearUserPref', this);
       this._ppmm.removeMessageListener('PDFJS:Parent:setIntPref', this);
       this._ppmm.removeMessageListener('PDFJS:Parent:setBoolPref', this);
       this._ppmm.removeMessageListener('PDFJS:Parent:setCharPref', this);
       this._ppmm.removeMessageListener('PDFJS:Parent:setStringPref', this);
       this._ppmm.removeMessageListener('PDFJS:Parent:isDefaultHandlerApp',
                                        this);
@@ -118,39 +118,39 @@ var PdfjsChromeUtils = {
   },
 
   /*
    * Called by the main module when preference changes are picked up
    * in the parent process. Observers don't propagate so we need to
    * instruct the child to refresh its configuration and (possibly)
    * the module's registration.
    */
-  notifyChildOfSettingsChange: function () {
+  notifyChildOfSettingsChange() {
     if (Services.appinfo.processType ===
         Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) {
       // XXX kinda bad, we want to get the parent process mm associated
       // with the content process. _ppmm is currently the global process
       // manager, which means this is going to fire to every child process
       // we have open. Unfortunately I can't find a way to get at that
       // process specific mm from js.
       this._ppmm.broadcastAsyncMessage('PDFJS:Child:refreshSettings', {});
     }
   },
 
   /*
    * Events
    */
 
-  observe: function(aSubject, aTopic, aData) {
+  observe(aSubject, aTopic, aData) {
     if (aTopic === 'quit-application') {
       this.uninit();
     }
   },
 
-  receiveMessage: function (aMsg) {
+  receiveMessage(aMsg) {
     switch (aMsg.name) {
       case 'PDFJS:Parent:clearUserPref':
         this._clearUserPref(aMsg.data.name);
         break;
       case 'PDFJS:Parent:setIntPref':
         this._setIntPref(aMsg.data.name, aMsg.data.value);
         break;
       case 'PDFJS:Parent:setBoolPref':
@@ -177,30 +177,30 @@ var PdfjsChromeUtils = {
         return this._removeEventListener(aMsg);
     }
   },
 
   /*
    * Internal
    */
 
-  _findbarFromMessage: function(aMsg) {
+  _findbarFromMessage(aMsg) {
     let browser = aMsg.target;
     let tabbrowser = browser.getTabBrowser();
     let tab = tabbrowser.getTabForBrowser(browser);
     return tabbrowser.getFindBar(tab);
   },
 
-  _updateControlState: function (aMsg) {
+  _updateControlState(aMsg) {
     let data = aMsg.data;
     this._findbarFromMessage(aMsg)
         .updateControlState(data.result, data.findPrevious);
   },
 
-  handleEvent: function(aEvent) {
+  handleEvent(aEvent) {
     // To avoid forwarding the message as a CPOW, create a structured cloneable
     // version of the event for both performance, and ease of usage, reasons.
     let type = aEvent.type;
     let detail = {
       query: aEvent.detail.query,
       caseSensitive: aEvent.detail.caseSensitive,
       highlightAll: aEvent.detail.highlightAll,
       findPrevious: aEvent.detail.findPrevious
@@ -208,27 +208,26 @@ var PdfjsChromeUtils = {
 
     let browser = aEvent.currentTarget.browser;
     if (!this._browsers.has(browser)) {
       throw new Error('FindEventManager was not bound ' +
                       'for the current browser.');
     }
     // Only forward the events if the current browser is a registered browser.
     let mm = browser.messageManager;
-    mm.sendAsyncMessage('PDFJS:Child:handleEvent',
-                        { type: type, detail: detail });
+    mm.sendAsyncMessage('PDFJS:Child:handleEvent', { type, detail, });
     aEvent.preventDefault();
   },
 
   _types: ['find',
            'findagain',
            'findhighlightallchange',
            'findcasesensitivitychange'],
 
-  _addEventListener: function (aMsg) {
+  _addEventListener(aMsg) {
     let browser = aMsg.target;
     if (this._browsers.has(browser)) {
       throw new Error('FindEventManager was bound 2nd time ' +
                       'without unbinding it first.');
     }
 
     // Since this jsm is global, we need to store all the browsers
     // we have to forward the messages for.
@@ -237,105 +236,104 @@ var PdfjsChromeUtils = {
     // And we need to start listening to find events.
     for (var i = 0; i < this._types.length; i++) {
       var type = this._types[i];
       this._findbarFromMessage(aMsg)
           .addEventListener(type, this, true);
     }
   },
 
-  _removeEventListener: function (aMsg) {
+  _removeEventListener(aMsg) {
     let browser = aMsg.target;
     if (!this._browsers.has(browser)) {
       throw new Error('FindEventManager was unbound without binding it first.');
     }
 
     this._browsers.delete(browser);
 
     // No reason to listen to find events any longer.
     for (var i = 0; i < this._types.length; i++) {
       var type = this._types[i];
       this._findbarFromMessage(aMsg)
           .removeEventListener(type, this, true);
     }
   },
 
-  _ensurePreferenceAllowed: function (aPrefName) {
+  _ensurePreferenceAllowed(aPrefName) {
     let unPrefixedName = aPrefName.split(PREF_PREFIX + '.');
     if (unPrefixedName[0] !== '' ||
         this._allowedPrefNames.indexOf(unPrefixedName[1]) === -1) {
       let msg = '"' + aPrefName + '" ' +
                 'can\'t be accessed from content. See PdfjsChromeUtils.';
       throw new Error(msg);
     }
   },
 
-  _clearUserPref: function (aPrefName) {
+  _clearUserPref(aPrefName) {
     this._ensurePreferenceAllowed(aPrefName);
     Services.prefs.clearUserPref(aPrefName);
   },
 
-  _setIntPref: function (aPrefName, aPrefValue) {
+  _setIntPref(aPrefName, aPrefValue) {
     this._ensurePreferenceAllowed(aPrefName);
     Services.prefs.setIntPref(aPrefName, aPrefValue);
   },
 
-  _setBoolPref: function (aPrefName, aPrefValue) {
+  _setBoolPref(aPrefName, aPrefValue) {
     this._ensurePreferenceAllowed(aPrefName);
     Services.prefs.setBoolPref(aPrefName, aPrefValue);
   },
 
-  _setCharPref: function (aPrefName, aPrefValue) {
+  _setCharPref(aPrefName, aPrefValue) {
     this._ensurePreferenceAllowed(aPrefName);
     Services.prefs.setCharPref(aPrefName, aPrefValue);
   },
 
-  _setStringPref: function (aPrefName, aPrefValue) {
+  _setStringPref(aPrefName, aPrefValue) {
     this._ensurePreferenceAllowed(aPrefName);
     let str = Cc['@mozilla.org/supports-string;1']
                 .createInstance(Ci.nsISupportsString);
     str.data = aPrefValue;
     Services.prefs.setComplexValue(aPrefName, Ci.nsISupportsString, str);
   },
 
   /*
    * Svc.mime doesn't have profile information in the child, so
    * we bounce this pdfjs enabled configuration check over to the
    * parent.
    */
-  isDefaultHandlerApp: function () {
+  isDefaultHandlerApp() {
     var handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
     return (!handlerInfo.alwaysAskBeforeHandling &&
             handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally);
   },
 
   /*
    * Display a notification warning when the renderer isn't sure
    * a pdf displayed correctly.
    */
-  _displayWarning: function (aMsg) {
+  _displayWarning(aMsg) {
     let data = aMsg.data;
     let browser = aMsg.target;
 
     let tabbrowser = browser.getTabBrowser();
     let notificationBox = tabbrowser.getNotificationBox(browser);
 
     // Flag so we don't send the message twice, since if the user clicks
     // "open with different viewer" both the button callback and
     // eventCallback will be called.
     let messageSent = false;
     function sendMessage(download) {
       let mm = browser.messageManager;
-      mm.sendAsyncMessage('PDFJS:Child:fallbackDownload',
-                          { download: download });
+      mm.sendAsyncMessage('PDFJS:Child:fallbackDownload', { download, });
     }
     let buttons = [{
       label: data.label,
       accessKey: data.accessKey,
-      callback: function() {
+      callback() {
         messageSent = true;
         sendMessage(true);
       }
     }];
     notificationBox.appendNotification(data.message, 'pdfjs-fallback', null,
                                        notificationBox.PRIORITY_INFO_LOW,
                                        buttons,
                                        function eventsCallback(eventType) {
--- a/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm
+++ b/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm
@@ -33,111 +33,111 @@ var PdfjsContentUtils = {
    * Public API
    */
 
   get isRemote() {
     return (Services.appinfo.processType ===
             Services.appinfo.PROCESS_TYPE_CONTENT);
   },
 
-  init: function () {
+  init() {
     // child *process* mm, or when loaded into the parent for in-content
     // support the psuedo child process mm 'child PPMM'.
     if (!this._mm) {
       this._mm = Cc['@mozilla.org/childprocessmessagemanager;1'].
         getService(Ci.nsISyncMessageSender);
       this._mm.addMessageListener('PDFJS:Child:refreshSettings', this);
       Services.obs.addObserver(this, 'quit-application', false);
     }
   },
 
-  uninit: function () {
+  uninit() {
     if (this._mm) {
       this._mm.removeMessageListener('PDFJS:Child:refreshSettings', this);
       Services.obs.removeObserver(this, 'quit-application');
     }
     this._mm = null;
   },
 
   /*
    * prefs utilities - the child does not have write access to prefs.
    * note, the pref names here are cross-checked against a list of
    * approved pdfjs prefs in chrome utils.
    */
 
-  clearUserPref: function (aPrefName) {
+  clearUserPref(aPrefName) {
     this._mm.sendSyncMessage('PDFJS:Parent:clearUserPref', {
       name: aPrefName
     });
   },
 
-  setIntPref: function (aPrefName, aPrefValue) {
+  setIntPref(aPrefName, aPrefValue) {
     this._mm.sendSyncMessage('PDFJS:Parent:setIntPref', {
       name: aPrefName,
       value: aPrefValue
     });
   },
 
-  setBoolPref: function (aPrefName, aPrefValue) {
+  setBoolPref(aPrefName, aPrefValue) {
     this._mm.sendSyncMessage('PDFJS:Parent:setBoolPref', {
       name: aPrefName,
       value: aPrefValue
     });
   },
 
-  setCharPref: function (aPrefName, aPrefValue) {
+  setCharPref(aPrefName, aPrefValue) {
     this._mm.sendSyncMessage('PDFJS:Parent:setCharPref', {
       name: aPrefName,
       value: aPrefValue
     });
   },
 
-  setStringPref: function (aPrefName, aPrefValue) {
+  setStringPref(aPrefName, aPrefValue) {
     this._mm.sendSyncMessage('PDFJS:Parent:setStringPref', {
       name: aPrefName,
       value: aPrefValue
     });
   },
 
   /*
    * Forwards default app query to the parent where we check various
    * handler app settings only available in the parent process.
    */
-  isDefaultHandlerApp: function () {
+  isDefaultHandlerApp() {
     return this._mm.sendSyncMessage('PDFJS:Parent:isDefaultHandlerApp')[0];
   },
 
   /*
    * Request the display of a notification warning in the associated window
    * when the renderer isn't sure a pdf displayed correctly.
    */
-  displayWarning: function (aWindow, aMessage, aLabel, accessKey) {
+  displayWarning(aWindow, aMessage, aLabel, aAccessKey) {
     // the child's dom frame mm associated with the window.
     let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIDocShell)
                        .QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIContentFrameMessageManager);
     winmm.sendAsyncMessage('PDFJS:Parent:displayWarning', {
       message: aMessage,
       label: aLabel,
-      accessKey: accessKey
+      accessKey: aAccessKey,
     });
   },
 
   /*
    * Events
    */
 
-  observe: function(aSubject, aTopic, aData) {
+  observe(aSubject, aTopic, aData) {
     if (aTopic === 'quit-application') {
       this.uninit();
     }
   },
 
-  receiveMessage: function (aMsg) {
+  receiveMessage(aMsg) {
     switch (aMsg.name) {
       case 'PDFJS:Child:refreshSettings':
         // Only react to this if we are remote.
         if (Services.appinfo.processType ===
             Services.appinfo.PROCESS_TYPE_CONTENT) {
           let jsm = 'resource://pdf.js/PdfJs.jsm';
           let pdfjs = Components.utils.import(jsm, {}).PdfJs;
           pdfjs.updateRegistration();
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -18,18 +18,18 @@
   define('pdfjs-dist/build/pdf', ['exports'], factory);
  } else if (typeof exports !== 'undefined') {
   factory(exports);
  } else {
   factory(root['pdfjsDistBuildPdf'] = {});
  }
 }(this, function (exports) {
  'use strict';
- var pdfjsVersion = '1.6.467';
- var pdfjsBuild = '54d55e8b';
+ var pdfjsVersion = '1.7.227';
+ var pdfjsBuild = 'e132fa97';
  var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
  var pdfjsLibs = {};
  (function pdfjsWrapper() {
   (function (root, factory) {
    factory(root.pdfjsSharedUtil = {});
   }(this, function (exports) {
    var globalScope = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this;
    var FONT_IDENTITY_MATRIX = [
@@ -1429,16 +1429,17 @@
   }));
   (function (root, factory) {
    factory(root.pdfjsDisplayDOMUtils = {}, root.pdfjsSharedUtil);
   }(this, function (exports, sharedUtil) {
    var removeNullCharacters = sharedUtil.removeNullCharacters;
    var warn = sharedUtil.warn;
    var deprecated = sharedUtil.deprecated;
    var createValidAbsoluteUrl = sharedUtil.createValidAbsoluteUrl;
+   var DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
    var CustomStyle = function CustomStyleClosure() {
     var prefixes = [
      'ms',
      'Moz',
      'Webkit',
      'O'
     ];
     var _cache = Object.create(null);
@@ -1554,17 +1555,17 @@
      case LinkTarget.PARENT:
      case LinkTarget.TOP:
       return globalSettings.externalLinkTarget;
      }
      warn('PDFJS.externalLinkTarget is invalid: ' + globalSettings.externalLinkTarget);
      globalSettings.externalLinkTarget = LinkTarget.NONE;
      return LinkTarget.NONE;
     case 'externalLinkRel':
-     return globalSettings ? globalSettings.externalLinkRel : 'noreferrer';
+     return globalSettings ? globalSettings.externalLinkRel : DEFAULT_LINK_REL;
     case 'enableStats':
      return !!(globalSettings && globalSettings.enableStats);
     default:
      throw new Error('Unknown default setting: ' + id);
     }
    }
    function isExternalLinkTargetSet() {
     var externalLinkTarget = getDefaultSetting('externalLinkTarget');
@@ -1586,16 +1587,17 @@
    exports.CustomStyle = CustomStyle;
    exports.addLinkAttributes = addLinkAttributes;
    exports.isExternalLinkTargetSet = isExternalLinkTargetSet;
    exports.isValidUrl = isValidUrl;
    exports.getFilenameFromUrl = getFilenameFromUrl;
    exports.LinkTarget = LinkTarget;
    exports.hasCanvasTypedArrays = hasCanvasTypedArrays;
    exports.getDefaultSetting = getDefaultSetting;
+   exports.DEFAULT_LINK_REL = DEFAULT_LINK_REL;
   }));
   (function (root, factory) {
    factory(root.pdfjsDisplayFontLoader = {}, root.pdfjsSharedUtil);
   }(this, function (exports, sharedUtil) {
    var assert = sharedUtil.assert;
    var bytesToString = sharedUtil.bytesToString;
    var string32 = sharedUtil.string32;
    var shadow = sharedUtil.shadow;
@@ -5079,25 +5081,23 @@
         }
        };
        pattern = new TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform);
       } else {
        pattern = getShadingPatternFromIR(IR);
       }
       return pattern;
      },
-     setStrokeColorN: function CanvasGraphics_setStrokeColorN()
-      {
-       this.current.strokeColor = this.getColorN_Pattern(arguments);
-      },
-     setFillColorN: function CanvasGraphics_setFillColorN()
-      {
-       this.current.fillColor = this.getColorN_Pattern(arguments);
-       this.current.patternFill = true;
-      },
+     setStrokeColorN: function CanvasGraphics_setStrokeColorN() {
+      this.current.strokeColor = this.getColorN_Pattern(arguments);
+     },
+     setFillColorN: function CanvasGraphics_setFillColorN() {
+      this.current.fillColor = this.getColorN_Pattern(arguments);
+      this.current.patternFill = true;
+     },
      setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
       var color = Util.makeCssRgb(r, g, b);
       this.ctx.strokeStyle = color;
       this.current.strokeColor = color;
      },
      setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
       var color = Util.makeCssRgb(r, g, b);
       this.ctx.fillStyle = color;
@@ -6819,17 +6819,17 @@
       this._continue();
      },
      _continue: function InternalRenderTask__continue() {
       this.running = true;
       if (this.cancelled) {
        return;
       }
       if (this.task.onContinue) {
-       this.task.onContinue.call(this.task, this._scheduleNextBound);
+       this.task.onContinue(this._scheduleNextBound);
       } else {
        this._scheduleNext();
       }
      },
      _scheduleNext: function InternalRenderTask__scheduleNext() {
       if (this.useRequestAnimationFrame && typeof window !== 'undefined') {
        window.requestAnimationFrame(this._nextBound);
       } else {
@@ -6881,16 +6881,17 @@
   }));
   (function (root, factory) {
    factory(root.pdfjsDisplayGlobal = {}, root.pdfjsSharedUtil, root.pdfjsDisplayDOMUtils, root.pdfjsDisplayAPI, root.pdfjsDisplayAnnotationLayer, root.pdfjsDisplayTextLayer, root.pdfjsDisplayMetadata, root.pdfjsDisplaySVG);
   }(this, function (exports, sharedUtil, displayDOMUtils, displayAPI, displayAnnotationLayer, displayTextLayer, displayMetadata, displaySVG) {
    var globalScope = sharedUtil.globalScope;
    var deprecated = sharedUtil.deprecated;
    var warn = sharedUtil.warn;
    var LinkTarget = displayDOMUtils.LinkTarget;
+   var DEFAULT_LINK_REL = displayDOMUtils.DEFAULT_LINK_REL;
    var isWorker = typeof window === 'undefined';
    if (!globalScope.PDFJS) {
     globalScope.PDFJS = {};
    }
    var PDFJS = globalScope.PDFJS;
    if (typeof pdfjsVersion !== 'undefined') {
     PDFJS.version = pdfjsVersion;
    }
@@ -6948,17 +6949,17 @@
    PDFJS.disableRange = PDFJS.disableRange === undefined ? false : PDFJS.disableRange;
    PDFJS.disableStream = PDFJS.disableStream === undefined ? false : PDFJS.disableStream;
    PDFJS.disableAutoFetch = PDFJS.disableAutoFetch === undefined ? false : PDFJS.disableAutoFetch;
    PDFJS.pdfBug = PDFJS.pdfBug === undefined ? false : PDFJS.pdfBug;
    PDFJS.postMessageTransfers = PDFJS.postMessageTransfers === undefined ? true : PDFJS.postMessageTransfers;
    PDFJS.disableCreateObjectURL = PDFJS.disableCreateObjectURL === undefined ? false : PDFJS.disableCreateObjectURL;
    PDFJS.disableWebGL = PDFJS.disableWebGL === undefined ? true : PDFJS.disableWebGL;
    PDFJS.externalLinkTarget = PDFJS.externalLinkTarget === undefined ? LinkTarget.NONE : PDFJS.externalLinkTarget;
-   PDFJS.externalLinkRel = PDFJS.externalLinkRel === undefined ? 'noreferrer' : PDFJS.externalLinkRel;
+   PDFJS.externalLinkRel = PDFJS.externalLinkRel === undefined ? DEFAULT_LINK_REL : PDFJS.externalLinkRel;
    PDFJS.isEvalSupported = PDFJS.isEvalSupported === undefined ? true : PDFJS.isEvalSupported;
    PDFJS.getDocument = displayAPI.getDocument;
    PDFJS.PDFDataRangeTransport = displayAPI.PDFDataRangeTransport;
    PDFJS.PDFWorker = displayAPI.PDFWorker;
    Object.defineProperty(PDFJS, 'hasCanvasTypedArrays', {
     configurable: true,
     get: function PDFJS_hasCanvasTypedArrays() {
      var value = displayDOMUtils.hasCanvasTypedArrays();
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -18,18 +18,18 @@
   define('pdfjs-dist/build/pdf.worker', ['exports'], factory);
  } else if (typeof exports !== 'undefined') {
   factory(exports);
  } else {
   factory(root['pdfjsDistBuildPdfWorker'] = {});
  }
 }(this, function (exports) {
  'use strict';
- var pdfjsVersion = '1.6.467';
- var pdfjsBuild = '54d55e8b';
+ var pdfjsVersion = '1.7.227';
+ var pdfjsBuild = 'e132fa97';
  var pdfjsFilePath = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : null;
  var pdfjsLibs = {};
  (function pdfjsWrapper() {
   (function (root, factory) {
    factory(root.pdfjsCoreArithmeticDecoder = {});
   }(this, function (exports) {
    var ArithmeticDecoder = function ArithmeticDecoderClosure() {
     var QeTable = [
@@ -38192,17 +38192,17 @@
            i += offset - 1;
           }
          }
         }
         if (!inFDEF && !inELSE) {
          var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0;
          if (op >= 0x71 && op <= 0x75) {
           n = stack.pop();
-          if (n === n) {
+          if (!isNaN(n)) {
            stackDelta = -n * 2;
           }
          }
          while (stackDelta < 0 && stack.length > 0) {
           stack.pop();
           stackDelta++;
          }
          while (stackDelta > 0) {
deleted file mode 100644
--- a/browser/extensions/pdfjs/content/network.js
+++ /dev/null
@@ -1,617 +0,0 @@
-/* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// NOTE: Be careful what goes in this file, as it is also used from the context
-// of the addon. So using warn/error in here will break the addon.
-
-'use strict';
-
-(function (root, factory) {
-  if (typeof define === 'function' && define.amd) {
-    define('pdfjs/core/network', ['exports', 'pdfjs/shared/util',
-      'pdfjs/core/worker'], factory);
-  } else if (typeof exports !== 'undefined') {
-    factory(exports, require('../shared/util.js'), require('./worker.js'));
-  } else {
-    factory((root.pdfjsCoreNetwork = {}), root.pdfjsSharedUtil,
-      root.pdfjsCoreWorker);
-  }
-}(this, function (exports, sharedUtil, coreWorker) {
-if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
-  throw new Error('Module "pdfjs/core/network" shall not ' +
-                  'be used with FIREFOX or MOZCENTRAL build.');
-}
-
-  var OK_RESPONSE = 200;
-  var PARTIAL_CONTENT_RESPONSE = 206;
-
-  function NetworkManager(url, args) {
-    this.url = url;
-    args = args || {};
-    this.isHttp = /^https?:/i.test(url);
-    this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
-    this.withCredentials = args.withCredentials || false;
-    this.getXhr = args.getXhr ||
-      function NetworkManager_getXhr() {
-        return new XMLHttpRequest();
-      };
-
-    this.currXhrId = 0;
-    this.pendingRequests = Object.create(null);
-    this.loadedRequests = Object.create(null);
-  }
-
-  function getArrayBuffer(xhr) {
-    var data = xhr.response;
-    if (typeof data !== 'string') {
-      return data;
-    }
-    var length = data.length;
-    var array = new Uint8Array(length);
-    for (var i = 0; i < length; i++) {
-      array[i] = data.charCodeAt(i) & 0xFF;
-    }
-    return array.buffer;
-  }
-
-  var supportsMozChunked =
-    typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME') ? false :
-      (function supportsMozChunkedClosure() {
-    try {
-      var x = new XMLHttpRequest();
-      // Firefox 37- required .open() to be called before setting responseType.
-      // https://bugzilla.mozilla.org/show_bug.cgi?id=707484
-      // Even though the URL is not visited, .open() could fail if the URL is
-      // blocked, e.g. via the connect-src CSP directive or the NoScript addon.
-      // When this error occurs, this feature detection method will mistakenly
-      // report that moz-chunked-arraybuffer is not supported in Firefox 37-.
-      x.open('GET', 'https://example.com');
-      x.responseType = 'moz-chunked-arraybuffer';
-      return x.responseType === 'moz-chunked-arraybuffer';
-    } catch (e) {
-      return false;
-    }
-  })();
-
-  NetworkManager.prototype = {
-    requestRange: function NetworkManager_requestRange(begin, end, listeners) {
-      var args = {
-        begin: begin,
-        end: end
-      };
-      for (var prop in listeners) {
-        args[prop] = listeners[prop];
-      }
-      return this.request(args);
-    },
-
-    requestFull: function NetworkManager_requestFull(listeners) {
-      return this.request(listeners);
-    },
-
-    request: function NetworkManager_request(args) {
-      var xhr = this.getXhr();
-      var xhrId = this.currXhrId++;
-      var pendingRequest = this.pendingRequests[xhrId] = {
-        xhr: xhr
-      };
-
-      xhr.open('GET', this.url);
-      xhr.withCredentials = this.withCredentials;
-      for (var property in this.httpHeaders) {
-        var value = this.httpHeaders[property];
-        if (typeof value === 'undefined') {
-          continue;
-        }
-        xhr.setRequestHeader(property, value);
-      }
-      if (this.isHttp && 'begin' in args && 'end' in args) {
-        var rangeStr = args.begin + '-' + (args.end - 1);
-        xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
-        pendingRequest.expectedStatus = 206;
-      } else {
-        pendingRequest.expectedStatus = 200;
-      }
-
-      var useMozChunkedLoading = supportsMozChunked && !!args.onProgressiveData;
-      if (useMozChunkedLoading) {
-        xhr.responseType = 'moz-chunked-arraybuffer';
-        pendingRequest.onProgressiveData = args.onProgressiveData;
-        pendingRequest.mozChunked = true;
-      } else {
-        xhr.responseType = 'arraybuffer';
-      }
-
-      if (args.onError) {
-        xhr.onerror = function(evt) {
-          args.onError(xhr.status);
-        };
-      }
-      xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
-      xhr.onprogress = this.onProgress.bind(this, xhrId);
-
-      pendingRequest.onHeadersReceived = args.onHeadersReceived;
-      pendingRequest.onDone = args.onDone;
-      pendingRequest.onError = args.onError;
-      pendingRequest.onProgress = args.onProgress;
-
-      xhr.send(null);
-
-      return xhrId;
-    },
-
-    onProgress: function NetworkManager_onProgress(xhrId, evt) {
-      var pendingRequest = this.pendingRequests[xhrId];
-      if (!pendingRequest) {
-        // Maybe abortRequest was called...
-        return;
-      }
-
-      if (pendingRequest.mozChunked) {
-        var chunk = getArrayBuffer(pendingRequest.xhr);
-        pendingRequest.onProgressiveData(chunk);
-      }
-
-      var onProgress = pendingRequest.onProgress;
-      if (onProgress) {
-        onProgress(evt);
-      }
-    },
-
-    onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
-      var pendingRequest = this.pendingRequests[xhrId];
-      if (!pendingRequest) {
-        // Maybe abortRequest was called...
-        return;
-      }
-
-      var xhr = pendingRequest.xhr;
-      if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
-        pendingRequest.onHeadersReceived();
-        delete pendingRequest.onHeadersReceived;
-      }
-
-      if (xhr.readyState !== 4) {
-        return;
-      }
-
-      if (!(xhrId in this.pendingRequests)) {
-        // The XHR request might have been aborted in onHeadersReceived()
-        // callback, in which case we should abort request
-        return;
-      }
-
-      delete this.pendingRequests[xhrId];
-
-      // success status == 0 can be on ftp, file and other protocols
-      if (xhr.status === 0 && this.isHttp) {
-        if (pendingRequest.onError) {
-          pendingRequest.onError(xhr.status);
-        }
-        return;
-      }
-      var xhrStatus = xhr.status || OK_RESPONSE;
-
-      // From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
-      // "A server MAY ignore the Range header". This means it's possible to
-      // get a 200 rather than a 206 response from a range request.
-      var ok_response_on_range_request =
-          xhrStatus === OK_RESPONSE &&
-          pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
-
-      if (!ok_response_on_range_request &&
-          xhrStatus !== pendingRequest.expectedStatus) {
-        if (pendingRequest.onError) {
-          pendingRequest.onError(xhr.status);
-        }
-        return;
-      }
-
-      this.loadedRequests[xhrId] = true;
-
-      var chunk = getArrayBuffer(xhr);
-      if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
-        var rangeHeader = xhr.getResponseHeader('Content-Range');
-        var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
-        var begin = parseInt(matches[1], 10);
-        pendingRequest.onDone({
-          begin: begin,
-          chunk: chunk
-        });
-      } else if (pendingRequest.onProgressiveData) {
-        pendingRequest.onDone(null);
-      } else if (chunk) {
-        pendingRequest.onDone({
-          begin: 0,
-          chunk: chunk
-        });
-      } else if (pendingRequest.onError) {
-        pendingRequest.onError(xhr.status);
-      }
-    },
-
-    hasPendingRequests: function NetworkManager_hasPendingRequests() {
-      for (var xhrId in this.pendingRequests) {
-        return true;
-      }
-      return false;
-    },
-
-    getRequestXhr: function NetworkManager_getXhr(xhrId) {
-      return this.pendingRequests[xhrId].xhr;
-    },
-
-    isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
-      return !!(this.pendingRequests[xhrId].onProgressiveData);
-    },
-
-    isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
-      return xhrId in this.pendingRequests;
-    },
-
-    isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
-      return xhrId in this.loadedRequests;
-    },
-
-    abortAllRequests: function NetworkManager_abortAllRequests() {
-      for (var xhrId in this.pendingRequests) {
-        this.abortRequest(xhrId | 0);
-      }
-    },
-
-    abortRequest: function NetworkManager_abortRequest(xhrId) {
-      var xhr = this.pendingRequests[xhrId].xhr;
-      delete this.pendingRequests[xhrId];
-      xhr.abort();
-    }
-  };
-
-  var assert = sharedUtil.assert;
-  var createPromiseCapability = sharedUtil.createPromiseCapability;
-  var isInt = sharedUtil.isInt;
-  var MissingPDFException = sharedUtil.MissingPDFException;
-  var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
-
-  /** @implements {IPDFStream} */
-  function PDFNetworkStream(options) {
-    this._options = options;
-    var source = options.source;
-    this._manager = new NetworkManager(source.url, {
-      httpHeaders: source.httpHeaders,
-      withCredentials: source.withCredentials
-    });
-    this._rangeChunkSize = source.rangeChunkSize;
-    this._fullRequestReader = null;
-    this._rangeRequestReaders = [];
-  }
-
-  PDFNetworkStream.prototype = {
-    _onRangeRequestReaderClosed:
-        function PDFNetworkStream_onRangeRequestReaderClosed(reader) {
-      var i = this._rangeRequestReaders.indexOf(reader);
-      if (i >= 0) {
-        this._rangeRequestReaders.splice(i, 1);
-      }
-    },
-
-    getFullReader: function PDFNetworkStream_getFullReader() {
-      assert(!this._fullRequestReader);
-      this._fullRequestReader =
-        new PDFNetworkStreamFullRequestReader(this._manager, this._options);
-      return this._fullRequestReader;
-    },
-
-    getRangeReader: function PDFNetworkStream_getRangeReader(begin, end) {
-      var reader = new PDFNetworkStreamRangeRequestReader(this._manager,
-                                                          begin, end);
-      reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
-      this._rangeRequestReaders.push(reader);
-      return reader;
-    },
-
-    cancelAllRequests: function PDFNetworkStream_cancelAllRequests(reason) {
-      if (this._fullRequestReader) {
-        this._fullRequestReader.cancel(reason);
-      }
-      var readers = this._rangeRequestReaders.slice(0);
-      readers.forEach(function (reader) {
-        reader.cancel(reason);
-      });
-    }
-  };
-
-  /** @implements {IPDFStreamReader} */
-  function PDFNetworkStreamFullRequestReader(manager, options) {
-    this._manager = manager;
-
-    var source = options.source;
-    var args = {
-      onHeadersReceived: this._onHeadersReceived.bind(this),
-      onProgressiveData: source.disableStream ? null :
-                         this._onProgressiveData.bind(this),
-      onDone: this._onDone.bind(this),
-      onError: this._onError.bind(this),
-      onProgress: this._onProgress.bind(this)
-    };
-    this._url = source.url;
-    this._fullRequestId = manager.requestFull(args);
-    this._headersReceivedCapability = createPromiseCapability();
-    this._disableRange = options.disableRange || false;
-    this._contentLength = source.length; // optional
-    this._rangeChunkSize = source.rangeChunkSize;
-    if (!this._rangeChunkSize && !this._disableRange) {
-      this._disableRange = true;
-    }
-
-    this._isStreamingSupported = false;
-    this._isRangeSupported = false;
-
-    this._cachedChunks = [];
-    this._requests = [];
-    this._done = false;
-    this._storedError = undefined;
-
-    this.onProgress = null;
-  }
-
-  PDFNetworkStreamFullRequestReader.prototype = {
-    _validateRangeRequestCapabilities: function
-        PDFNetworkStreamFullRequestReader_validateRangeRequestCapabilities() {
-
-      if (this._disableRange) {
-        return false;
-      }
-
-      var networkManager = this._manager;
-      if (!networkManager.isHttp) {
-        return false;
-      }
-      var fullRequestXhrId = this._fullRequestId;
-      var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId);
-      if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') {
-        return false;
-      }
-
-      var contentEncoding =
-        fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity';
-      if (contentEncoding !== 'identity') {
-        return false;
-      }
-
-      var length = fullRequestXhr.getResponseHeader('Content-Length');
-      length = parseInt(length, 10);
-      if (!isInt(length)) {
-        return false;
-      }
-
-      this._contentLength = length; // setting right content length
-
-      if (length <= 2 * this._rangeChunkSize) {
-        // The file size is smaller than the size of two chunks, so it does
-        // not make any sense to abort the request and retry with a range
-        // request.
-        return false;
-      }
-
-      return true;
-    },
-
-    _onHeadersReceived:
-        function PDFNetworkStreamFullRequestReader_onHeadersReceived() {
-
-      if (this._validateRangeRequestCapabilities()) {
-        this._isRangeSupported = true;
-      }
-
-      var networkManager = this._manager;
-      var fullRequestXhrId = this._fullRequestId;
-      if (networkManager.isStreamingRequest(fullRequestXhrId)) {
-        // We can continue fetching when progressive loading is enabled,
-        // and we don't need the autoFetch feature.
-        this._isStreamingSupported = true;
-      } else if (this._isRangeSupported) {
-        // NOTE: by cancelling the full request, and then issuing range
-        // requests, there will be an issue for sites where you can only
-        // request the pdf once. However, if this is the case, then the
-        // server should not be returning that it can support range
-        // requests.
-        networkManager.abortRequest(fullRequestXhrId);
-      }
-
-      this._headersReceivedCapability.resolve();
-    },
-
-    _onProgressiveData:
-        function PDFNetworkStreamFullRequestReader_onProgressiveData(chunk) {
-      if (this._requests.length > 0) {
-        var requestCapability = this._requests.shift();
-        requestCapability.resolve({value: chunk, done: false});
-      } else {
-        this._cachedChunks.push(chunk);
-      }
-    },
-
-    _onDone: function PDFNetworkStreamFullRequestReader_onDone(args) {
-      if (args) {
-        this._onProgressiveData(args.chunk);
-      }
-      this._done = true;
-      if (this._cachedChunks.length > 0) {
-        return;
-      }
-      this._requests.forEach(function (requestCapability) {
-        requestCapability.resolve({value: undefined, done: true});
-      });
-      this._requests = [];
-    },
-
-    _onError: function PDFNetworkStreamFullRequestReader_onError(status) {
-      var url = this._url;
-      var exception;
-      if (status === 404 || status === 0 && /^file:/.test(url)) {
-        exception = new MissingPDFException('Missing PDF "' + url + '".');
-      } else {
-        exception = new UnexpectedResponseException(
-          'Unexpected server response (' + status +
-          ') while retrieving PDF "' + url + '".', status);
-      }
-      this._storedError = exception;
-      this._headersReceivedCapability.reject(exception);
-      this._requests.forEach(function (requestCapability) {
-        requestCapability.reject(exception);
-      });
-      this._requests = [];
-      this._cachedChunks = [];
-    },
-
-    _onProgress: function PDFNetworkStreamFullRequestReader_onProgress(data) {
-      if (this.onProgress) {
-        this.onProgress({
-          loaded: data.loaded,
-          total: data.lengthComputable ? data.total : this._contentLength
-        });
-      }
-    },
-
-    get isRangeSupported() {
-      return this._isRangeSupported;
-    },
-
-    get isStreamingSupported() {
-      return this._isStreamingSupported;
-    },
-
-    get contentLength() {
-      return this._contentLength;
-    },
-
-    get headersReady() {
-      return this._headersReceivedCapability.promise;
-    },
-
-    read: function PDFNetworkStreamFullRequestReader_read() {
-      if (this._storedError) {
-        return Promise.reject(this._storedError);
-      }
-      if (this._cachedChunks.length > 0) {
-        var chunk = this._cachedChunks.shift();
-        return Promise.resolve(chunk);
-      }
-      if (this._done) {
-        return Promise.resolve({value: undefined, done: true});
-      }
-      var requestCapability = createPromiseCapability();
-      this._requests.push(requestCapability);
-      return requestCapability.promise;
-    },
-
-    cancel: function PDFNetworkStreamFullRequestReader_cancel(reason) {
-      this._done = true;
-      this._headersReceivedCapability.reject(reason);
-      this._requests.forEach(function (requestCapability) {
-        requestCapability.resolve({value: undefined, done: true});
-      });
-      this._requests = [];
-      if (this._manager.isPendingRequest(this._fullRequestId)) {
-        this._manager.abortRequest(this._fullRequestId);
-      }
-      this._fullRequestReader = null;
-    }
-  };
-
-  /** @implements {IPDFStreamRangeReader} */
-  function PDFNetworkStreamRangeRequestReader(manager, begin, end) {
-    this._manager = manager;
-    var args = {
-      onDone: this._onDone.bind(this),
-      onProgress: this._onProgress.bind(this)
-    };
-    this._requestId = manager.requestRange(begin, end, args);
-    this._requests = [];
-    this._queuedChunk = null;
-    this._done = false;
-
-    this.onProgress = null;
-    this.onClosed = null;
-  }
-
-  PDFNetworkStreamRangeRequestReader.prototype = {
-    _close: function PDFNetworkStreamRangeRequestReader_close() {
-      if (this.onClosed) {
-        this.onClosed(this);
-      }
-    },
-
-    _onDone: function PDFNetworkStreamRangeRequestReader_onDone(data) {
-      var chunk = data.chunk;
-      if (this._requests.length > 0) {
-        var requestCapability = this._requests.shift();
-        requestCapability.resolve({value: chunk, done: false});
-      } else {
-        this._queuedChunk = chunk;
-      }
-      this._done = true;
-      this._requests.forEach(function (requestCapability) {
-        requestCapability.resolve({value: undefined, done: true});
-      });
-      this._requests = [];
-      this._close();
-    },
-
-    _onProgress: function PDFNetworkStreamRangeRequestReader_onProgress(evt) {
-      if (!this.isStreamingSupported && this.onProgress) {
-        this.onProgress({
-          loaded: evt.loaded
-        });
-      }
-    },
-
-    get isStreamingSupported() {
-      return false; // TODO allow progressive range bytes loading
-    },
-
-    read: function PDFNetworkStreamRangeRequestReader_read() {
-      if (this._queuedChunk !== null) {
-        var chunk = this._queuedChunk;
-        this._queuedChunk = null;
-        return Promise.resolve({value: chunk, done: false});
-      }
-      if (this._done) {
-        return Promise.resolve({value: undefined, done: true});
-      }
-      var requestCapability = createPromiseCapability();
-      this._requests.push(requestCapability);
-      return requestCapability.promise;
-    },
-
-    cancel: function PDFNetworkStreamRangeRequestReader_cancel(reason) {
-      this._done = true;
-      this._requests.forEach(function (requestCapability) {
-        requestCapability.resolve({value: undefined, done: true});
-      });
-      this._requests = [];
-      if (this._manager.isPendingRequest(this._requestId)) {
-        this._manager.abortRequest(this._requestId);
-      }
-      this._close();
-    }
-  };
-
-  coreWorker.setPDFNetworkStreamClass(PDFNetworkStream);
-
-  exports.PDFNetworkStream = PDFNetworkStream;
-  exports.NetworkManager = NetworkManager;
-}));
-
--- a/browser/extensions/pdfjs/content/web/l10n.js
+++ b/browser/extensions/pdfjs/content/web/l10n.js
@@ -116,35 +116,37 @@
   });
 
   // Public API
   document.mozL10n = {
     // get a localized string
     get: translateString,
 
     // get the document language
-    getLanguage: function() {
+    getLanguage() {
       return gLanguage;
     },
 
     // get the direction (ltr|rtl) of the current language
-    getDirection: function() {
+    getDirection() {
       // http://www.w3.org/International/questions/qa-scripts
       // Arabic, Hebrew, Farsi, Pashto, Urdu
       var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
 
       // use the short language code for "full" codes like 'ar-sa' (issue 5440)
       var shortCode = gLanguage.split('-')[0];
 
       return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr';
     },
 
-    getReadyState: function() { return gReadyState; },
+    getReadyState() {
+      return gReadyState;
+    },
 
-    setExternalLocalizerServices: function (externalLocalizerServices) {
+    setExternalLocalizerServices(externalLocalizerServices) {
       gExternalLocalizerServices = externalLocalizerServices;
 
       // ... in case if we missed DOMContentLoaded above.
       if (window.document.readyState === 'interactive' ||
           window.document.readyState === 'complete') {
         translateDocument();
       }
     },
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -2473,18 +2473,18 @@ var pdfjsWebLibs;
      anchor.href = linkService.getAnchorUrl('#page=' + id);
      anchor.title = mozL10n.get('thumb_page_title', { page: id }, 'Page {{page}}');
      anchor.onclick = function stopNavigation() {
       linkService.page = id;
       return false;
      };
      this.anchor = anchor;
      var div = document.createElement('div');
-     div.id = 'thumbnailContainer' + id;
      div.className = 'thumbnail';
+     div.setAttribute('data-page-number', this.id);
      this.div = div;
      if (id === 1) {
       div.classList.add('selected');
      }
      var ring = document.createElement('div');
      ring.className = 'thumbnailSelectionRing';
      var borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH;
      ring.style.width = this.canvasWidth + borderAdjustment + 'px';
@@ -3868,27 +3868,26 @@ var pdfjsWebLibs;
      this.enhanceTextSelection = enhanceTextSelection;
      this.renderInteractiveForms = renderInteractiveForms;
      this.eventBus = options.eventBus || domEvents.getGlobalEventBus();
      this.renderingQueue = renderingQueue;
      this.textLayerFactory = textLayerFactory;
      this.annotationLayerFactory = annotationLayerFactory;
      this.renderer = options.renderer || RendererType.CANVAS;
      this.paintTask = null;
-     this.paintedViewport = null;
+     this.paintedViewportMap = new WeakMap();
      this.renderingState = RenderingStates.INITIAL;
      this.resume = null;
      this.error = null;
      this.onBeforeDraw = null;
      this.onAfterDraw = null;
      this.textLayer = null;
      this.zoomLayer = null;
      this.annotationLayer = null;
      var div = document.createElement('div');
-     div.id = 'pageContainer' + this.id;
      div.className = 'page';
      div.style.width = Math.floor(this.viewport.width) + 'px';
      div.style.height = Math.floor(this.viewport.height) + 'px';
      div.setAttribute('data-page-number', this.id);
      this.div = div;
      container.appendChild(div);
     }
     PDFPageView.prototype = {
@@ -3924,26 +3923,25 @@ var pdfjsWebLibs;
       }
       div.removeAttribute('data-loaded');
       if (currentAnnotationNode) {
        this.annotationLayer.hide();
       } else {
        this.annotationLayer = null;
       }
       if (this.canvas && !currentZoomLayerNode) {
+       this.paintedViewportMap.delete(this.canvas);
        this.canvas.width = 0;
        this.canvas.height = 0;
        delete this.canvas;
       }
       if (this.svg) {
+       this.paintedViewportMap.delete(this.svg);
        delete this.svg;
       }
-      if (!currentZoomLayerNode) {
-       this.paintedViewport = null;
-      }
       this.loadingIconDiv = document.createElement('div');
       this.loadingIconDiv.className = 'loadingIcon';
       div.appendChild(this.loadingIconDiv);
      },
      update: function PDFPageView_update(scale, rotation) {
       this.scale = scale || this.scale;
       if (typeof rotation !== 'undefined') {
        this.rotation = rotation;
@@ -4008,17 +4006,17 @@ var pdfjsWebLibs;
      },
      cssTransform: function PDFPageView_transform(target, redrawAnnotations) {
       var CustomStyle = pdfjsLib.CustomStyle;
       var width = this.viewport.width;
       var height = this.viewport.height;
       var div = this.div;
       target.style.width = target.parentNode.style.width = div.style.width = Math.floor(width) + 'px';
       target.style.height = target.parentNode.style.height = div.style.height = Math.floor(height) + 'px';
-      var relativeRotation = this.viewport.rotation - this.paintedViewport.rotation;
+      var relativeRotation = this.viewport.rotation - this.paintedViewportMap.get(target).rotation;
       var absRotation = Math.abs(relativeRotation);
       var scaleX = 1, scaleY = 1;
       if (absRotation === 90 || absRotation === 270) {
        scaleX = height / width;
        scaleY = width / height;
       }
       var cssTransform = 'rotate(' + relativeRotation + 'deg) ' + 'scale(' + scaleX + ',' + scaleY + ')';
       CustomStyle.setProp('transform', target, cssTransform);
@@ -4126,16 +4124,17 @@ var pdfjsWebLibs;
        }
        self.renderingState = RenderingStates.FINISHED;
        if (self.loadingIconDiv) {
         div.removeChild(self.loadingIconDiv);
         delete self.loadingIconDiv;
        }
        if (self.zoomLayer) {
         var zoomLayerCanvas = self.zoomLayer.firstChild;
+        self.paintedViewportMap.delete(zoomLayerCanvas);
         zoomLayerCanvas.width = 0;
         zoomLayerCanvas.height = 0;
         if (div.contains(self.zoomLayer)) {
          div.removeChild(self.zoomLayer);
         }
         self.zoomLayer = null;
        }
        self.error = error;
@@ -4233,17 +4232,17 @@ var pdfjsWebLibs;
        }
       }
       var sfx = approximateFraction(outputScale.sx);
       var sfy = approximateFraction(outputScale.sy);
       canvas.width = roundToDivide(viewport.width * outputScale.sx, sfx[0]);
       canvas.height = roundToDivide(viewport.height * outputScale.sy, sfy[0]);
       canvas.style.width = roundToDivide(viewport.width, sfx[1]) + 'px';
       canvas.style.height = roundToDivide(viewport.height, sfy[1]) + 'px';
-      this.paintedViewport = viewport;
+      this.paintedViewportMap.set(canvas, viewport);
       var transform = !outputScale.scaled ? null : [
        outputScale.sx,
        0,
        0,
        outputScale.sy,
        0,
        0
       ];
@@ -4319,17 +4318,17 @@ var pdfjsWebLibs;
      _getVisibleThumbs: function PDFThumbnailViewer_getVisibleThumbs() {
       return getVisibleElements(this.container, this.thumbnails);
      },
      scrollThumbnailIntoView: function PDFThumbnailViewer_scrollThumbnailIntoView(page) {
       var selected = document.querySelector('.thumbnail.selected');
       if (selected) {
        selected.classList.remove('selected');
       }
-      var thumbnail = document.getElementById('thumbnailContainer' + page);
+      var thumbnail = document.querySelector('div.thumbnail[data-page-number="' + page + '"]');
       if (thumbnail) {
        thumbnail.classList.add('selected');
       }
       var visibleThumbs = this._getVisibleThumbs();
       var numVisibleThumbs = visibleThumbs.views.length;
       if (numVisibleThumbs > 0) {
        var first = visibleThumbs.first.id;
        var last = numVisibleThumbs > 1 ? visibleThumbs.last.id : first;
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -914,17 +914,19 @@ cargo_build_flags = $(CARGOFLAGS)
 ifndef MOZ_DEBUG
 cargo_build_flags = --release
 endif
 ifdef MOZ_CARGO_SUPPORTS_FROZEN
 cargo_build_flags += --frozen
 endif
 
 cargo_build_flags += --manifest-path $(CARGO_FILE)
+ifdef BUILD_VERBOSE_LOG
 cargo_build_flags += --verbose
+endif
 
 # Enable color output if original stdout was a TTY and color settings
 # aren't already present. This essentially restores the default behavior
 # of cargo when running via `mach`.
 ifdef MACH_STDOUT_ISATTY
 ifeq (,$(findstring --color,$(cargo_build_flags)))
 cargo_build_flags += --color=always
 endif
--- a/devtools/client/netmonitor/shared/components/response-panel.js
+++ b/devtools/client/netmonitor/shared/components/response-panel.js
@@ -59,17 +59,21 @@ const ResponsePanel = createClass({
   // Additionally, we also directly parse the response text content to
   // verify whether it's json or not, to handle responses incorrectly
   // labeled as text/plain instead.
   isJSON(mimeType, response) {
     let json, error;
     try {
       json = JSON.parse(response);
     } catch (err) {
-      error = err;
+      try {
+        json = JSON.parse(atob(response));
+      } catch (err64) {
+        error = err;
+      }
     }
 
     if (/\bjson/.test(mimeType) || json) {
       // Extract the actual json substring in case this might be a "JSONP".
       // This regex basically parses a function call and captures the
       // function name and arguments in two separate groups.
       let jsonpRegex = /^\s*([\w$]+)\s*\(\s*([^]*)\s*\)\s*;?\s*$/;
       let [, jsonpCallback, jsonp] = response.match(jsonpRegex) || [];
--- a/devtools/client/netmonitor/test/browser.ini
+++ b/devtools/client/netmonitor/test/browser.ini
@@ -11,16 +11,17 @@ support-files =
   html_image-tooltip-test-page.html
   html_cors-test-page.html
   html_custom-get-page.html
   html_cyrillic-test-page.html
   html_frame-test-page.html
   html_frame-subdocument.html
   html_filter-test-page.html
   html_infinite-get-page.html
+  html_json-b64.html
   html_json-custom-mime-test-page.html
   html_json-long-test-page.html
   html_json-malformed-test-page.html
   html_json-text-mime-test-page.html
   html_jsonp-test-page.html
   html_navigate-test-page.html
   html_params-test-page.html
   html_post-data-test-page.html
@@ -100,16 +101,17 @@ skip-if = (os == 'linux' && debug && bit
 skip-if = (os == 'linux' && debug && bits == 32) # Bug 1303439
 [browser_net_filter-02.js]
 [browser_net_filter-03.js]
 [browser_net_filter-04.js]
 [browser_net_footer-summary.js]
 [browser_net_html-preview.js]
 [browser_net_icon-preview.js]
 [browser_net_image-tooltip.js]
+[browser_net_json-b64.js]
 [browser_net_json-long.js]
 [browser_net_json-malformed.js]
 [browser_net_json_custom_mime.js]
 [browser_net_json_text_mime.js]
 [browser_net_jsonp.js]
 [browser_net_large-response.js]
 [browser_net_leak_on_tab_close.js]
 [browser_net_open_request_in_tab.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/netmonitor/test/browser_net_json-b64.js
@@ -0,0 +1,62 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Tests if JSON responses encoded in base64 are handled correctly.
+ */
+
+add_task(function* () {
+  let { L10N } = require("devtools/client/netmonitor/l10n");
+  let { tab, monitor } = yield initNetMonitor(JSON_B64_URL);
+  info("Starting test... ");
+
+  let { document, NetMonitorView } = monitor.panelWin;
+  let { RequestsMenu } = NetMonitorView;
+
+  RequestsMenu.lazyUpdate = false;
+
+  let wait = waitForNetworkEvents(monitor, 1);
+  yield ContentTask.spawn(tab.linkedBrowser, {}, function* () {
+    content.wrappedJSObject.performRequests();
+  });
+  yield wait;
+
+  wait = waitForDOM(document, "#panel-3");
+  EventUtils.sendMouseEvent({ type: "mousedown" },
+    document.getElementById("details-pane-toggle"));
+  document.querySelector("#tab-3 a").click();
+  yield wait;
+
+  let tabpanel = document.querySelector("#panel-3");
+
+  is(tabpanel.querySelector(".response-error-header") === null, true,
+    "The response error header doesn't have the intended visibility.");
+  let jsonView = tabpanel.querySelector(".tree-section .treeLabel") || {};
+  is(jsonView.textContent === L10N.getStr("jsonScopeName"), true,
+    "The response json view has the intended visibility.");
+  is(tabpanel.querySelector(".editor-mount iframe") === null, true,
+    "The response editor doesn't have the intended visibility.");
+  is(tabpanel.querySelector(".response-image-box") === null, true,
+    "The response image box doesn't have the intended visibility.");
+
+  is(tabpanel.querySelectorAll(".tree-section").length, 1,
+    "There should be 1 tree sections displayed in this tabpanel.");
+  is(tabpanel.querySelectorAll(".treeRow:not(.tree-section)").length, 1,
+    "There should be 1 json properties displayed in this tabpanel.");
+  is(tabpanel.querySelectorAll(".empty-notice").length, 0,
+    "The empty notice should not be displayed in this tabpanel.");
+
+  let labels = tabpanel
+    .querySelectorAll("tr:not(.tree-section) .treeLabelCell .treeLabel");
+  let values = tabpanel
+    .querySelectorAll("tr:not(.tree-section) .treeValueCell .objectBox");
+
+  is(labels[0].textContent, "greeting",
+    "The first json property name was incorrect.");
+  is(values[0].textContent, "\"This is a base 64 string.\"",
+    "The first json property value was incorrect.");
+
+  yield teardown(monitor);
+});
--- a/devtools/client/netmonitor/test/head.js
+++ b/devtools/client/netmonitor/test/head.js
@@ -34,16 +34,17 @@ const POST_JSON_URL = EXAMPLE_URL + "htm
 const POST_RAW_URL = EXAMPLE_URL + "html_post-raw-test-page.html";
 const POST_RAW_WITH_HEADERS_URL = EXAMPLE_URL + "html_post-raw-with-headers-test-page.html";
 const PARAMS_URL = EXAMPLE_URL + "html_params-test-page.html";
 const JSONP_URL = EXAMPLE_URL + "html_jsonp-test-page.html";
 const JSON_LONG_URL = EXAMPLE_URL + "html_json-long-test-page.html";
 const JSON_MALFORMED_URL = EXAMPLE_URL + "html_json-malformed-test-page.html";
 const JSON_CUSTOM_MIME_URL = EXAMPLE_URL + "html_json-custom-mime-test-page.html";
 const JSON_TEXT_MIME_URL = EXAMPLE_URL + "html_json-text-mime-test-page.html";
+const JSON_B64_URL = EXAMPLE_URL + "html_json-b64.html";
 const SORTING_URL = EXAMPLE_URL + "html_sorting-test-page.html";
 const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html";
 const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html";
 const CUSTOM_GET_URL = EXAMPLE_URL + "html_custom-get-page.html";
 const SINGLE_GET_URL = EXAMPLE_URL + "html_single-get-page.html";
 const STATISTICS_URL = EXAMPLE_URL + "html_statistics-test-page.html";
 const CURL_URL = EXAMPLE_URL + "html_copy-as-curl.html";
 const CURL_UTILS_URL = EXAMPLE_URL + "html_curl-utils.html";
new file mode 100644
--- /dev/null
+++ b/devtools/client/netmonitor/test/html_json-b64.html
@@ -0,0 +1,38 @@
+<!-- Any copyright is dedicated to the Public Domain.
+     http://creativecommons.org/publicdomain/zero/1.0/ -->
+<!doctype html>
+
+<html>
+  <head>
+    <meta charset="utf-8"/>
+    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
+    <meta http-equiv="Pragma" content="no-cache" />
+    <meta http-equiv="Expires" content="0" />
+    <title>Network Monitor test page</title>
+  </head>
+
+  <body>
+    <p>JSON b64 test</p>
+
+    <script type="text/javascript">
+      function get(aAddress, aCallback) {
+        var xhr = new XMLHttpRequest();
+        xhr.open("GET", aAddress, true);
+
+        xhr.onreadystatechange = function() {
+          if (this.readyState == this.DONE) {
+            aCallback();
+          }
+        };
+        xhr.send(null);
+      }
+
+      function performRequests() {
+        get("sjs_content-type-test-server.sjs?fmt=json-b64", function() {
+          // Done.
+        });
+      }
+    </script>
+  </body>
+
+</html>
--- a/devtools/client/netmonitor/test/sjs_content-type-test-server.sjs
+++ b/devtools/client/netmonitor/test/sjs_content-type-test-server.sjs
@@ -132,16 +132,24 @@ function handleRequest(request, response
         let fun = (params.filter((s) => s.includes("jsonp="))[0] || "").split("=")[1];
         response.setStatusLine(request.httpVersion, status, "OK");
         response.setHeader("Content-Type", "text/json; charset=utf-8", false);
         setCacheHeaders();
         response.write(" " + fun + " ( { \"greeting\": \"Hello weird JSONP!\" } ) ; ");
         response.finish();
         break;
       }
+      case "json-b64": {
+        response.setStatusLine(request.httpVersion, status, "OK");
+        response.setHeader("Content-Type", "text/json; charset=utf-8", false);
+        setCacheHeaders();
+        response.write(btoa("{ \"greeting\": \"This is a base 64 string.\" }"));
+        response.finish();
+        break;
+      }
       case "json-long": {
         let str = "{ \"greeting\": \"Hello long string JSON!\" },";
         response.setStatusLine(request.httpVersion, status, "OK");
         response.setHeader("Content-Type", "text/json; charset=utf-8", false);
         setCacheHeaders();
         response.write("[" + new Array(2048).join(str).slice(0, -1) + "]");
         response.finish();
         break;
--- a/dom/base/Dispatcher.h
+++ b/dom/base/Dispatcher.h
@@ -3,52 +3,35 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Dispatcher_h
 #define mozilla_dom_Dispatcher_h
 
 #include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/TaskCategory.h"
 #include "nsISupports.h"
 
 class nsIEventTarget;
 class nsIRunnable;
 
+// This file defines basic functionality for dispatching runnables to various
+// groups: either the SystemGroup or a DocGroup or TabGroup. Ideally all
+// runnables destined for the main thread should be dispatched to a group
+// instead so that we know what kind of web content they'll be
+// touching. Runnables sent to the SystemGroup never touch web
+// content. Runnables sent to a DocGroup can only touch documents belonging to
+// that DocGroup. Runnables sent to a TabGroup can touch any document in any of
+// the tabs belonging to the TabGroup.
+
 namespace mozilla {
 class AbstractThread;
 namespace dom {
-
 class TabGroup;
-class DocGroup;
-
-enum class TaskCategory {
-  // User input (clicks, keypresses, etc.)
-  UI,
-
-  // Data from the network
-  Network,
-
-  // setTimeout, setInterval
-  Timer,
-
-  // Runnables posted from a worker to the main thread
-  Worker,
-
-  // requestIdleCallback
-  IdleCallback,
-
-  // Vsync notifications
-  RefreshDriver,
-
-  // Most DOM events (postMessage, media, plugins)
-  Other,
-
-  Count
-};
 
 // This trait should be attached to classes like nsIGlobalObject and nsIDocument
 // that have a DocGroup or TabGroup attached to them. The methods here should
 // delegate to the DocGroup or TabGroup. We can't use the Dispatcher class
 // directly because it inherits from nsISupports.
 class DispatcherTrait {
 public:
   // This method may or may not be safe off of the main thread. For nsIDocument
@@ -78,17 +61,17 @@ public:
   // This method is always safe to call off the main thread. The nsIEventTarget
   // can always be used off the main thread.
   virtual nsIEventTarget* EventTargetFor(TaskCategory aCategory) const = 0;
 
   // Must be called on the main thread. The AbstractThread can always be used
   // off the main thread.
   virtual AbstractThread* AbstractMainThreadFor(TaskCategory aCategory) = 0;
 
-  // These methods perform a safe cast. They return null if |this| is not of the
+  // This method performs a safe cast. It returns null if |this| is not of the
   // requested type.
   virtual TabGroup* AsTabGroup() { return nullptr; }
 
 protected:
   virtual already_AddRefed<nsIEventTarget>
   CreateEventTargetFor(TaskCategory aCategory);
 
   static Dispatcher* FromEventTarget(nsIEventTarget* aEventTarget);
--- a/dom/base/IdleRequest.h
+++ b/dom/base/IdleRequest.h
@@ -7,17 +7,21 @@
 #ifndef mozilla_dom_idlerequest_h
 #define mozilla_dom_idlerequest_h
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/Maybe.h"
 #include "nsCOMPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDOMNavigationTiming.h"
+#include "nsICancelableRunnable.h"
+#include "nsIIncrementalRunnable.h"
+#include "nsIRunnable.h"
 #include "nsITimeoutHandler.h"
+#include "nsString.h"
 
 class nsPIDOMWindowInner;
 
 namespace mozilla {
 namespace dom {
 
 class IdleRequestCallback;
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3008,17 +3008,17 @@ nsIDocument::EventTargetFor(TaskCategory
 {
   if (mDocGroup) {
     return mDocGroup->EventTargetFor(aCategory);
   }
   return DispatcherTrait::EventTargetFor(aCategory);
 }
 
 AbstractThread*
-nsIDocument::AbstractMainThreadFor(mozilla::dom::TaskCategory aCategory)
+nsIDocument::AbstractMainThreadFor(mozilla::TaskCategory aCategory)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mDocGroup) {
     return mDocGroup->AbstractMainThreadFor(aCategory);
   }
   return DispatcherTrait::AbstractMainThreadFor(aCategory);
 }
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1772,24 +1772,24 @@ private:
   mozilla::dom::TabGroup* TabGroupInner();
   mozilla::dom::TabGroup* TabGroupOuter();
 
   bool IsBackgroundInternal() const;
 
 public:
   // Dispatch a runnable related to the global.
   virtual nsresult Dispatch(const char* aName,
-                            mozilla::dom::TaskCategory aCategory,
+                            mozilla::TaskCategory aCategory,
                             already_AddRefed<nsIRunnable>&& aRunnable) override;
 
   virtual nsIEventTarget*
-  EventTargetFor(mozilla::dom::TaskCategory aCategory) const override;
+  EventTargetFor(mozilla::TaskCategory aCategory) const override;
 
   virtual mozilla::AbstractThread*
-  AbstractMainThreadFor(mozilla::dom::TaskCategory aCategory) override;
+  AbstractMainThreadFor(mozilla::TaskCategory aCategory) override;
 
 protected:
   // These members are only used on outer window objects. Make sure
   // you never set any of these on an inner object!
   bool                          mFullScreen : 1;
   bool                          mFullscreenMode : 1;
   bool                          mIsClosed : 1;
   bool                          mInClose : 1;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2871,24 +2871,24 @@ public:
     mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
   
   virtual void UpdateIntersectionObservations() = 0;
   virtual void ScheduleIntersectionObserverNotification() = 0;
   virtual void NotifyIntersectionObservers() = 0;
 
   // Dispatch a runnable related to the document.
   virtual nsresult Dispatch(const char* aName,
-                            mozilla::dom::TaskCategory aCategory,
+                            mozilla::TaskCategory aCategory,
                             already_AddRefed<nsIRunnable>&& aRunnable) override;
 
   virtual nsIEventTarget*
-  EventTargetFor(mozilla::dom::TaskCategory aCategory) const override;
+  EventTargetFor(mozilla::TaskCategory aCategory) const override;
 
   virtual mozilla::AbstractThread*
-  AbstractMainThreadFor(mozilla::dom::TaskCategory aCategory) override;
+  AbstractMainThreadFor(mozilla::TaskCategory aCategory) override;
 
   // The URLs passed to these functions should match what
   // JS::DescribeScriptedCaller() returns, since these APIs are used to
   // determine whether some code is being called from a tracking script.
   void NoteScriptTrackingStatus(const nsACString& aURL, bool isTracking);
   bool IsScriptTracking(const nsACString& aURL) const;
 
   bool PrerenderHref(nsIURI* aHref);
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -599,17 +599,17 @@ public:
   virtual nsresult MoveBy(int32_t aXDif, int32_t aYDif) = 0;
   virtual nsresult UpdateCommands(const nsAString& anAction, nsISelection* aSel, int16_t aReason) = 0;
 
   mozilla::dom::TabGroup* TabGroup();
 
   mozilla::dom::DocGroup* GetDocGroup() const;
 
   virtual nsIEventTarget*
-  EventTargetFor(mozilla::dom::TaskCategory aCategory) const = 0;
+  EventTargetFor(mozilla::TaskCategory aCategory) const = 0;
 
 protected:
   // The nsPIDOMWindow constructor. The aOuterWindow argument should
   // be null if and only if the created window itself is an outer
   // window. In all other cases aOuterWindow should be the outer
   // window for the inner window that is being created.
   explicit nsPIDOMWindow<T>(nsPIDOMWindowOuter *aOuterWindow);
 
--- a/dom/events/JSEventHandler.cpp
+++ b/dom/events/JSEventHandler.cpp
@@ -157,23 +157,24 @@ JSEventHandler::HandleEvent(nsIDOMEvent*
       scriptEvent->GetError(&error.Value());
     } else {
       msgOrEvent.SetAsEvent() = aEvent->InternalDOMEvent();
     }
 
     RefPtr<OnErrorEventHandlerNonNull> handler =
       mTypedHandler.OnErrorEventHandler();
     ErrorResult rv;
-    bool handled = handler->Call(mTarget, msgOrEvent, fileName, lineNumber,
-                                 columnNumber, error, rv);
+    JS::Rooted<JS::Value> retval(RootingCx());
+    handler->Call(mTarget, msgOrEvent, fileName, lineNumber,
+                  columnNumber, error, &retval, rv);
     if (rv.Failed()) {
       return rv.StealNSResult();
     }
 
-    if (handled) {
+    if (retval.isBoolean() && retval.toBoolean()) {
       event->PreventDefaultInternal(isChromeHandler);
     }
     return NS_OK;
   }
 
   if (mTypedHandler.Type() == TypedEventHandler::eOnBeforeUnload) {
     MOZ_ASSERT(mEventName == nsGkAtoms::onbeforeunload);
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4543,16 +4543,17 @@ nsresult HTMLMediaElement::InitializeDec
     return NS_ERROR_FAILURE;
 
   LOG(LogLevel::Debug, ("%p Cloned decoder %p from %p", this, decoder.get(), aOriginal));
 
   RefPtr<MediaResource> resource =
     originalResource->CloneData(decoder->GetResourceCallback());
 
   if (!resource) {
+    decoder->Shutdown();
     LOG(LogLevel::Debug, ("%p Failed to cloned stream for decoder %p", this, decoder.get()));
     return NS_ERROR_FAILURE;
   }
 
   return FinishDecoderSetup(decoder, resource, nullptr);
 }
 
 nsresult HTMLMediaElement::InitializeDecoderForChannel(nsIChannel* aChannel,
@@ -4582,18 +4583,20 @@ nsresult HTMLMediaElement::InitializeDec
     return NS_ERROR_FAILURE;
   }
 
   LOG(LogLevel::Debug, ("%p Created decoder %p for type %s", this, decoder.get(), mimeType.get()));
 
   RefPtr<MediaResource> resource =
     MediaResource::Create(decoder->GetResourceCallback(), aChannel);
 
-  if (!resource)
+  if (!resource) {
+    decoder->Shutdown();
     return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   if (mChannelLoader) {
     mChannelLoader->Done();
     mChannelLoader = nullptr;
   }
 
   return FinishDecoderSetup(decoder, resource, aListener);
 }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -758,18 +758,22 @@ protected:
   class MediaLoadListener;
   class MediaStreamTracksAvailableCallback;
   class MediaStreamTrackListener;
   class StreamListener;
   class StreamSizeListener;
   class ShutdownObserver;
 
   MediaDecoderOwner::NextFrameStatus NextFrameStatus();
+
   void SetDecoder(MediaDecoder* aDecoder) {
     MOZ_ASSERT(aDecoder); // Use ShutdownDecoder() to clear.
+    if (mDecoder) {
+      ShutdownDecoder();
+    }
     mDecoder = aDecoder;
   }
 
   class WakeLockBoolWrapper {
   public:
     explicit WakeLockBoolWrapper(bool val = false)
       : mValue(val), mCanPlay(true), mOuter(nullptr) {}
 
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -26,16 +26,17 @@
 #include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/VideoDecoderManagerChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ExternalHelperAppChild.h"
 #include "mozilla/dom/FlyWebPublishedServerIPC.h"
 #include "mozilla/dom/GetFilesHelper.h"
+#include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/PCrashReporterChild.h"
 #include "mozilla/dom/ProcessGlobal.h"
 #include "mozilla/dom/PushNotifier.h"
 #include "mozilla/dom/StorageIPC.h"
 #include "mozilla/dom/TabGroup.h"
 #include "mozilla/dom/workers/ServiceWorkerManager.h"
 #include "mozilla/dom/nsIContentChild.h"
 #include "mozilla/dom/URLClassifierChild.h"
@@ -129,17 +130,16 @@
 #include "base/message_loop.h"
 #include "base/process_util.h"
 #include "base/task.h"
 
 #include "nsChromeRegistryContent.h"
 #include "nsFrameMessageManager.h"
 
 #include "nsIGeolocationProvider.h"
-#include "mozilla/dom/PMemoryReportRequestChild.h"
 #include "mozilla/dom/PCycleCollectWithLogsChild.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsHostObjectProtocolHandler.h"
 
 #ifdef MOZ_WEBRTC
 #include "signaling/src/peerconnection/WebrtcGlobalChild.h"
 #endif
@@ -220,48 +220,16 @@ using namespace mozilla::widget;
 #if defined(MOZ_WIDGET_GONK)
 using namespace mozilla::system;
 #endif
 using namespace mozilla::widget;
 
 namespace mozilla {
 namespace dom {
 
-class MemoryReportRequestChild : public PMemoryReportRequestChild,
-                                 public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  MemoryReportRequestChild(bool aAnonymize,
-                           const MaybeFileDesc& aDMDFile);
-  NS_IMETHOD Run() override;
-
-private:
-  ~MemoryReportRequestChild() override;
-
-  bool     mAnonymize;
-  FileDescriptor mDMDFile;
-};
-
-NS_IMPL_ISUPPORTS(MemoryReportRequestChild, nsIRunnable)
-
-MemoryReportRequestChild::MemoryReportRequestChild(
-  bool aAnonymize, const MaybeFileDesc& aDMDFile)
-: mAnonymize(aAnonymize)
-{
-  if (aDMDFile.type() == MaybeFileDesc::TFileDescriptor) {
-    mDMDFile = aDMDFile.get_FileDescriptor();
-  }
-}
-
-MemoryReportRequestChild::~MemoryReportRequestChild()
-{
-}
-
 // IPC sender for remote GC/CC logging.
 class CycleCollectWithLogsChild final
   : public PCycleCollectWithLogsChild
   , public nsICycleCollectorLogSink
 {
 public:
   NS_DECL_ISUPPORTS
 
@@ -1044,147 +1012,31 @@ ContentChild::InitXPCOM()
   // The stylesheet cache is not ready yet. Store this URL for future use.
   nsCOMPtr<nsIURI> ucsURL = DeserializeURI(userContentSheetURL);
   nsLayoutStylesheetCache::SetUserContentCSSURL(ucsURL);
 
   // This will register cross-process observer.
   mozilla::dom::time::InitializeDateCacheCleaner();
 }
 
-PMemoryReportRequestChild*
-ContentChild::AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
-                                             const bool &aAnonymize,
-                                             const bool &aMinimizeMemoryUsage,
-                                             const MaybeFileDesc& aDMDFile)
-{
-  auto *actor =
-    new MemoryReportRequestChild(aAnonymize, aDMDFile);
-  actor->AddRef();
-  return actor;
-}
-
-class HandleReportCallback final : public nsIHandleReportCallback
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  explicit HandleReportCallback(MemoryReportRequestChild* aActor,
-                                const nsACString& aProcess)
-  : mActor(aActor)
-  , mProcess(aProcess)
-  { }
-
-  NS_IMETHOD Callback(const nsACString& aProcess, const nsACString &aPath,
-                      int32_t aKind, int32_t aUnits, int64_t aAmount,
-                      const nsACString& aDescription,
-                      nsISupports* aUnused) override
-  {
-    MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
-                           aAmount, nsCString(aDescription));
-    mActor->SendReport(memreport);
-    return NS_OK;
-  }
-private:
-  ~HandleReportCallback() = default;
-
-  RefPtr<MemoryReportRequestChild> mActor;
-  const nsCString mProcess;
-};
-
-NS_IMPL_ISUPPORTS(
-  HandleReportCallback
-, nsIHandleReportCallback
-)
-
-class FinishReportingCallback final : public nsIFinishReportingCallback
+mozilla::ipc::IPCResult
+ContentChild::RecvRequestMemoryReport(const uint32_t& aGeneration,
+                                      const bool& aAnonymize,
+                                      const bool& aMinimizeMemoryUsage,
+                                      const MaybeFileDesc& aDMDFile)
 {
-public:
-  NS_DECL_ISUPPORTS
-
-  explicit FinishReportingCallback(MemoryReportRequestChild* aActor)
-  : mActor(aActor)
-  {
-  }
-
-  NS_IMETHOD Callback(nsISupports* aUnused) override
-  {
-    bool sent = PMemoryReportRequestChild::Send__delete__(mActor);
-    return sent ? NS_OK : NS_ERROR_FAILURE;
-  }
-
-private:
-  ~FinishReportingCallback() = default;
-
-  RefPtr<MemoryReportRequestChild> mActor;
-};
-
-NS_IMPL_ISUPPORTS(
-  FinishReportingCallback
-, nsIFinishReportingCallback
-)
-
-mozilla::ipc::IPCResult
-ContentChild::RecvPMemoryReportRequestConstructor(
-  PMemoryReportRequestChild* aChild,
-  const uint32_t& aGeneration,
-  const bool& aAnonymize,
-  const bool& aMinimizeMemoryUsage,
-  const MaybeFileDesc& aDMDFile)
-{
-  MemoryReportRequestChild *actor =
-    static_cast<MemoryReportRequestChild*>(aChild);
-  DebugOnly<nsresult> rv;
-
-  if (aMinimizeMemoryUsage) {
-    nsCOMPtr<nsIMemoryReporterManager> mgr =
-      do_GetService("@mozilla.org/memory-reporter-manager;1");
-    rv = mgr->MinimizeMemoryUsage(actor);
-    // mgr will eventually call actor->Run()
-  } else {
-    rv = actor->Run();
-  }
-
-  // Bug 1295622: don't kill the process just because this failed.
-  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "actor operation failed");
+  nsCString process;
+  GetProcessName(process);
+  AppendProcessId(process);
+
+  MemoryReportRequestClient::Start(
+    aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, process);
   return IPC_OK();
 }
 
-NS_IMETHODIMP MemoryReportRequestChild::Run()
-{
-  ContentChild *child = static_cast<ContentChild*>(Manager());
-  nsCOMPtr<nsIMemoryReporterManager> mgr =
-    do_GetService("@mozilla.org/memory-reporter-manager;1");
-
-  nsCString process;
-  child->GetProcessName(process);
-  child->AppendProcessId(process);
-
-  // Run the reporters.  The callback will turn each measurement into a
-  // MemoryReport.
-  RefPtr<HandleReportCallback> handleReport =
-    new HandleReportCallback(this, process);
-  RefPtr<FinishReportingCallback> finishReporting =
-    new FinishReportingCallback(this);
-
-  nsresult rv =
-    mgr->GetReportsForThisProcessExtended(handleReport, nullptr, mAnonymize,
-                                          FileDescriptorToFILE(mDMDFile, "wb"),
-                                          finishReporting, nullptr);
-  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
-                       "GetReportsForThisProcessExtended failed");
-  return rv;
-}
-
-bool
-ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor)
-{
-  static_cast<MemoryReportRequestChild*>(actor)->Release();
-  return true;
-}
-
 PCycleCollectWithLogsChild*
 ContentChild::AllocPCycleCollectWithLogsChild(const bool& aDumpAllTraces,
                                               const FileDescriptor& aGCLog,
                                               const FileDescriptor& aCCLog)
 {
   auto* actor = new CycleCollectWithLogsChild(aGCLog, aCCLog);
   // Return actor with refcount 0, which is safe because it has a non-XPCOM type.
   return actor;
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -217,32 +217,16 @@ public:
   virtual bool DeallocPHalChild(PHalChild*) override;
 
   virtual PHeapSnapshotTempFileHelperChild*
   AllocPHeapSnapshotTempFileHelperChild() override;
 
   virtual bool
   DeallocPHeapSnapshotTempFileHelperChild(PHeapSnapshotTempFileHelperChild*) override;
 
-  virtual PMemoryReportRequestChild*
-  AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
-                                 const bool& aAnonymize,
-                                 const bool& aMinimizeMemoryUsage,
-                                 const MaybeFileDesc& aDMDFile) override;
-
-  virtual bool
-  DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) override;
-
-  virtual mozilla::ipc::IPCResult
-  RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* aChild,
-                                      const uint32_t& aGeneration,
-                                      const bool& aAnonymize,
-                                      const bool &aMinimizeMemoryUsage,
-                                      const MaybeFileDesc &aDMDFile) override;
-
   virtual PCycleCollectWithLogsChild*
   AllocPCycleCollectWithLogsChild(const bool& aDumpAllTraces,
                                   const FileDescriptor& aGCLog,
                                   const FileDescriptor& aCCLog) override;
 
   virtual bool
   DeallocPCycleCollectWithLogsChild(PCycleCollectWithLogsChild* aActor) override;
 
@@ -599,16 +583,23 @@ public:
 
   virtual mozilla::ipc::IPCResult
   RecvBlobURLRegistration(const nsCString& aURI, PBlobChild* aBlobChild,
                           const IPC::Principal& aPrincipal) override;
 
   virtual mozilla::ipc::IPCResult
   RecvBlobURLUnregistration(const nsCString& aURI) override;
 
+  mozilla::ipc::IPCResult
+  RecvRequestMemoryReport(
+          const uint32_t& generation,
+          const bool& anonymize,
+          const bool& minimizeMemoryUsage,
+          const MaybeFileDesc& DMDFile) override;
+
 #if defined(XP_WIN) && defined(ACCESSIBILITY)
   bool
   SendGetA11yContentId();
 #endif // defined(XP_WIN) && defined(ACCESSIBILITY)
 
   // Get a reference to the font family list passed from the chrome process,
   // for use during gfx initialization.
   InfallibleTArray<mozilla::dom::FontFamilyListEntry>&
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -41,21 +41,21 @@
 #include "mozilla/devtools/HeapSnapshotTempFileHelperParent.h"
 #include "mozilla/docshell/OfflineCacheUpdateParent.h"
 #include "mozilla/dom/DataTransfer.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/GetFilesHelper.h"
 #include "mozilla/dom/GeolocationBinding.h"
+#include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/dom/Notification.h"
 #include "mozilla/dom/PContentBridgeParent.h"
 #include "mozilla/dom/PContentPermissionRequestParent.h"
 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
-#include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/ServiceWorkerRegistrar.h"
 #include "mozilla/dom/StorageIPC.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/Permissions.h"
 #include "mozilla/dom/PresentationParent.h"
 #include "mozilla/dom/PPresentationParent.h"
 #include "mozilla/dom/PushNotifier.h"
@@ -291,81 +291,16 @@ struct nsIConsoleService::COMTypeInfo<ns
 const nsIID nsIConsoleService::COMTypeInfo<nsConsoleService, void>::kIID = NS_ICONSOLESERVICE_IID;
 
 namespace mozilla {
 namespace dom {
 
 #define NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC "ipc:network:set-offline"
 #define NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC "ipc:network:set-connectivity"
 
-class MemoryReportRequestParent : public PMemoryReportRequestParent
-{
-public:
-  explicit MemoryReportRequestParent(uint32_t aGeneration);
-
-  virtual ~MemoryReportRequestParent();
-
-  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
-
-  virtual mozilla::ipc::IPCResult RecvReport(const MemoryReport& aReport) override;
-  virtual mozilla::ipc::IPCResult Recv__delete__() override;
-
-private:
-  const uint32_t mGeneration;
-  // Non-null if we haven't yet called EndProcessReport() on it.
-  RefPtr<nsMemoryReporterManager> mReporterManager;
-
-  ContentParent* Owner()
-  {
-    return static_cast<ContentParent*>(Manager());
-  }
-};
-
-MemoryReportRequestParent::MemoryReportRequestParent(uint32_t aGeneration)
-  : mGeneration(aGeneration)
-{
-  MOZ_COUNT_CTOR(MemoryReportRequestParent);
-  mReporterManager = nsMemoryReporterManager::GetOrCreate();
-  NS_WARNING_ASSERTION(mReporterManager, "GetOrCreate failed");
-}
-
-mozilla::ipc::IPCResult
-MemoryReportRequestParent::RecvReport(const MemoryReport& aReport)
-{
-  if (mReporterManager) {
-    mReporterManager->HandleChildReport(mGeneration, aReport);
-  }
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-MemoryReportRequestParent::Recv__delete__()
-{
-  // Notifying the reporter manager is done in ActorDestroy, because
-  // it needs to happen even if the child process exits mid-report.
-  // (The reporter manager will time out eventually, but let's avoid
-  // that if possible.)
-  return IPC_OK();
-}
-
-void
-MemoryReportRequestParent::ActorDestroy(ActorDestroyReason aWhy)
-{
-  if (mReporterManager) {
-    mReporterManager->EndProcessReport(mGeneration, aWhy == Deletion);
-    mReporterManager = nullptr;
-  }
-}
-
-MemoryReportRequestParent::~MemoryReportRequestParent()
-{
-  MOZ_ASSERT(!mReporterManager);
-  MOZ_COUNT_DTOR(MemoryReportRequestParent);
-}
-
 // IPC receiver for remote GC/CC logging.
 class CycleCollectWithLogsParent final : public PCycleCollectWithLogsParent
 {
 public:
   ~CycleCollectWithLogsParent()
   {
     MOZ_COUNT_DTOR(CycleCollectWithLogsParent);
   }
@@ -2830,32 +2765,49 @@ ContentParent::AllocPHeapSnapshotTempFil
 bool
 ContentParent::DeallocPHeapSnapshotTempFileHelperParent(
   devtools::PHeapSnapshotTempFileHelperParent* aHeapSnapshotHelper)
 {
   delete aHeapSnapshotHelper;
   return true;
 }
 
-PMemoryReportRequestParent*
-ContentParent::AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
-                                               const bool &aAnonymize,
-                                               const bool &aMinimizeMemoryUsage,
-                                               const MaybeFileDesc &aDMDFile)
-{
-  MemoryReportRequestParent* parent =
-    new MemoryReportRequestParent(aGeneration);
-  return parent;
-}
-
 bool
-ContentParent::DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor)
-{
-  delete actor;
-  return true;
+ContentParent::SendRequestMemoryReport(const uint32_t& aGeneration,
+                                       const bool& aAnonymize,
+                                       const bool& aMinimizeMemoryUsage,
+                                       const MaybeFileDesc& aDMDFile)
+{
+  // This automatically cancels the previous request.
+  mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
+  Unused << PContentParent::SendRequestMemoryReport(
+    aGeneration,
+    aAnonymize,
+    aMinimizeMemoryUsage,
+    aDMDFile);
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+ContentParent::RecvAddMemoryReport(const MemoryReport& aReport)
+{
+  if (mMemoryReportRequest) {
+    mMemoryReportRequest->RecvReport(aReport);
+  }
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+ContentParent::RecvFinishMemoryReport(const uint32_t& aGeneration)
+{
+  if (mMemoryReportRequest) {
+    mMemoryReportRequest->Finish(aGeneration);
+    mMemoryReportRequest = nullptr;
+  }
+  return IPC_OK();
 }
 
 PCycleCollectWithLogsParent*
 ContentParent::AllocPCycleCollectWithLogsParent(const bool& aDumpAllTraces,
                                                 const FileDescriptor& aGCLog,
                                                 const FileDescriptor& aCCLog)
 {
   MOZ_CRASH("Don't call this; use ContentParent::CycleCollectWithLogs");
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -11,16 +11,17 @@
 #include "mozilla/dom/nsIContentParent.h"
 #include "mozilla/gfx/gfxVarReceiver.h"
 #include "mozilla/gfx/GPUProcessListener.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/HalTypes.h"
 #include "mozilla/LinkedList.h"
+#include "mozilla/MemoryReportingProcess.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/UniquePtr.h"
 
 #include "nsDataHashtable.h"
 #include "nsFrameMessageManager.h"
 #include "nsHashKeys.h"
 #include "nsIObserver.h"
@@ -90,25 +91,27 @@ namespace dom {
 class Element;
 class TabParent;
 class PStorageParent;
 class ClonedMessageData;
 class MemoryReport;
 class TabContext;
 class ContentBridgeParent;
 class GetFilesHelper;
+class MemoryReportRequestHost;
 
 class ContentParent final : public PContentParent
                           , public nsIContentParent
                           , public nsIObserver
                           , public nsIDOMGeoPositionCallback
                           , public nsIDOMGeoPositionErrorCallback
                           , public gfx::gfxVarReceiver
                           , public mozilla::LinkedListElement<ContentParent>
                           , public gfx::GPUProcessListener
+                          , public mozilla::MemoryReportingProcess
 {
   typedef mozilla::ipc::GeckoChildProcessHost GeckoChildProcessHost;
   typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
   typedef mozilla::ipc::PFileDescriptorSetParent PFileDescriptorSetParent;
   typedef mozilla::ipc::TestShellParent TestShellParent;
   typedef mozilla::ipc::URIParams URIParams;
   typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
   typedef mozilla::dom::ClonedMessageData ClonedMessageData;
@@ -317,17 +320,17 @@ public:
   DeallocateTabId(const TabId& aTabId,
                   const ContentParentId& aCpId,
                   bool aMarkedDestroying);
 
   void ReportChildAlreadyBlocked();
 
   bool RequestRunToCompletion();
 
-  bool IsAlive() const;
+  bool IsAlive() const override;
 
   virtual bool IsForBrowser() const override
   {
     return mIsForBrowser;
   }
 
   GeckoChildProcessHost* Process() const
   {
@@ -723,16 +726,20 @@ private:
                                 InfallibleTArray<nsString>* dictionaries,
                                 ClipboardCapabilities* clipboardCaps,
                                 DomainPolicyClone* domainPolicy,
                                 StructuredCloneData* initialData,
                                 InfallibleTArray<FontFamilyListEntry>* fontFamilies,
                                 OptionalURIParams* aUserContentSheetURL,
                                 nsTArray<LookAndFeelInt>* aLookAndFeelIntCache) override;
 
+
+  mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
+  mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
+
   virtual bool
   DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) override;
 
   virtual bool
   DeallocPRemoteSpellcheckEngineParent(PRemoteSpellcheckEngineParent*) override;
 
   virtual PBrowserParent* AllocPBrowserParent(const TabId& aTabId,
                                               const IPCTabContext& aContext,
@@ -782,25 +789,16 @@ private:
                                                                  const bool& aActive,
                                                                  const bool& aHSTSPriming) override;
 
   virtual bool DeallocPHalParent(PHalParent*) override;
 
   virtual bool
   DeallocPHeapSnapshotTempFileHelperParent(PHeapSnapshotTempFileHelperParent*) override;
 
-  virtual PMemoryReportRequestParent*
-  AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
-                                  const bool &aAnonymize,
-                                  const bool &aMinimizeMemoryUsage,
-                                  const MaybeFileDesc &aDMDFile) override;
-
-  virtual bool
-  DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) override;
-
   virtual PCycleCollectWithLogsParent*
   AllocPCycleCollectWithLogsParent(const bool& aDumpAllTraces,
                                    const FileDescriptor& aGCLog,
                                    const FileDescriptor& aCCLog) override;
 
   virtual bool
   DeallocPCycleCollectWithLogsParent(PCycleCollectWithLogsParent* aActor) override;
 
@@ -1082,16 +1080,21 @@ private:
   virtual mozilla::ipc::IPCResult RecvUpdateChildScalars(
     InfallibleTArray<ScalarAction>&& aScalarActions) override;
   virtual mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars(
     InfallibleTArray<KeyedScalarAction>&& aScalarActions) override;
 public:
   void SendGetFilesResponseAndForget(const nsID& aID,
                                      const GetFilesResponseResult& aResult);
 
+  bool SendRequestMemoryReport(const uint32_t& aGeneration,
+                               const bool& aAnonymize,
+                               const bool& aMinimizeMemoryUsage,
+                               const MaybeFileDesc& aDMDFile) override;
+
 private:
 
   // If you add strong pointers to cycle collected objects here, be sure to
   // release these objects in ShutDownProcess.  See the comment there for more
   // details.
 
   GeckoChildProcessHost* mSubprocess;
   const TimeStamp mLaunchTS; // used to calculate time to start content process
@@ -1146,16 +1149,17 @@ private:
   PProcessHangMonitorParent* mHangMonitorActor;
 
 #ifdef MOZ_GECKO_PROFILER
   RefPtr<mozilla::ProfileGatherer> mGatherer;
 #endif
   nsCString mProfile;
 
   UniquePtr<gfx::DriverCrashGuard> mDriverCrashGuard;
+  UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
 
 #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
   mozilla::UniquePtr<SandboxBroker> mSandboxBroker;
   static mozilla::UniquePtr<SandboxBrokerPolicyFactory>
       sSandboxBrokerPolicyFactory;
 #endif
 
 #ifdef NS_PRINTING
new file mode 100644
--- /dev/null
+++ b/dom/ipc/MemoryReportRequest.cpp
@@ -0,0 +1,205 @@
+/* -*- 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/. */
+
+#include "MemoryReportRequest.h"
+#include "mozilla/Unused.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/gfx/GPUParent.h"
+
+namespace mozilla {
+namespace dom {
+
+MemoryReportRequestHost::MemoryReportRequestHost(uint32_t aGeneration)
+  : mGeneration(aGeneration),
+    mSuccess(false)
+{
+  MOZ_COUNT_CTOR(MemoryReportRequestHost);
+  mReporterManager = nsMemoryReporterManager::GetOrCreate();
+  NS_WARNING_ASSERTION(mReporterManager, "GetOrCreate failed");
+}
+
+void
+MemoryReportRequestHost::RecvReport(const MemoryReport& aReport)
+{
+  // Skip reports from older generations. We need to do this here since we
+  // could receive older reports from a subprocesses before it acknowledges
+  // a new request, and we only track one active request per process.
+  if (aReport.generation() != mGeneration) {
+    return;
+  }
+
+  if (mReporterManager) {
+    mReporterManager->HandleChildReport(mGeneration, aReport);
+  }
+}
+
+void
+MemoryReportRequestHost::Finish(uint32_t aGeneration)
+{
+  // Skip reports from older generations. See the comment in RecvReport.
+  if (mGeneration != aGeneration) {
+    return;
+  }
+  mSuccess = true;
+}
+
+MemoryReportRequestHost::~MemoryReportRequestHost()
+{
+  MOZ_COUNT_DTOR(MemoryReportRequestHost);
+
+  if (mReporterManager) {
+    mReporterManager->EndProcessReport(mGeneration, mSuccess);
+    mReporterManager = nullptr;
+  }
+}
+
+NS_IMPL_ISUPPORTS(MemoryReportRequestClient, nsIRunnable)
+
+/* static */ void
+MemoryReportRequestClient::Start(uint32_t aGeneration,
+                                 bool aAnonymize,
+                                 bool aMinimizeMemoryUsage,
+                                 const MaybeFileDesc& aDMDFile,
+                                 const nsACString& aProcessString)
+{
+  RefPtr<MemoryReportRequestClient> request = new MemoryReportRequestClient(
+    aGeneration,
+    aAnonymize,
+    aDMDFile,
+    aProcessString);
+
+  DebugOnly<nsresult> rv;
+  if (aMinimizeMemoryUsage) {
+    nsCOMPtr<nsIMemoryReporterManager> mgr =
+      do_GetService("@mozilla.org/memory-reporter-manager;1");
+    rv = mgr->MinimizeMemoryUsage(request);
+    // mgr will eventually call actor->Run()
+  } else {
+    rv = request->Run();
+  }
+
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "actor operation failed");
+}
+
+MemoryReportRequestClient::MemoryReportRequestClient(uint32_t aGeneration,
+                                                     bool aAnonymize,
+                                                     const MaybeFileDesc& aDMDFile,
+                                                     const nsACString& aProcessString)
+ : mGeneration(aGeneration),
+   mAnonymize(aAnonymize),
+   mProcessString(aProcessString)
+{
+  if (aDMDFile.type() == MaybeFileDesc::TFileDescriptor) {
+    mDMDFile = aDMDFile.get_FileDescriptor();
+  }
+}
+
+MemoryReportRequestClient::~MemoryReportRequestClient()
+{
+}
+
+class HandleReportCallback final : public nsIHandleReportCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  explicit HandleReportCallback(uint32_t aGeneration,
+                                const nsACString& aProcess)
+  : mGeneration(aGeneration)
+  , mProcess(aProcess)
+  { }
+
+  NS_IMETHOD Callback(const nsACString& aProcess, const nsACString &aPath,
+                      int32_t aKind, int32_t aUnits, int64_t aAmount,
+                      const nsACString& aDescription,
+                      nsISupports* aUnused) override
+  {
+    MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
+                           aAmount, mGeneration, nsCString(aDescription));
+    switch (XRE_GetProcessType()) {
+      case GeckoProcessType_Content:
+        ContentChild::GetSingleton()->SendAddMemoryReport(memreport);
+        break;
+      case GeckoProcessType_GPU:
+        Unused << gfx::GPUParent::GetSingleton()->SendAddMemoryReport(memreport);
+        break;
+      default:
+        MOZ_ASSERT_UNREACHABLE("Unhandled process type");
+    }
+    return NS_OK;
+  }
+private:
+  ~HandleReportCallback() = default;
+
+  uint32_t mGeneration;
+  const nsCString mProcess;
+};
+
+NS_IMPL_ISUPPORTS(
+  HandleReportCallback
+, nsIHandleReportCallback
+)
+
+class FinishReportingCallback final : public nsIFinishReportingCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  explicit FinishReportingCallback(uint32_t aGeneration)
+  : mGeneration(aGeneration)
+  {
+  }
+
+  NS_IMETHOD Callback(nsISupports* aUnused) override
+  {
+    bool sent = false;
+    switch (XRE_GetProcessType()) {
+      case GeckoProcessType_Content:
+        sent = ContentChild::GetSingleton()->SendFinishMemoryReport(mGeneration);
+        break;
+      case GeckoProcessType_GPU:
+        sent = gfx::GPUParent::GetSingleton()->SendFinishMemoryReport(mGeneration);
+        break;
+      default:
+        MOZ_ASSERT_UNREACHABLE("Unhandled process type");
+    }
+    return sent ? NS_OK : NS_ERROR_FAILURE;
+  }
+
+private:
+  ~FinishReportingCallback() = default;
+
+  uint32_t mGeneration;
+};
+
+NS_IMPL_ISUPPORTS(
+  FinishReportingCallback
+, nsIFinishReportingCallback
+)
+
+NS_IMETHODIMP MemoryReportRequestClient::Run()
+{
+  nsCOMPtr<nsIMemoryReporterManager> mgr =
+    do_GetService("@mozilla.org/memory-reporter-manager;1");
+
+  // Run the reporters.  The callback will turn each measurement into a
+  // MemoryReport.
+  RefPtr<HandleReportCallback> handleReport =
+    new HandleReportCallback(mGeneration, mProcessString);
+  RefPtr<FinishReportingCallback> finishReporting =
+    new FinishReportingCallback(mGeneration);
+
+  nsresult rv =
+    mgr->GetReportsForThisProcessExtended(handleReport, nullptr, mAnonymize,
+                                          FileDescriptorToFILE(mDMDFile, "wb"),
+                                          finishReporting, nullptr);
+  NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
+                       "GetReportsForThisProcessExtended failed");
+  return rv;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/ipc/MemoryReportRequest.h
@@ -0,0 +1,68 @@
+/* -*- 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/. */
+
+#ifndef mozilla_dom_MemoryReportRequest_h_
+#define mozilla_dom_MemoryReportRequest_h_
+
+#include "mozilla/dom/MemoryReportTypes.h"
+#include "mozilla/ipc/FileDescriptor.h"
+#include "nsISupports.h"
+
+class nsMemoryReporterManager;
+
+namespace mozilla {
+namespace dom {
+
+class MaybeFileDesc;
+
+class MemoryReportRequestHost final
+{
+public:
+  explicit MemoryReportRequestHost(uint32_t aGeneration);
+  ~MemoryReportRequestHost();
+
+  void RecvReport(const MemoryReport& aReport);
+  void Finish(uint32_t aGeneration);
+
+private:
+  const uint32_t mGeneration;
+  // Non-null if we haven't yet called EndProcessReport() on it.
+  RefPtr<nsMemoryReporterManager> mReporterManager;
+  bool mSuccess;
+};
+
+class MemoryReportRequestClient final : public nsIRunnable
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  static void Start(uint32_t aGeneration,
+                    bool aAnonymize,
+                    bool aMinimizeMemoryUsage,
+                    const MaybeFileDesc& aDMDFile,
+                    const nsACString& aProcessString);
+
+  NS_IMETHOD Run() override;
+
+private:
+  MemoryReportRequestClient(uint32_t aGeneration,
+                            bool aAnonymize,
+                            const MaybeFileDesc& aDMDFile,
+                            const nsACString& aProcessString);
+
+private:
+  ~MemoryReportRequestClient();
+
+  uint32_t mGeneration;
+  bool mAnonymize;
+  mozilla::ipc::FileDescriptor mDMDFile;
+  nsCString mProcessString;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_MemoryReportRequest_h_
rename from dom/ipc/PMemoryReportRequest.ipdl
rename to dom/ipc/MemoryReportTypes.ipdlh
--- a/dom/ipc/PMemoryReportRequest.ipdl
+++ b/dom/ipc/MemoryReportTypes.ipdlh
@@ -1,29 +1,27 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-include protocol PContent;
+using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace dom {
 
 struct MemoryReport {
   nsCString process;
   nsCString path;
   int32_t kind;
   int32_t units;
   int64_t amount;
+  uint32_t generation;
   nsCString desc;
 };
 
-protocol PMemoryReportRequest {
-  manager PContent;
-
-parent:
-  async Report(MemoryReport aReport);
-  async __delete__();
+union MaybeFileDesc {
+    FileDescriptor;
+    void_t;
 };
 
 }
 }
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -17,17 +17,16 @@ include protocol PExternalHelperApp;
 include protocol PHandlerService;
 include protocol PDeviceStorageRequest;
 include protocol PFileDescriptorSet;
 include protocol PHal;
 include protocol PHeapSnapshotTempFileHelper;
 include protocol PProcessHangMonitor;
 include protocol PImageBridge;
 include protocol PMedia;
-include protocol PMemoryReportRequest;
 include protocol PNecko;
 include protocol PGMPContent;
 include protocol PGMPService;
 include protocol PPluginModule;
 include protocol PGMP;
 include protocol PPrinting;
 include protocol PSendStream;
 include protocol POfflineCacheUpdate;
@@ -52,16 +51,17 @@ include PTabContext;
 include URIParams;
 include PluginTypes;
 include ProtocolTypes;
 include PBackgroundSharedTypes;
 include PContentPermission;
 include ServiceWorkerConfiguration;
 include GraphicsMessages;
 include ProfilerTypes;
+include MemoryReportTypes;
 
 // Workaround to prevent error if PContentChild.cpp & PContentBridgeParent.cpp
 // are put into different UnifiedProtocolsXX.cpp files.
 // XXX Remove this once bug 1069073 is fixed
 include "mozilla/dom/PContentBridgeParent.h";
 
 using GeoPosition from "nsGeoPositionIPCSerialiser.h";
 using AlertNotificationType from "mozilla/AlertNotificationIPCSerializer.h";
@@ -69,17 +69,16 @@ using AlertNotificationType from "mozill
 using struct ChromePackage from "mozilla/chrome/RegistryMessageUtils.h";
 using struct SubstitutionMapping from "mozilla/chrome/RegistryMessageUtils.h";
 using struct OverrideMapping from "mozilla/chrome/RegistryMessageUtils.h";
 using base::ChildPrivileges from "base/process_util.h";
 using base::ProcessId from "base/process.h";
 using struct IPC::Permission from "mozilla/net/NeckoMessageUtils.h";
 using class IPC::Principal from "mozilla/dom/PermissionMessageUtils.h";
 using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
-using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 using mozilla::hal::ProcessPriority from "mozilla/HalTypes.h";
 using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
 using mozilla::dom::TabId from "mozilla/dom/ipc/IdType.h";
 using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
 using mozilla::LayoutDeviceIntPoint from "Units.h";
 using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
 using class mozilla::dom::MessagePort from "mozilla/dom/MessagePort.h";
@@ -262,21 +261,16 @@ struct DataStorageItem {
   DataStorageType type;
 };
 
 struct ClipboardCapabilities {
   bool supportsSelectionClipboard;
   bool supportsFindClipboard;
 };
 
-union MaybeFileDesc {
-    FileDescriptor;
-    void_t;
-};
-
 union FileDescOrError {
     FileDescriptor;
     nsresult;
 };
 
 struct DomainPolicyClone
 {
     bool        active;
@@ -366,17 +360,16 @@ nested(upto inside_cpow) sync protocol P
     manages PDeviceStorageRequest;
     manages PPSMContentDownloader;
     manages PExternalHelperApp;
     manages PFileDescriptorSet;
     manages PHal;
     manages PHandlerService;
     manages PHeapSnapshotTempFileHelper;
     manages PMedia;
-    manages PMemoryReportRequest;
     manages PNecko;
     manages POfflineCacheUpdate;
     manages PPrinting;
     manages PSendStream;
     manages PScreenManager;
     manages PSpeechSynthesis;
     manages PStorage;
     manages PTestShell;
@@ -443,18 +436,20 @@ child:
 
     /**
      * Enable system-level sandboxing features, if available.  Can
      * usually only be performed zero or one times.  The child may
      * abnormally exit if this fails; the details are OS-specific.
      */
     async SetProcessSandbox(MaybeFileDesc aBroker);
 
-    async PMemoryReportRequest(uint32_t generation, bool anonymize,
-                               bool minimizeMemoryUsage, MaybeFileDesc DMDFile);
+    async RequestMemoryReport(uint32_t generation,
+                              bool anonymize,
+                              bool minimizeMemoryUsage,
+                              MaybeFileDesc DMDFile);
 
     /**
      * Communication between the PuppetBidiKeyboard and the actual
      * BidiKeyboard hosted by the parent
      */
     async BidiKeyboardNotify(bool isLangRTL, bool haveBidiKeyboards);
 
     /**
@@ -1159,16 +1154,19 @@ parent:
      */
     async AccumulateChildHistogram(Accumulation[] accumulations);
     async AccumulateChildKeyedHistogram(KeyedAccumulation[] accumulations);
     async UpdateChildScalars(ScalarAction[] updates);
     async UpdateChildKeyedScalars(KeyedScalarAction[] updates);
 
     sync GetA11yContentId() returns (uint32_t aContentId);
 
+    async AddMemoryReport(MemoryReport aReport);
+    async FinishMemoryReport(uint32_t aGeneration);
+
 both:
      async AsyncMessage(nsString aMessage, CpowEntry[] aCpows,
                         Principal aPrincipal, ClonedMessageData aData);
 
     /**
      * Notify `push-subscription-modified` observers in the parent and child.
      */
     async NotifyPushSubscriptionModifiedObservers(nsCString scope,
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2727,21 +2727,17 @@ TabChild::MakeVisible()
 
 void
 TabChild::MakeHidden()
 {
   if (mPuppetWidget && !mPuppetWidget->IsVisible()) {
     return;
   }
 
-  CompositorBridgeChild* compositor = CompositorBridgeChild::Get();
-
-  // Clear cached resources directly. This avoids one extra IPC
-  // round-trip from CompositorBridgeChild to CompositorBridgeParent.
-  compositor->RecvClearCachedResources(mLayersId);
+  ClearCachedResources();
 
   // Hide all plugins in this tab.
   if (nsCOMPtr<nsIPresShell> shell = GetPresShell()) {
     if (nsPresContext* presContext = shell->GetPresContext()) {
       nsRootPresContext* rootPresContext = presContext->GetRootPresContext();
       nsIFrame* rootFrame = shell->FrameConstructor()->GetRootFrame();
       rootPresContext->ComputePluginGeometryUpdates(rootFrame, nullptr, nullptr);
       rootPresContext->ApplyPluginGeometryUpdates();
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -21,16 +21,17 @@ EXPORTS.mozilla.dom += [
     'ContentChild.h',
     'ContentParent.h',
     'ContentProcess.h',
     'ContentProcessManager.h',
     'CPOWManagerGetter.h',
     'CrashReporterChild.h',
     'CrashReporterParent.h',
     'FilePickerParent.h',
+    'MemoryReportRequest.h',
     'nsIContentChild.h',
     'nsIContentParent.h',
     'PermissionMessageUtils.h',
     'TabChild.h',
     'TabContext.h',
     'TabMessageUtils.h',
     'TabParent.h',
     'URLClassifierChild.h',
@@ -48,16 +49,17 @@ UNIFIED_SOURCES += [
     'ContentBridgeChild.cpp',
     'ContentBridgeParent.cpp',
     'ContentParent.cpp',
     'ContentProcess.cpp',
     'ContentProcessManager.cpp',
     'CrashReporterParent.cpp',
     'DatePickerParent.cpp',
     'FilePickerParent.cpp',
+    'MemoryReportRequest.cpp',
     'nsIContentChild.cpp',
     'nsIContentParent.cpp',
     'PermissionMessageUtils.cpp',
     'ProcessPriorityManager.cpp',
     'ScreenManagerParent.cpp',
     'StructuredCloneData.cpp',
     'TabChild.cpp',
     'TabContext.cpp',
@@ -73,29 +75,29 @@ UNIFIED_SOURCES += [
 SOURCES += [
     'ContentChild.cpp',
     'CrashReporterChild.cpp',
     'ProcessHangMonitor.cpp',
 ]
 
 IPDL_SOURCES += [
     'DOMTypes.ipdlh',
+    'MemoryReportTypes.ipdlh',
     'PBrowser.ipdl',
     'PBrowserOrId.ipdlh',
     'PColorPicker.ipdl',
     'PContent.ipdl',
     'PContentBridge.ipdl',
     'PContentPermission.ipdlh',
     'PContentPermissionRequest.ipdl',
     'PCrashReporter.ipdl',
     'PCycleCollectWithLogs.ipdl',
     'PDatePicker.ipdl',
     'PDocumentRenderer.ipdl',
     'PFilePicker.ipdl',
-    'PMemoryReportRequest.ipdl',
     'PPluginWidget.ipdl',
     'PProcessHangMonitor.ipdl',
     'PScreenManager.ipdl',
     'PTabContext.ipdlh',
     'PURLClassifier.ipdl',
     'ServiceWorkerConfiguration.ipdlh',
 ]
 
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1078,17 +1078,17 @@ public:
         mAudioDevice->GetMediaSource() == MediaSourceEnum::AudioCapture) {
       // It should be possible to pipe the capture stream to anything. CORS is
       // not a problem here, we got explicit user content.
       nsCOMPtr<nsIPrincipal> principal = window->GetExtantDoc()->NodePrincipal();
       domStream =
         DOMMediaStream::CreateAudioCaptureStreamAsInput(window, principal, msg);
 
       stream = msg->CreateSourceStream(
-        globalWindow->AbstractMainThreadFor(dom::TaskCategory::Other)); // Placeholder
+        globalWindow->AbstractMainThreadFor(TaskCategory::Other)); // Placeholder
       msg->RegisterCaptureStreamForWindow(
             mWindowID, domStream->GetInputStream()->AsProcessedStream());
       window->SetAudioCapture(true);
     } else {
       class LocalTrackSource : public MediaStreamTrackSource
       {
       public:
         LocalTrackSource(nsIPrincipal* aPrincipal,
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -633,24 +633,24 @@ MediaKeySession::MakePromise(ErrorResult
     NS_WARNING("Passed non-global to MediaKeys ctor!");
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
   return DetailedPromise::Create(global, aRv, aName);
 }
 
 void
-MediaKeySession::SetExpiration(double aSecondsSinceEpoch)
+MediaKeySession::SetExpiration(double aExpiration)
 {
   EME_LOG("MediaKeySession[%p,'%s'] SetExpiry(%.12lf) (%.2lf hours from now)",
           this,
           NS_ConvertUTF16toUTF8(mSessionId).get(),
-          aSecondsSinceEpoch,
-          aSecondsSinceEpoch - double(time(0)) / (60 * 60));
-  mExpiration = aSecondsSinceEpoch;
+          aExpiration,
+          (aExpiration - 1000.0 * double(time(0))) / (1000.0 * 60 * 60));
+  mExpiration = aExpiration;
 }
 
 EventHandlerNonNull*
 MediaKeySession::GetOnkeystatuseschange()
 {
   return GetEventHandler(nsGkAtoms::onkeystatuseschange, EmptyString());
 }
 
--- a/dom/media/fmp4/MP4Decoder.cpp
+++ b/dom/media/fmp4/MP4Decoder.cpp
@@ -247,17 +247,17 @@ MP4Decoder::IsVideoAccelerated(layers::K
   if (!decoder) {
     taskQueue->BeginShutdown();
     taskQueue->AwaitShutdownAndIdle();
     promise->MaybeResolve(NS_LITERAL_STRING("No; Failed to create H264 decoder"));
     return promise.forget();
   }
 
   decoder->Init()
-    ->Then(aParent->AbstractMainThreadFor(dom::TaskCategory::Other),
+    ->Then(aParent->AbstractMainThreadFor(TaskCategory::Other),
            __func__,
            [promise, decoder, taskQueue] (TrackInfo::TrackType aTrack) {
              nsCString failureReason;
              bool ok = decoder->IsHardwareAccelerated(failureReason);
              nsAutoString result;
              if (ok) {
                result.AssignLiteral("Yes");
              } else {
--- a/dom/media/gmp/GMPDecryptorChild.cpp
+++ b/dom/media/gmp/GMPDecryptorChild.cpp
@@ -120,21 +120,20 @@ GMPDecryptorChild::SessionMessage(const 
   CALL_ON_GMP_THREAD(SendSessionMessage,
                      nsCString(aSessionId, aSessionIdLength),
                      aMessageType, Move(msg));
 }
 
 void
 GMPDecryptorChild::ExpirationChange(const char* aSessionId,
                                     uint32_t aSessionIdLength,
-                                    GMPTimestamp aMillisecondsSinceEpoch)
+                                    GMPTimestamp aExpiryTime)
 {
   CALL_ON_GMP_THREAD(SendExpirationChange,
-                     nsCString(aSessionId, aSessionIdLength),
-                     aMillisecondsSinceEpoch / 1e3);
+                     nsCString(aSessionId, aSessionIdLength), aExpiryTime);
 }
 
 void
 GMPDecryptorChild::SessionClosed(const char* aSessionId,
                                  uint32_t aSessionIdLength)
 {
   CALL_ON_GMP_THREAD(SendSessionClosed,
                      nsCString(aSessionId, aSessionIdLength));
--- a/dom/media/gmp/GMPDecryptorParent.cpp
+++ b/dom/media/gmp/GMPDecryptorParent.cpp
@@ -302,26 +302,26 @@ GMPDecryptorParent::RecvSessionMessage(c
     return IPC_FAIL_NO_REASON(this);
   }
   mCallback->SessionMessage(aSessionId, ToMediaKeyMessageType(aMessageType), aMessage);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 GMPDecryptorParent::RecvExpirationChange(const nsCString& aSessionId,
-                                         const double& aSecondsSinceEpoch)
+                                         const double& aExpiryTime)
 {
   LOGD(("GMPDecryptorParent[%p]::RecvExpirationChange(sessionId='%s', expiry=%lf)",
-        this, aSessionId.get(), aSecondsSinceEpoch));
+        this, aSessionId.get(), aExpiryTime));
 
   if (!mIsOpen) {
     NS_WARNING("Trying to use a dead GMP decrypter!");
     return IPC_FAIL_NO_REASON(this);
   }
-  mCallback->ExpirationChange(aSessionId, aSecondsSinceEpoch);
+  mCallback->ExpirationChange(aSessionId, aExpiryTime);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 GMPDecryptorParent::RecvSessionClosed(const nsCString& aSessionId)
 {
   LOGD(("GMPDecryptorParent[%p]::RecvSessionClosed(sessionId='%s')",
         this, aSessionId.get()));
--- a/dom/media/gmp/PGMPDecryptor.ipdl
+++ b/dom/media/gmp/PGMPDecryptor.ipdl
@@ -66,17 +66,17 @@ parent:
   async RejectPromise(uint32_t aPromiseId,
                       GMPDOMException aDOMExceptionCode,
                       nsCString aMessage);
 
   async SessionMessage(nsCString aSessionId,
                        GMPSessionMessageType aMessageType,
                        uint8_t[] aMessage);
 
-  async ExpirationChange(nsCString aSessionId, double aSecondsSinceEpoch);
+  async ExpirationChange(nsCString aSessionId, double aExpiryTime);
 
   async SessionClosed(nsCString aSessionId);
 
   async SessionError(nsCString aSessionId,
                      GMPDOMException aDOMExceptionCode,
                      uint32_t aSystemCode,
                      nsCString aMessage);
 
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -2748,17 +2748,17 @@ PluginModuleParent::NPP_NewInternal(NPMI
     // Any IPC messages for the PluginInstance actor should be dispatched to the
     // DocGroup for the plugin's document.
     RefPtr<nsPluginInstanceOwner> owner = parentInstance->GetOwner();
     nsCOMPtr<nsIDOMElement> elt;
     owner->GetDOMElement(getter_AddRefs(elt));
     if (nsCOMPtr<nsINode> node = do_QueryInterface(elt)) {
         nsCOMPtr<nsIDocument> doc = node->OwnerDoc();
         if (doc) {
-            nsCOMPtr<nsIEventTarget> eventTarget = doc->EventTargetFor(dom::TaskCategory::Other);
+            nsCOMPtr<nsIEventTarget> eventTarget = doc->EventTargetFor(TaskCategory::Other);
             SetEventTargetForActor(parentInstance, eventTarget);
         }
     }
 
     if (!SendPPluginInstanceConstructor(parentInstance,
                                         nsDependentCString(pluginType), mode,
                                         names, values)) {
         // |parentInstance| is automatically deleted.
--- a/dom/plugins/test/mochitest/test_bug1092842.html
+++ b/dom/plugins/test/mochitest/test_bug1092842.html
@@ -29,18 +29,19 @@
       clearInterval(interval);
       doTest();
       SimpleTest.finish();
     }, 100);
   }
 
   function doTest() {
     is(p.getClipRegionRectCount(), 1, "getClipRegionRectCount should be a single rect");
-    is(p.getClipRegionRectEdge(0,2) - p.getClipRegionRectEdge(0,0), 100, "width of clip region rect");
-    is(p.getClipRegionRectEdge(0,3) - p.getClipRegionRectEdge(0,1), 26, "height of clip region rect");
+    var dpr = window.devicePixelRatio;
+    is(p.getClipRegionRectEdge(0,2) - p.getClipRegionRectEdge(0,0), 100 * dpr, "width of clip region rect");
+    is(p.getClipRegionRectEdge(0,3) - p.getClipRegionRectEdge(0,1), 26 * dpr, "height of clip region rect");
   }
   </script>
 
   <div style="position:fixed; z-index:1; left:0; right:0; top:0; height:100px; border-bottom:24px solid blue; background:pink; transform:translateZ(0)"></div>
   <object id="theplugin" type="application/x-test" drawmode="solid" color="ff00ff00" wmode="window"
           style="position:absolute; top:50px; left:0; width:100px; height:100px"></object>
 
   <p id="display"></p>
--- a/dom/plugins/test/mochitest/test_bug539565-1.html
+++ b/dom/plugins/test/mochitest/test_bug539565-1.html
@@ -35,20 +35,21 @@ function runTests() {
   function doClick(x,y,func) {
     synthesizeMouse($("plugin1"), x, y, {}, window);
     setTimeout(func,0);
   }
 
   function verify(test,x,y,next) {
     var p = $("plugin1").getLastMouseX();
     const delta = 2;
-    ok(p-delta <= x && x <= p+delta, "test"+test+" LastMouseX got " + p + " expected " + x + 
+    var dpr = window.devicePixelRatio / SpecialPowers.getFullZoom(window);
+    ok(p-delta <= x * dpr && x * dpr <= p+delta, "test"+test+" LastMouseX got " + p + " expected " + x + 
                                      " with fullZoom="+SpecialPowers.getFullZoom(window)+" MozTransform='"+$("container").style.MozTransform+"'");
     p = $("plugin1").getLastMouseY();
-    ok(p-delta <= y && y <= p+delta, "test"+test+" LastMouseY got " + p + " expected " + y +
+    ok(p-delta <= y * dpr && y * dpr <= p+delta, "test"+test+" LastMouseY got " + p + " expected " + y +
                                      " with fullZoom="+SpecialPowers.getFullZoom(window)+" MozTransform='"+$("container").style.MozTransform+"'");
     if (next) next();
   }
 
   function click(x,y,next) {
     waitForPaint(function(){doClick(x,y,next);})
   }
   function zoom(factor) {
--- a/dom/plugins/test/mochitest/test_bug539565-2.html
+++ b/dom/plugins/test/mochitest/test_bug539565-2.html
@@ -35,20 +35,21 @@ function runTests() {
   function doClick(x,y,func) {
     synthesizeMouse($("plugin1"), x, y, {}, window); 
     setTimeout(func,0);
   }
 
   function verify(test,x,y,next) {
     var p = $("plugin1").getLastMouseX();
     const delta = 2;
-    ok(p-delta <= x && x <= p+delta, "test"+test+" LastMouseX got " + p + " expected " + x + 
+    var dpr = window.devicePixelRatio / SpecialPowers.getFullZoom(window);
+    ok(p-delta <= x * dpr && x * dpr <= p+delta, "test"+test+" LastMouseX got " + p + " expected " + x + 
                                      " with fullZoom="+SpecialPowers.getFullZoom(window)+" MozTransform='"+$("container").style.MozTransform+"'");
     p = $("plugin1").getLastMouseY();
-    ok(p-delta <= y && y <= p+delta, "test"+test+" LastMouseY got " + p + " expected " + y +
+    ok(p-delta <= y * dpr && y * dpr <= p+delta, "test"+test+" LastMouseY got " + p + " expected " + y +
                                      " with fullZoom="+SpecialPowers.getFullZoom(window)+" MozTransform='"+$("container").style.MozTransform+"'");
     if (next) next();
   }
 
   function click(x,y,next) {
     waitForPaint(function(){doClick(x,y,next);})
   }
   function zoom(factor) {
--- a/dom/plugins/test/mochitest/test_zero_opacity.html
+++ b/dom/plugins/test/mochitest/test_zero_opacity.html
@@ -29,16 +29,17 @@
       clearInterval(interval);
       doTest();
       SimpleTest.finish();
     }, 100);
   }
 
   function doTest() {
     is(p.getClipRegionRectCount(), 1, "getClipRegionRectCount should be a single rect");
-    is(p.getClipRegionRectEdge(0,2) - p.getClipRegionRectEdge(0,0), 100, "width of clip region rect");
-    is(p.getClipRegionRectEdge(0,3) - p.getClipRegionRectEdge(0,1), 50, "height of clip region rect");
+    var dpr = window.devicePixelRatio;
+    is(p.getClipRegionRectEdge(0,2) - p.getClipRegionRectEdge(0,0), 100 * dpr, "width of clip region rect");
+    is(p.getClipRegionRectEdge(0,3) - p.getClipRegionRectEdge(0,1), 50 * dpr, "height of clip region rect");
   }
   </script>
 
   <p id="display"></p>
 
-  <embed id="theplugin" type="application/x-test" width="100" height="50" style="opacity:0" wmode="window"></embed>
\ No newline at end of file
+  <embed id="theplugin" type="application/x-test" width="100" height="50" style="opacity:0" wmode="window"></embed>
--- a/dom/webidl/EventHandler.webidl
+++ b/dom/webidl/EventHandler.webidl
@@ -10,23 +10,21 @@
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 [TreatNonObjectAsNull]
 callback EventHandlerNonNull = any (Event event);
 typedef EventHandlerNonNull? EventHandler;
 
 [TreatNonObjectAsNull]
-// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23489
-//callback OnBeforeUnloadEventHandlerNonNull = DOMString (Event event);
 callback OnBeforeUnloadEventHandlerNonNull = DOMString? (Event event);
 typedef OnBeforeUnloadEventHandlerNonNull? OnBeforeUnloadEventHandler;
 
 [TreatNonObjectAsNull]
-callback OnErrorEventHandlerNonNull = boolean ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column, optional any error);
+callback OnErrorEventHandlerNonNull = any ((Event or DOMString) event, optional DOMString source, optional unsigned long lineno, optional unsigned long column, optional any error);
 typedef OnErrorEventHandlerNonNull? OnErrorEventHandler;
 
 [NoInterfaceObject]
 interface GlobalEventHandlers {
            attribute EventHandler onabort;
            attribute EventHandler onblur;
 // We think the spec is wrong here. See OnErrorEventHandlerForNodes/Window
 // below.
--- a/dom/xslt/xslt/txMozillaXMLOutput.cpp
+++ b/dom/xslt/xslt/txMozillaXMLOutput.cpp
@@ -795,16 +795,17 @@ txMozillaXMLOutput::createResultDocument
         rv = NS_NewXMLDocument(getter_AddRefs(mDocument),
                                aLoadedAsData);
         NS_ENSURE_SUCCESS(rv, rv);
     }
     // This should really be handled by nsIDocument::BeginLoad
     MOZ_ASSERT(mDocument->GetReadyStateEnum() ==
                nsIDocument::READYSTATE_UNINITIALIZED, "Bad readyState");
     mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_LOADING);
+    mDocument->SetMayStartLayout(false);
     nsCOMPtr<nsIDocument> source = do_QueryInterface(aSourceDocument);
     NS_ENSURE_STATE(source);
     bool hasHadScriptObject = false;
     nsIScriptGlobalObject* sgo =
       source->GetScriptHandlingObject(hasHadScriptObject);
     NS_ENSURE_STATE(sgo || !hasHadScriptObject);
 
     mCurrentNode = mDocument;
--- a/editor/libeditor/EditorBase.h
+++ b/editor/libeditor/EditorBase.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_EditorBase_h
 #define mozilla_EditorBase_h
 
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc.
+#include "mozilla/FlushType.h"          // for FlushType enum
 #include "mozilla/OwningNonNull.h"      // for OwningNonNull
 #include "mozilla/SelectionState.h"     // for RangeUpdater, etc.
 #include "mozilla/StyleSheet.h"   // for StyleSheet
 #include "mozilla/dom/Text.h"
 #include "nsCOMPtr.h"                   // for already_AddRefed, nsCOMPtr
 #include "nsCycleCollectionParticipant.h"
 #include "nsGkAtoms.h"
 #include "nsIEditor.h"                  // for nsIEditor::EDirection, etc.
@@ -947,16 +948,24 @@ public:
 
   /**
    * HideCaret() hides caret with nsCaret::AddForceHide() or may show carent
    * with nsCaret::RemoveForceHide().  This does NOT set visibility of
    * nsCaret.  Therefore, this is stateless.
    */
   void HideCaret(bool aHide);
 
+  void FlushFrames()
+  {
+    nsCOMPtr<nsIDocument> doc = GetDocument();
+    if (doc) {
+      doc->FlushPendingNotifications(FlushType::Frames);
+    }
+  }
+
 protected:
   enum Tristate
   {
     eTriUnset,
     eTriFalse,
     eTriTrue
   };
 
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -1656,16 +1656,19 @@ HTMLEditor::PasteAsCitedQuotation(const 
   // Try to set type=cite.  Ignore it if this fails.
   newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::type,
                    NS_LITERAL_STRING("cite"), true);
 
   // Set the selection to the underneath the node we just inserted:
   rv = selection->Collapse(newNode, 0);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // Ensure that the inserted <blockquote> has a frame to make it IsEditable.
+  FlushFrames();
+
   return Paste(aSelectionType);
 }
 
 /**
  * Paste a plaintext quotation.
  */
 NS_IMETHODIMP
 HTMLEditor::PasteAsPlaintextQuotation(int32_t aSelectionType)
@@ -1712,16 +1715,17 @@ HTMLEditor::PasteAsPlaintextQuotation(in
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 HTMLEditor::InsertTextWithQuotations(const nsAString& aStringToInsert)
 {
+  AutoEditBatch beginBatching(this);
   // The whole operation should be undoable in one transaction:
   BeginTransaction();
 
   // We're going to loop over the string, collecting up a "hunk"
   // that's all the same type (quoted or not),
   // Whenever the quotedness changes (or we reach the string's end)
   // we will insert the hunk all at once, quoted or non.
 
@@ -1875,16 +1879,19 @@ HTMLEditor::InsertAsPlaintextQuotation(c
       newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
         NS_LITERAL_STRING("white-space: pre-wrap;"), true);
     }
 
     // and set the selection inside it:
     selection->Collapse(newNode, 0);
   }
 
+  // Ensure that the inserted <span> has a frame to make it IsEditable.
+  FlushFrames();
+
   if (aAddCites) {
     rv = TextEditor::InsertAsQuotation(aQuotedText, aNodeInserted);
   } else {
     rv = TextEditor::InsertText(aQuotedText);
   }
   // Note that if !aAddCites, aNodeInserted isn't set.
   // That's okay because the routines that use aAddCites
   // don't need to know the inserted node.
@@ -1958,16 +1965,19 @@ HTMLEditor::InsertAsCitedQuotation(const
 
   if (!aCitation.IsEmpty()) {
     newNode->SetAttr(kNameSpaceID_None, nsGkAtoms::cite, aCitation, true);
   }
 
   // Set the selection inside the blockquote so aQuotedText will go there:
   selection->Collapse(newNode, 0);
 
+  // Ensure that the inserted <blockquote> has a frame to make it IsEditable.
+  FlushFrames();
+
   if (aInsertHTML) {
     rv = LoadHTML(aQuotedText);
   } else {
     rv = InsertText(aQuotedText);  // XXX ignore charset
   }
 
   if (aNodeInserted && NS_SUCCEEDED(rv)) {
     *aNodeInserted = GetAsDOMNode(newNode);
--- a/editor/libeditor/tests/mochitest.ini
+++ b/editor/libeditor/tests/mochitest.ini
@@ -155,16 +155,22 @@ subsuite = clipboard
 [test_bug757771.html]
 [test_bug767684.html]
 [test_bug772796.html]
 skip-if = toolkit == 'android' # bug 1309431
 [test_bug773262.html]
 [test_bug780035.html]
 [test_bug787432.html]
 [test_bug790475.html]
+[test_bug795418.html]
+[test_bug795418-2.html]
+[test_bug795418-3.html]
+[test_bug795418-4.html]
+[test_bug795418-5.html]
+[test_bug795418-6.html]
 [test_bug795785.html]
 [test_bug796839.html]
 [test_bug830600.html]
 subsuite = clipboard
 skip-if = e10s
 [test_bug832025.html]
 [test_bug850043.html]
 [test_bug857487.html]
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug795418-2.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=795418
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test #2 for Bug 772796</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772796">Mozilla Bug 795418</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<div id="copySource">Copy this</div>
+<iframe src="data:application/xhtml+xml,<html contenteditable='' xmlns='http://www.w3.org/1999/xhtml'><span>AB</span></html>"></iframe>
+
+<pre id="test">
+
+<script type="application/javascript">
+
+/** Test for Bug 795418 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  var div = document.getElementById("copySource");
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+
+  // Select the text from the text node in div.
+  var r = document.createRange();
+  r.setStart(div.firstChild, 0);
+  r.setEnd(div.firstChild, 9);
+  sel.addRange(r);
+
+  function checkResult() {
+    var iframe = document.querySelector("iframe");
+    var iframeWindow = iframe.contentWindow;
+    var theEdit = iframe.contentDocument.firstChild;
+    theEdit.offsetHeight;
+    is(theEdit.innerHTML,
+       "<blockquote xmlns=\"http://www.w3.org/1999/xhtml\" type=\"cite\">Copy this</blockquote><span xmlns=\"http://www.w3.org/1999/xhtml\">AB</span>",
+       "unexpected HTML for test");
+    SimpleTest.finish();
+  }
+
+  function pasteQuote() {
+    var iframe = document.querySelector("iframe");
+    var iframeWindow = iframe.contentWindow;
+    var theEdit = iframe.contentDocument.firstChild;
+    theEdit.offsetHeight;
+    iframeWindow.focus();
+    SimpleTest.waitForFocus(function() {
+      var iframeSel = iframeWindow.getSelection();
+      iframeSel.removeAllRanges();
+      let span = iframe.contentDocument.querySelector('span');
+      iframeSel.collapse(span, 1);
+
+      SpecialPowers.doCommand(iframeWindow, "cmd_pasteQuote");
+      setTimeout(checkResult, 0);
+    }, iframeWindow);
+  }
+
+  SimpleTest.waitForClipboard(
+    function compare(value) {
+      return true;
+    },
+    function setup() {
+      synthesizeKey("C", {accelKey: true});
+    },
+    function onSuccess() {
+      setTimeout(pasteQuote, 0);
+    },
+    function onFailure() {
+      SimpleTest.finish();
+    },
+    "text/html"
+  );
+});
+
+</script>
+
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug795418-3.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=795418
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test #3 for Bug 772796</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772796">Mozilla Bug 795418</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<div id="copySource">Copy this</div>
+<iframe src="data:text/html,<html><body><span>AB</span>"></iframe>
+
+<pre id="test">
+
+<script type="application/javascript">
+
+/** Test for Bug 795418 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  var div = document.getElementById("copySource");
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+
+  // Select the text from the text node in div.
+  var r = document.createRange();
+  r.setStart(div.firstChild, 0);
+  r.setEnd(div.firstChild, 9);
+  sel.addRange(r);
+
+  function checkResult() {
+    var iframe = document.querySelector("iframe");
+    var iframeWindow = iframe.contentWindow;
+    var theEdit = iframe.contentDocument.body;
+    theEdit.offsetHeight;
+    is(theEdit.innerHTML,
+       "<span>AB<blockquote type=\"cite\">Copy this</blockquote></span>",
+       "unexpected HTML for test");
+    SimpleTest.finish();
+  }
+
+  function pasteQuote() {
+    var iframe = document.querySelector("iframe");
+    var iframeWindow = iframe.contentWindow;
+    var theEdit = iframe.contentDocument.body;
+    iframe.contentDocument.designMode='on';
+    iframe.contentDocument.body.offsetHeight;
+    iframeWindow.focus();
+    SimpleTest.waitForFocus(function() {
+      var iframeSel = iframeWindow.getSelection();
+      iframeSel.removeAllRanges();
+      iframeSel.collapse(theEdit.firstChild, 1);
+
+      SpecialPowers.doCommand(iframeWindow, "cmd_pasteQuote");
+      setTimeout(checkResult, 0);
+    }, iframeWindow);
+  }
+
+  SimpleTest.waitForClipboard(
+    function compare(value) {
+      return true;
+    },
+    function setup() {
+      synthesizeKey("C", {accelKey: true});
+    },
+    function onSuccess() {
+      setTimeout(pasteQuote, 0);
+    },
+    function onFailure() {
+      SimpleTest.finish();
+    },
+    "text/html"
+  );
+});
+
+</script>
+
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug795418-4.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=795418
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test #4 for Bug 795418</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795418">Mozilla Bug 795418</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<div id="copySource">Copy this</div>
+<div id="editable" contenteditable style="display:grid">AB</div>
+
+<pre id="test">
+
+<script type="application/javascript">
+
+/** Test for Bug 795418 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  var div = document.getElementById("copySource");
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+
+  // Select the text from the text node in div.
+  var r = document.createRange();
+  r.setStart(div.firstChild, 0);
+  r.setEnd(div.firstChild, 9);
+  sel.addRange(r);
+
+  SimpleTest.waitForClipboard(
+    function compare(value) {
+      var theEdit = document.getElementById("editable");
+      sel.collapse(theEdit.firstChild, 2);
+
+      SpecialPowers.doCommand(window, "cmd_paste");
+      is(theEdit.innerHTML,
+        "ABCopy this",
+        "unexpected HTML for test");
+      return true;
+    },
+    function setup() {
+      synthesizeKey("C", {accelKey: true});
+    },
+    function onSuccess() {
+      SimpleTest.finish();
+    },
+    function onFailure() {
+      SimpleTest.finish();
+    },
+    "text/html"
+  );
+});
+
+</script>
+
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug795418-5.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=795418
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test #5 for Bug 795418</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795418">Mozilla Bug 795418</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<div id="copySource">Copy this</div>
+<div id="editable" contenteditable style="display:ruby">AB</div>
+
+<pre id="test">
+
+<script type="application/javascript">
+
+/** Test for Bug 795418 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  var div = document.getElementById("copySource");
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+
+  // Select the text from the text node in div.
+  var r = document.createRange();
+  r.setStart(div.firstChild, 0);
+  r.setEnd(div.firstChild, 9);
+  sel.addRange(r);
+
+  SimpleTest.waitForClipboard(
+    function compare(value) {
+      var theEdit = document.getElementById("editable");
+      sel.collapse(theEdit.firstChild, 2);
+
+      SpecialPowers.doCommand(window, "cmd_paste");
+      is(theEdit.innerHTML,
+        "ABCopy this",
+        "unexpected HTML for test");
+      return true;
+    },
+    function setup() {
+      synthesizeKey("C", {accelKey: true});
+    },
+    function onSuccess() {
+      SimpleTest.finish();
+    },
+    function onFailure() {
+      SimpleTest.finish();
+    },
+    "text/html"
+  );
+});
+
+</script>
+
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug795418-6.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=795418
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test #5 for Bug 795418</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795418">Mozilla Bug 795418</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<div id="copySource">Copy this</div>
+<div id="editable" contenteditable style="display:table">AB</div>
+
+<pre id="test">
+
+<script type="application/javascript">
+
+/** Test for Bug 795418 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  var div = document.getElementById("copySource");
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+
+  // Select the text from the text node in div.
+  var r = document.createRange();
+  r.setStart(div.firstChild, 0);
+  r.setEnd(div.firstChild, 9);
+  sel.addRange(r);
+
+  SimpleTest.waitForClipboard(
+    function compare(value) {
+      var theEdit = document.getElementById("editable");
+      sel.collapse(theEdit.firstChild, 2);
+
+      SpecialPowers.doCommand(window, "cmd_pasteQuote");
+      is(theEdit.innerHTML,
+        "AB<blockquote type=\"cite\">Copy this</blockquote>",
+        "unexpected HTML for test");
+      return true;
+    },
+    function setup() {
+      synthesizeKey("C", {accelKey: true});
+    },
+    function onSuccess() {
+      SimpleTest.finish();
+    },
+    function onFailure() {
+      SimpleTest.finish();
+    },
+    "text/html"
+  );
+});
+
+</script>
+
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/tests/test_bug795418.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=795418
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 795418</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=795418">Mozilla Bug 795418</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<div id="copySource">Copy this</div>
+<div id="editable" contenteditable><span>AB</span></div>
+
+<pre id="test">
+
+<script type="application/javascript">
+
+/** Test for Bug 795418 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+  var div = document.getElementById("copySource");
+  var sel = window.getSelection();
+  sel.removeAllRanges();
+
+  // Select the text from the text node in div.
+  var r = document.createRange();
+  r.setStart(div.firstChild, 0);
+  r.setEnd(div.firstChild, 9);
+  sel.addRange(r);
+
+  SimpleTest.waitForClipboard(
+    function compare(value) {
+      var theEdit = document.getElementById("editable");
+      sel.collapse(theEdit.firstChild, 1);
+
+      SpecialPowers.doCommand(window, "cmd_pasteQuote");
+      is(theEdit.innerHTML,
+        "<span>AB<blockquote type=\"cite\">Copy this</blockquote></span>",
+        "unexpected HTML for test");
+      return true;
+    },
+    function setup() {
+      synthesizeKey("C", {accelKey: true});
+    },
+    function onSuccess() {
+      SimpleTest.finish();
+    },
+    function onFailure() {
+      SimpleTest.finish();
+    },
+    "text/html"
+  );
+});
+
+</script>
+
+</pre>
+</body>
+</html>
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -6,16 +6,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "GPUChild.h"
 #include "gfxConfig.h"
 #include "gfxPrefs.h"
 #include "GPUProcessHost.h"
 #include "GPUProcessManager.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/CheckerboardReportService.h"
+#include "mozilla/dom/MemoryReportRequest.h"
 #include "mozilla/gfx/gfxVars.h"
 #if defined(XP_WIN)
 # include "mozilla/gfx/DeviceManagerDx.h"
 #endif
 #include "mozilla/ipc/CrashReporterHost.h"
 
 namespace mozilla {
 namespace gfx {
@@ -169,28 +170,63 @@ GPUChild::RecvUpdateChildKeyedScalars(In
 
 mozilla::ipc::IPCResult
 GPUChild::RecvNotifyDeviceReset()
 {
   mHost->mListener->OnProcessDeviceReset(mHost);
   return IPC_OK();
 }
 
+bool
+GPUChild::SendRequestMemoryReport(const uint32_t& aGeneration,
+                                  const bool& aAnonymize,
+                                  const bool& aMinimizeMemoryUsage,
+                                  const MaybeFileDesc& aDMDFile)
+{
+  mMemoryReportRequest = MakeUnique<MemoryReportRequestHost>(aGeneration);
+  Unused << PGPUChild::SendRequestMemoryReport(
+    aGeneration,
+    aAnonymize,
+    aMinimizeMemoryUsage,
+    aDMDFile);
+  return true;
+}
+
+mozilla::ipc::IPCResult
+GPUChild::RecvAddMemoryReport(const MemoryReport& aReport)
+{
+  if (mMemoryReportRequest) {
+    mMemoryReportRequest->RecvReport(aReport);
+  }
+  return IPC_OK();
+}
+
+mozilla::ipc::IPCResult
+GPUChild::RecvFinishMemoryReport(const uint32_t& aGeneration)
+{
+  if (mMemoryReportRequest) {
+    mMemoryReportRequest->Finish(aGeneration);
+    mMemoryReportRequest = nullptr;
+  }
+  return IPC_OK();
+}
+
 void
 GPUChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (aWhy == AbnormalShutdown) {
 #ifdef MOZ_CRASHREPORTER
     if (mCrashReporter) {
       mCrashReporter->GenerateCrashReport(OtherPid());
       mCrashReporter = nullptr;
     }
 #endif
+
     Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
-        nsDependentCString(XRE_ChildProcessTypeToString(GeckoProcessType_GPU), 1));
+        nsDependentCString(XRE_ChildProcessTypeToString(GeckoProcessType_GPU)), 1);
 
     // Notify the Telemetry environment so that we can refresh and do a subsession split
     if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
       obsvc->NotifyObservers(nullptr, "compositor:process-aborted", nullptr);
     }
 
   }
 
--- a/gfx/ipc/GPUChild.h
+++ b/gfx/ipc/GPUChild.h
@@ -9,25 +9,30 @@
 #include "mozilla/RefPtr.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/PGPUChild.h"
 #include "mozilla/gfx/gfxVarReceiver.h"
 
 namespace mozilla {
 namespace ipc {
 class CrashReporterHost;
-} // namespace
+} // namespace ipc
+namespace dom {
+class MemoryReportRequestHost;
+} // namespace dom
 namespace gfx {
 
 class GPUProcessHost;
 
 class GPUChild final
   : public PGPUChild,
     public gfxVarReceiver
 {
+  typedef mozilla::dom::MemoryReportRequestHost MemoryReportRequestHost;
+
 public:
   explicit GPUChild(GPUProcessHost* aHost);
   ~GPUChild();
 
   void Init();
 
   void EnsureGPUReady();
 
@@ -41,21 +46,29 @@ public:
   mozilla::ipc::IPCResult RecvAccumulateChildHistogram(InfallibleTArray<Accumulation>&& aAccumulations) override;
   mozilla::ipc::IPCResult RecvAccumulateChildKeyedHistogram(InfallibleTArray<KeyedAccumulation>&& aAccumulations) override;
   mozilla::ipc::IPCResult RecvUpdateChildScalars(InfallibleTArray<ScalarAction>&& aScalarActions) override;
   mozilla::ipc::IPCResult RecvUpdateChildKeyedScalars(InfallibleTArray<KeyedScalarAction>&& aScalarActions) override;
   void ActorDestroy(ActorDestroyReason aWhy) override;
   mozilla::ipc::IPCResult RecvGraphicsError(const nsCString& aError) override;
   mozilla::ipc::IPCResult RecvNotifyUiObservers(const nsCString& aTopic) override;
   mozilla::ipc::IPCResult RecvNotifyDeviceReset() override;
+  mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override;
+  mozilla::ipc::IPCResult RecvFinishMemoryReport(const uint32_t& aGeneration) override;
+
+  bool SendRequestMemoryReport(const uint32_t& aGeneration,
+                               const bool& aAnonymize,
+                               const bool& aMinimizeMemoryUsage,
+                               const MaybeFileDesc& aDMDFile);
 
   static void Destroy(UniquePtr<GPUChild>&& aChild);
 
 private:
   GPUProcessHost* mHost;
   UniquePtr<ipc::CrashReporterHost> mCrashReporter;
+  UniquePtr<MemoryReportRequestHost> mMemoryReportRequest;
   bool mGPUReady;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif // _include_mozilla_gfx_ipc_GPUChild_h_
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -9,40 +9,42 @@
 #include "GPUParent.h"
 #include "gfxConfig.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "GPUProcessHost.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
+#include "mozilla/dom/MemoryReportRequest.h"
+#include "mozilla/dom/VideoDecoderManagerChild.h"
+#include "mozilla/dom/VideoDecoderManagerParent.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/gfxVars.h"
 #include "mozilla/ipc/CrashReporterClient.h"
 #include "mozilla/ipc/ProcessChild.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
-#include "mozilla/dom/VideoDecoderManagerParent.h"
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/ImageBridgeParent.h"
-#include "mozilla/dom/VideoDecoderManagerChild.h"
 #include "mozilla/layers/LayerTreeOwnerTracker.h"
 #include "mozilla/layers/UiCompositorControllerParent.h"
 #include "nsDebugImpl.h"
 #include "nsExceptionHandler.h"
 #include "nsThreadManager.h"
 #include "prenv.h"
 #include "ProcessUtils.h"
 #include "VRManager.h"
 #include "VRManagerParent.h"
 #include "VsyncBridgeParent.h"
 #if defined(XP_WIN)
 # include "DeviceManagerD3D9.h"
 # include "mozilla/gfx/DeviceManagerDx.h"
+# include <process.h>
 #endif
 #ifdef MOZ_WIDGET_GTK
 # include <gtk/gtk.h>
 #endif
 
 namespace mozilla {
 namespace gfx {
 
@@ -367,16 +369,29 @@ GPUParent::RecvNotifyGpuObservers(const 
   nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
   MOZ_ASSERT(obsSvc);
   if (obsSvc) {
     obsSvc->NotifyObservers(nullptr, aTopic.get(), nullptr);
   }
   return IPC_OK();
 }
 
+mozilla::ipc::IPCResult
+GPUParent::RecvRequestMemoryReport(const uint32_t& aGeneration,
+                                   const bool& aAnonymize,
+                                   const bool& aMinimizeMemoryUsage,
+                                   const MaybeFileDesc& aDMDFile)
+{
+  nsPrintfCString processName("GPU (pid %u)", (unsigned)getpid());
+
+  mozilla::dom::MemoryReportRequestClient::Start(
+    aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName);
+  return IPC_OK();
+}
+
 void
 GPUParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (AbnormalShutdown == aWhy) {
     NS_WARNING("Shutting down GPU process early due to a crash!");
     ProcessChild::QuickExit();
   }
 
--- a/gfx/ipc/GPUParent.h
+++ b/gfx/ipc/GPUParent.h
@@ -49,16 +49,21 @@ public:
   mozilla::ipc::IPCResult RecvNewContentCompositorBridge(Endpoint<PCompositorBridgeParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvNewContentImageBridge(Endpoint<PImageBridgeParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvNewContentVRManager(Endpoint<PVRManagerParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvNewContentVideoDecoderManager(Endpoint<PVideoDecoderManagerParent>&& aEndpoint) override;
   mozilla::ipc::IPCResult RecvGetDeviceStatus(GPUDeviceData* aOutStatus) override;
   mozilla::ipc::IPCResult RecvAddLayerTreeIdMapping(nsTArray<LayerTreeIdMapping>&& aMappings) override;
   mozilla::ipc::IPCResult RecvRemoveLayerTreeIdMapping(const LayerTreeIdMapping& aMapping) override;
   mozilla::ipc::IPCResult RecvNotifyGpuObservers(const nsCString& aTopic) override;
+  mozilla::ipc::IPCResult RecvRequestMemoryReport(
+    const uint32_t& generation,
+    const bool& anonymize,
+    const bool& minimizeMemoryUsage,
+    const MaybeFileDesc& DMDFile) override;
 
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
 private:
   const TimeStamp mLaunchTime;
   RefPtr<VsyncBridgeParent> mVsyncBridge;
 };
 
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=99: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "GPUProcessManager.h"
 #include "GPUProcessHost.h"
 #include "GPUProcessListener.h"
+#include "mozilla/MemoryReportingProcess.h"
 #include "mozilla/Sprintf.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/APZCTreeManagerChild.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorOptions.h"
 #include "mozilla/layers/ImageBridgeChild.h"
@@ -901,10 +902,66 @@ GPUProcessManager::NotifyGpuObservers(co
   if (!mGPUChild) {
     return false;
   }
   nsCString topic(aTopic);
   mGPUChild->SendNotifyGpuObservers(topic);
   return true;
 }
 
+class GPUMemoryReporter : public MemoryReportingProcess
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GPUMemoryReporter, override)
+
+  bool IsAlive() const override {
+    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
+      return !!gpm->GetGPUChild();
+    }
+    return false;
+  }
+
+  bool SendRequestMemoryReport(const uint32_t& aGeneration,
+                               const bool& aAnonymize,
+                               const bool& aMinimizeMemoryUsage,
+                               const dom::MaybeFileDesc& aDMDFile) override
+  {
+    GPUChild* child = GetChild();
+    if (!child) {
+      return false;
+    }
+
+    return child->SendRequestMemoryReport(
+      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile);
+  }
+
+  int32_t Pid() const override {
+    if (GPUChild* child = GetChild()) {
+      return (int32_t)child->OtherPid();
+    }
+    return 0;
+  }
+
+private:
+  GPUChild* GetChild() const {
+    if (GPUProcessManager* gpm = GPUProcessManager::Get()) {
+      if (GPUChild* child = gpm->GetGPUChild()) {
+        return child;
+      }
+    }
+    return nullptr;
+  }
+
+protected:
+  ~GPUMemoryReporter() = default;
+};
+
+RefPtr<MemoryReportingProcess>
+GPUProcessManager::GetProcessMemoryReporter()
+{
+  if (!mGPUChild) {
+    return nullptr;
+  }
+  return new GPUMemoryReporter();
+}
+
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/ipc/GPUProcessManager.h
+++ b/gfx/ipc/GPUProcessManager.h
@@ -17,16 +17,17 @@
 #include "mozilla/ipc/TaskFactory.h"
 #include "mozilla/ipc/Transport.h"
 #include "nsIObserverService.h"
 #include "nsThreadUtils.h"
 class nsBaseWidget;
 
 
 namespace mozilla {
+class MemoryReportingProcess;
 namespace layers {
 class IAPZCTreeManager;
 class CompositorOptions;
 class CompositorSession;
 class CompositorUpdateObserver;
 class PCompositorBridgeChild;
 class PImageBridgeChild;
 class RemoteCompositorSession;
@@ -135,16 +136,20 @@ public:
   bool NotifyGpuObservers(const char* aTopic);
 
   // Used for tests and diagnostics
   void KillProcess();
 
   // Returns -1 if there is no GPU process, or the platform pid for it.
   base::ProcessId GPUProcessPid();
 
+  // If a GPU process is present, create a MemoryReportingProcess object.
+  // Otherwise, return null.
+  RefPtr<MemoryReportingProcess> GetProcessMemoryReporter();
+
   // Returns access to the PGPU protocol if a GPU process is present.
   GPUChild* GetGPUChild() {
     return mGPUChild;
   }
 
   // Returns whether or not a GPU process was ever launched.
   bool AttemptedGPUProcess() const {
     return mNumProcessAttempts > 0;
--- a/gfx/ipc/PGPU.ipdl
+++ b/gfx/ipc/PGPU.ipdl
@@ -1,14 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include GraphicsMessages;
+include MemoryReportTypes;
 include protocol PCompositorBridge;
 include protocol PImageBridge;
 include protocol PVRManager;
 include protocol PVsyncBridge;
 include protocol PUiCompositorController;
 include protocol PVideoDecoderManager;
 
 using base::ProcessId from "base/process.h";
@@ -80,16 +81,21 @@ parent:
   // Request the current DeviceStatus from the GPU process. This blocks until
   // one is available (i.e., Init has completed).
   sync GetDeviceStatus() returns (GPUDeviceData status);
 
   // Have a message be broadcasted to the GPU process by the GPU process
   // observer service.
   async NotifyGpuObservers(nsCString aTopic);
 
+  async RequestMemoryReport(uint32_t generation,
+                            bool anonymize,
+                            bool minimizeMemoryUsage,
+                            MaybeFileDesc DMDFile);
+
 child:
   // Sent when the GPU process has initialized devices. This occurs once, after
   // Init().
   async InitComplete(GPUDeviceData data);
 
   // Sent when APZ detects checkerboarding and apz checkerboard reporting is enabled.
   async ReportCheckerboard(uint32_t severity, nsCString log);
 
@@ -104,12 +110,15 @@ child:
 
   // Messages for reporting telemetry to the UI process.
   async AccumulateChildHistogram(Accumulation[] accumulations);
   async AccumulateChildKeyedHistogram(KeyedAccumulation[] accumulations);
   async UpdateChildScalars(ScalarAction[] actions);
   async UpdateChildKeyedScalars(KeyedScalarAction[] actions);
 
   async NotifyDeviceReset();
+
+  async AddMemoryReport(MemoryReport aReport);
+  async FinishMemoryReport(uint32_t aGeneration);
 };
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp
+++ b/gfx/layers/ipc/CompositorBridgeChild.cpp
@@ -580,26 +580,16 @@ CompositorBridgeChild::RecvDidComposite(
 
   for (size_t i = 0; i < mTexturePools.Length(); i++) {
     mTexturePools[i]->ReturnDeferredClients();
   }
 
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult
-CompositorBridgeChild::RecvClearCachedResources(const uint64_t& aId)
-{
-  dom::TabChild* child = dom::TabChild::GetFrom(aId);
-  if (child) {
-    child->ClearCachedResources();
-  }
-  return IPC_OK();
-}
-
 void
 CompositorBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   if (aWhy == AbnormalShutdown) {
     // If the parent side runs into a problem then the actor will be destroyed.
     // There is nothing we can do in the child side, here sets mCanSend as false.
     gfxCriticalNote << "Receive IPC close with reason=AbnormalShutdown";
   }
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -89,19 +89,16 @@ public:
 
   static bool ChildProcessHasCompositorBridge();
 
   // Returns whether the compositor is in the GPU process (false if in the UI
   // process). This may only be called on the main thread.
   static bool CompositorIsInGPUProcess();
 
   virtual mozilla::ipc::IPCResult
-  RecvClearCachedResources(const uint64_t& id) override;
-
-  virtual mozilla::ipc::IPCResult
   RecvDidComposite(const uint64_t& aId, const uint64_t& aTransactionId,
                    const TimeStamp& aCompositeStart,
                    const TimeStamp& aCompositeEnd) override;
 
   virtual mozilla::ipc::IPCResult
   RecvInvalidateLayers(const uint64_t& aLayersId) override;
 
   virtual mozilla::ipc::IPCResult
--- a/gfx/layers/ipc/PCompositorBridge.ipdl
+++ b/gfx/layers/ipc/PCompositorBridge.ipdl
@@ -121,22 +121,16 @@ child:
   async CaptureAllPlugins(uintptr_t aParentWidget);
 
   /**
    * Hides all registered plugin widgets associated with a particular chrome
    * widget.
    */
   async HideAllPlugins(uintptr_t aParentWidget);
 
-  /**
-   * Drop any buffers that might be retained on the child compositor
-   * side.
-   */
-  async ClearCachedResources(uint64_t id);
-
   async ParentAsyncMessages(AsyncParentMessageData[] aMessages);
 
   async ObserveLayerUpdate(uint64_t aLayersId, uint64_t aEpoch, bool aActive);
 
 parent:
   // Must be called before Initialize().
   async PCompositorWidget(CompositorWidgetInitData aInitData);
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -2215,35 +2215,35 @@ gfxPlatform::InitGPUProcessPrefs()
   // We want to hide this from about:support, so only set a default if the
   // pref is known to be true.
   if (!gfxPrefs::GPUProcessEnabled() && !gfxPrefs::GPUProcessForceEnabled()) {
     return;
   }
 
   FeatureState& gpuProc = gfxConfig::GetFeature(Feature::GPU_PROCESS);
 
-  gpuProc.SetDefaultFromPref(
-    gfxPrefs::GetGPUProcessEnabledPrefName(),
-    true,
-    gfxPrefs::GetGPUProcessEnabledPrefDefault());
+  // We require E10S - otherwise, there is very little benefit to the GPU
+  // process, since the UI process must still use acceleration for
+  // performance.
+  if (!BrowserTabsRemoteAutostart()) {
+    gpuProc.DisableByDefault(
+      FeatureStatus::Unavailable,
+      "Multi-process mode is not enabled",
+      NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_E10S"));
+  } else {
+    gpuProc.SetDefaultFromPref(
+      gfxPrefs::GetGPUProcessEnabledPrefName(),
+      true,
+      gfxPrefs::GetGPUProcessEnabledPrefDefault());
+  }
 
   if (gfxPrefs::GPUProcessForceEnabled()) {
     gpuProc.UserForceEnable("User force-enabled via pref");
   }
 
-  // We require E10S - otherwise, there is very little benefit to the GPU
-  // process, since the UI process must still use acceleration for
-  // performance.
-  if (!BrowserTabsRemoteAutostart()) {
-    gpuProc.ForceDisable(
-      FeatureStatus::Unavailable,
-      "Multi-process mode is not enabled",
-      NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_E10S"));
-    return;
-  }
   if (InSafeMode()) {
     gpuProc.ForceDisable(
       FeatureStatus::Blocked,
       "Safe-mode is enabled",
       NS_LITERAL_CSTRING("FEATURE_FAILURE_SAFE_MODE"));
     return;
   }
   if (gfxPrefs::LayerScopeEnabled()) {
@@ -2409,16 +2409,37 @@ gfxPlatform::GetSoftwareVsyncRate()
 
 /* static */ int
 gfxPlatform::GetDefaultFrameRate()
 {
   return 60;
 }
 
 void
+gfxPlatform::GetAzureBackendInfo(mozilla::widget::InfoObject& aObj)
+{
+  if (gfxConfig::IsEnabled(Feature::GPU_PROCESS)) {
+    aObj.DefineProperty("AzureCanvasBackend (UI Process)", GetBackendName(mPreferredCanvasBackend));
+    aObj.DefineProperty("AzureFallbackCanvasBackend (UI Process)", GetBackendName(mFallbackCanvasBackend));
+    aObj.DefineProperty("AzureContentBackend (UI Process)", GetBackendName(mContentBackend));
+
+    if (gfxConfig::IsEnabled(gfx::Feature::DIRECT2D)) {
+      aObj.DefineProperty("AzureCanvasBackend", "Direct2D 1.1");
+      aObj.DefineProperty("AzureContentBackend", "Direct2D 1.1");
+    }
+  } else {
+    aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend));
+    aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend));
+    aObj.DefineProperty("AzureContentBackend", GetBackendName(mContentBackend));
+  }
+
+  aObj.DefineProperty("AzureCanvasAccelerated", AllowOpenGLCanvas());
+}
+
+void
 gfxPlatform::GetApzSupportInfo(mozilla::widget::InfoObject& aObj)
 {
   if (!gfxPlatform::AsyncPanZoomEnabled()) {
     return;
   }
 
   if (SupportsApzWheelInput()) {
     aObj.DefineProperty("ApzWheelInput", 1);
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -277,22 +277,17 @@ public:
     /// asking for it, we will examine the commands in the first few seconds
     /// of the canvas usage, and potentially change to accelerated or
     /// non-accelerated canvas.
     bool AllowOpenGLCanvas();
     virtual void InitializeSkiaCacheLimits();
 
     static bool AsyncPanZoomEnabled();
 
-    virtual void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
-      aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend));
-      aObj.DefineProperty("AzureCanvasAccelerated", AllowOpenGLCanvas());
-      aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend));
-      aObj.DefineProperty("AzureContentBackend", GetBackendName(mContentBackend));
-    }
+    virtual void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj);
     void GetApzSupportInfo(mozilla::widget::InfoObject& aObj);
     void GetTilesSupportInfo(mozilla::widget::InfoObject& aObj);
 
     // Get the default content backend that will be used with the default
     // compositor. If the compositor is known when calling this function,
     // GetContentBackendFor() should be called instead.
     mozilla::gfx::BackendType GetDefaultContentBackend() {
       return mContentBackend;
--- a/js/public/ProfilingStack.h
+++ b/js/public/ProfilingStack.h
@@ -16,17 +16,17 @@
 struct JSRuntime;
 class JSTracer;
 
 namespace js {
 
 // A call stack can be specified to the JS engine such that all JS entry/exits
 // to functions push/pop an entry to/from the specified stack.
 //
-// For more detailed information, see vm/SPSProfiler.h.
+// For more detailed information, see vm/GeckoProfiler.h.
 //
 class ProfileEntry
 {
     // All fields are marked volatile to prevent the compiler from re-ordering
     // instructions. Namely this sequence:
     //
     //    entry[size] = ...;
     //    size++;
@@ -90,20 +90,20 @@ class ProfileEntry
 
         FIRST    = OTHER,
         LAST     = EVENTS
     };
 
     static_assert((static_cast<int>(Category::FIRST) & Flags::ALL) == 0,
                   "The category bitflags should not intersect with the other flags!");
 
-    // All of these methods are marked with the 'volatile' keyword because SPS's
-    // representation of the stack is stored such that all ProfileEntry
-    // instances are volatile. These methods would not be available unless they
-    // were marked as volatile as well.
+    // All of these methods are marked with the 'volatile' keyword because the
+    // Gecko Profiler's representation of the stack is stored such that all
+    // ProfileEntry instances are volatile. These methods would not be
+    // available unless they were marked as volatile as well.
 
     bool isCpp() const volatile { return hasFlag(IS_CPP_ENTRY); }
     bool isJs() const volatile { return !isCpp(); }
 
     bool isCopyLabel() const volatile { return hasFlag(FRAME_LABEL_COPY); }
 
     void setLabel(const char* aString) volatile { string = aString; }
     const char* label() const volatile { return string; }
@@ -168,17 +168,17 @@ class ProfileEntry
     }
 
     // Note that the pointer returned might be invalid.
     JSScript* rawScript() const volatile {
         MOZ_ASSERT(isJs());
         return (JSScript*)spOrScript;
     }
 
-    // We can't know the layout of JSScript, so look in vm/SPSProfiler.cpp.
+    // We can't know the layout of JSScript, so look in vm/GeckoProfiler.cpp.
     JS_FRIEND_API(jsbytecode*) pc() const volatile;
     JS_FRIEND_API(void) setPC(jsbytecode* pc) volatile;
 
     void trace(JSTracer* trc);
 
     // The offset of a pc into a script's code can actually be 0, so to
     // signify a nullptr pc, use a -1 index. This is checked against in
     // pc() and setPC() to set/get the right pc.
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -418,28 +418,16 @@ js::obj_toString(JSContext* cx, unsigned
     RootedString str(cx, sb.finishString());
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
-
-bool
-js::obj_valueOf(JSContext* cx, unsigned argc, Value* vp)
-{
-    CallArgs args = CallArgsFromVp(argc, vp);
-    RootedObject obj(cx, ToObject(cx, args.thisv()));
-    if (!obj)
-        return false;
-    args.rval().setObject(*obj);
-    return true;
-}
-
 static bool
 obj_setPrototypeOf(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() < 2) {
         JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_MORE_ARGS_NEEDED,
                                   "Object.setPrototypeOf", "1", "");
@@ -1194,17 +1182,17 @@ ProtoSetter(JSContext* cx, unsigned argc
 }
 
 static const JSFunctionSpec object_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,             obj_toSource,                0,0),
 #endif
     JS_FN(js_toString_str,             obj_toString,                0,0),
     JS_SELF_HOSTED_FN(js_toLocaleString_str, "Object_toLocaleString", 0, 0),
-    JS_FN(js_valueOf_str,              obj_valueOf,                 0,0),
+    JS_SELF_HOSTED_FN(js_valueOf_str,  "Object_valueOf",            0,0),
 #if JS_HAS_OBJ_WATCHPOINT
     JS_FN(js_watch_str,                obj_watch,                   2,0),
     JS_FN(js_unwatch_str,              obj_unwatch,                 1,0),
 #endif
     JS_FN(js_hasOwnProperty_str,       obj_hasOwnProperty,          1,0),
     JS_FN(js_isPrototypeOf_str,        obj_isPrototypeOf,           1,0),
     JS_FN(js_propertyIsEnumerable_str, obj_propertyIsEnumerable,    1,0),
 #if JS_OLD_GETTER_SETTER_METHODS
--- a/js/src/builtin/Object.h
+++ b/js/src/builtin/Object.h
@@ -20,19 +20,16 @@ namespace js {
 
 // Object constructor native. Exposed only so the JIT can know its address.
 MOZ_MUST_USE bool
 obj_construct(JSContext* cx, unsigned argc, JS::Value* vp);
 
 MOZ_MUST_USE bool
 obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp);
 
-MOZ_MUST_USE bool
-obj_valueOf(JSContext* cx, unsigned argc, JS::Value* vp);
-
 PlainObject*
 ObjectCreateImpl(JSContext* cx, HandleObject proto, NewObjectKind newKind = GenericObject,
                  HandleObjectGroup group = nullptr);
 
 PlainObject*
 ObjectCreateWithTemplate(JSContext* cx, HandlePlainObject templateObj);
 
 // Object methods exposed so they can be installed in the self-hosting global.
--- a/js/src/builtin/Object.js
+++ b/js/src/builtin/Object.js
@@ -82,16 +82,22 @@ function ObjectIsExtensible(obj) {
 function Object_toLocaleString() {
     // Step 1.
     var O = this;
 
     // Step 2.
     return callContentFunction(O.toString, O);
 }
 
+// ES 2017 draft bb96899bb0d9ef9be08164a26efae2ee5f25e875 19.1.3.7
+function Object_valueOf() {
+    // Step 1.
+    return ToObject(this);
+}
+
 // ES7 draft (2016 March 8) B.2.2.3
 function ObjectDefineSetter(name, setter) {
     // Step 1.
     var object = ToObject(this);
 
     // Step 2.
     if (!IsCallable(setter))
         ThrowTypeError(JSMSG_BAD_GETTER_OR_SETTER, "setter");
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1740,23 +1740,23 @@ Terminate(JSContext* cx, unsigned arg, V
     fprintf(stderr, "terminate called\n");
 #endif
 
     JS_ClearPendingException(cx);
     return false;
 }
 
 static bool
-ReadSPSProfilingStack(JSContext* cx, unsigned argc, Value* vp)
+ReadGeckoProfilingStack(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setUndefined();
 
     // Return boolean 'false' if profiler is not enabled.
-    if (!cx->runtime()->spsProfiler.enabled()) {
+    if (!cx->runtime()->geckoProfiler.enabled()) {
         args.rval().setBoolean(false);
         return true;
     }
 
     // Array holding physical jit stack frames.
     RootedObject stack(cx, NewDenseEmptyArray(cx));
     if (!stack)
         return false;
@@ -4373,18 +4373,18 @@ gc::ZealModeHelpText),
 "  'collectNurseryBeforeDump' is specified, a minor GC is performed first,\n"
 "  otherwise objects in the nursery are ignored."),
 
     JS_FN_HELP("terminate", Terminate, 0, 0,
 "terminate()",
 "  Terminate JavaScript execution, as if we had run out of\n"
 "  memory or been terminated by the slow script dialog."),
 
-    JS_FN_HELP("readSPSProfilingStack", ReadSPSProfilingStack, 0, 0,
-"readSPSProfilingStack()",
+    JS_FN_HELP("readGeckoProfilingStack", ReadGeckoProfilingStack, 0, 0,
+"readGeckoProfilingStack()",
 "  Reads the jit stack using ProfilingFrameIterator."),
 
     JS_FN_HELP("enableOsiPointRegisterChecks", EnableOsiPointRegisterChecks, 0, 0,
 "enableOsiPointRegisterChecks()",
 "Emit extra code to verify live regs at the start of a VM call are not\n"
 "modified before its OsiPoint."),
 
     JS_FN_HELP("displayName", DisplayName, 1, 0,
--- a/js/src/gc/GCInternals.h
+++ b/js/src/gc/GCInternals.h
@@ -41,17 +41,17 @@ class MOZ_RAII AutoTraceSession
   protected:
     JSRuntime* runtime;
 
   private:
     AutoTraceSession(const AutoTraceSession&) = delete;
     void operator=(const AutoTraceSession&) = delete;
 
     JS::HeapState prevState;
-    AutoSPSEntry pseudoFrame;
+    AutoGeckoProfilerEntry pseudoFrame;
 };
 
 class MOZ_RAII AutoPrepareForTracing
 {
     mozilla::Maybe<AutoTraceSession> session_;
 
   public:
     AutoPrepareForTracing(JSContext* cx, ZoneSelector selector);
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -356,18 +356,18 @@ js::gc::GCRuntime::traceRuntimeCommon(JS
     // same struct as the JSRuntime, but is still split for historical reasons.
     rt->contextFromMainThread()->trace(trc);
 
     // Trace all compartment roots, but not the compartment itself; it is
     // traced via the parent pointer if traceRoots actually traces anything.
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
         c->traceRoots(trc, traceOrMark);
 
-    // Trace SPS.
-    rt->spsProfiler.trace(trc);
+    // Trace the Gecko Profiler.
+    rt->geckoProfiler.trace(trc);
 
     // Trace helper thread roots.
     HelperThreadState().trace(trc);
 
     // Trace the embedding's black and gray roots.
     if (!rt->isHeapMinorCollecting()) {
         gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK_EMBEDDING);
 
--- a/js/src/jit-test/tests/TypedObject/bug1096023.js
+++ b/js/src/jit-test/tests/TypedObject/bug1096023.js
@@ -1,12 +1,12 @@
 if (!this.hasOwnProperty("TypedObject"))
   quit();
 
-enableSPSProfiling();
+enableGeckoProfiling();
 var T = TypedObject;
 function check(results, ctor) {
   for (var i = 0; i < results.length; i++)
   var S = new T.StructType({f: ctor});
   for (var i = 0; i < results.length; i++) {
     var s = new S({f: results[i][1]});
   }
 }
--- a/js/src/jit-test/tests/asm.js/bug1276028.js
+++ b/js/src/jit-test/tests/asm.js/bug1276028.js
@@ -1,6 +1,6 @@
 load(libdir + "asm.js");
 
 var f = asmLink(asmCompile(USE_ASM + "function a234567() { return 42 } return a234567"));
 assertEq(f(), 42);
-enableSPSProfiling();
+enableGeckoProfiling();
 assertEq(f(), 42);
--- a/js/src/jit-test/tests/asm.js/testBug1046688.js
+++ b/js/src/jit-test/tests/asm.js/testBug1046688.js
@@ -1,9 +1,9 @@
-enableSPSProfiling();
+enableGeckoProfiling();
 for (var j = 0; j < 1000; ++j) {
   (function(stdlib) {
     "use asm";
     var pow = stdlib.Math.pow;
     function f() {
         return +pow(.0, .0)
     }
     return f;
--- a/js/src/jit-test/tests/asm.js/testBug1111327.js
+++ b/js/src/jit-test/tests/asm.js/testBug1111327.js
@@ -1,11 +1,11 @@
 load(libdir + "asm.js");
 
 // Single-step profiling currently only works in the ARM simulator
 if (!getBuildConfiguration()["arm-simulator"])
     quit();
 
-enableSPSProfiling();
+enableGeckoProfiling();
 enableSingleStepProfiling();
 var m = asmCompile(USE_ASM + 'function f() {} return f');
 asmLink(m)();
 asmLink(m)();
--- a/js/src/jit-test/tests/asm.js/testBug1236541.js
+++ b/js/src/jit-test/tests/asm.js/testBug1236541.js
@@ -1,9 +1,9 @@
-enableSPSProfiling();
+enableGeckoProfiling();
 
 function mod() {
     "use asm";
     function f(i0) {
         i0 = i0 | 0
         switch (0) {
             case 0:
         }
--- a/js/src/jit-test/tests/asm.js/testJumpRange.js
+++ b/js/src/jit-test/tests/asm.js/testJumpRange.js
@@ -33,14 +33,14 @@ for (let threshold of [0, 50, 100, 5000,
                 var i4ext = i4.extractLane;
                 function f(i) { i=i|0; return i4ext(i4load(H, i), 0)|0 }
                 function g(i) { i=i|0; return (i4ext(toi4(f4load(H, i)),1) + (f(i)|0))|0 }
                 function h(i) { i=i|0; return g(i)|0 }
                 return h
             `)(this, null, buf)(0), 52);
     }
 
-    enableSPSProfiling();
+    enableGeckoProfiling();
     asmLink(asmCompile(USE_ASM + 'function f() {} function g() { f() } function h() { g() } return h'))();
-    disableSPSProfiling();
+    disableGeckoProfiling();
 
     assertEq(asmCompile(fatFunc)()(), 142);
 }
--- a/js/src/jit-test/tests/asm.js/testProfiling.js
+++ b/js/src/jit-test/tests/asm.js/testProfiling.js
@@ -54,36 +54,36 @@ function assertStackContainsSeq(got, exp
 
     assertEq(checkSubSequence(gotNorm.split(','), expect.split(',')), true);
 }
 
 // Test profiling enablement while asm.js is running.
 var stacks;
 var ffi = function(enable) {
     if (enable == +1)
-        enableSPSProfiling();
+        enableGeckoProfiling();
     enableSingleStepProfiling();
     stacks = disableSingleStepProfiling();
     if (enable == -1)
-        disableSPSProfiling();
+        disableGeckoProfiling();
 }
 var f = asmLink(asmCompile('global','ffis',USE_ASM + "var ffi=ffis.ffi; function g(i) { i=i|0; ffi(i|0) } function f(i) { i=i|0; g(i|0) } return f"), null, {ffi});
 f(0);
 assertStackContainsSeq(stacks, "");
 f(+1);
 assertStackContainsSeq(stacks, "");
 f(0);
 assertStackContainsSeq(stacks, "<,g,f,>");
 f(-1);
 assertStackContainsSeq(stacks, "<,g,f,>");
 f(0);
 assertStackContainsSeq(stacks, "");
 
 // Enable profiling for the rest of the tests.
-enableSPSProfiling();
+enableGeckoProfiling();
 
 var f = asmLink(asmCompile(USE_ASM + "function f() { return 42 } return f"));
 enableSingleStepProfiling();
 assertEq(f(), 42);
 var stacks = disableSingleStepProfiling();
 assertStackContainsSeq(stacks, ">,f,>,>");
 
 var m = asmCompile(USE_ASM + "function g(i) { i=i|0; return (i+1)|0 } function f() { return g(42)|0 } return f");
--- a/js/src/jit-test/tests/asm.js/testTimeout5.js
+++ b/js/src/jit-test/tests/asm.js/testTimeout5.js
@@ -1,12 +1,12 @@
 // |jit-test| exitstatus: 6;
 
 load(libdir + "asm.js");
 
-enableSPSProfiling();
+enableGeckoProfiling();
 
 var f = asmLink(asmCompile('glob', 'ffis', 'buf', USE_ASM + "function f() { var i=0; while (1) { i=(i+1)|0 } } return f"));
 timeout(1);
 if (getBuildConfiguration()["arm-simulator"])
     enableSingleStepProfiling();
 f();
 assertEq(true, false);
--- a/js/src/jit-test/tests/asm.js/testTimeout6.js
+++ b/js/src/jit-test/tests/asm.js/testTimeout6.js
@@ -1,12 +1,12 @@
 // |jit-test| exitstatus: 6;
 
 load(libdir + "asm.js");
 
-enableSPSProfiling();
+enableGeckoProfiling();
 
 var f = asmLink(asmCompile('glob', 'ffis', 'buf', USE_ASM + "function g() { var i=0; while (1) { i=(i+1)|0 } } function f() { g() } return f"));
 timeout(1);
 if (getBuildConfiguration()["arm-simulator"])
     enableSingleStepProfiling();
 f();
 assertEq(true, false);
--- a/js/src/jit-test/tests/basic/bug713226.js
+++ b/js/src/jit-test/tests/basic/bug713226.js
@@ -3,17 +3,17 @@ gczeal(4);
 var optionNames = options().split(',');
   for (var i = 0; i < optionNames.length; i++)
     var optionName = optionNames[i];
 evaluate("\
 function addDebug(g, id) {\
     var debuggerGlobal = newGlobal();\
     debuggerGlobal.debuggee = g;\
     debuggerGlobal.id = id;\
-    debuggerGlobal.print = function (s) { (g) += s; };\
+    debuggerGlobal.print = function (s) { print(s); };\
     debuggerGlobal.eval('var dbg = new Debugger(debuggee);dbg.onDebuggerStatement = function () { print(id); debugger; };');\
     return debuggerGlobal;\
 }\
 var base = newGlobal();\
 var top = base;\
 for (var i = 0; i < 8; i++ )\
     top = addDebug(top, i);\
 base.eval('debugger;');\
--- a/js/src/jit-test/tests/debug/bug1107525.js
+++ b/js/src/jit-test/tests/debug/bug1107525.js
@@ -1,9 +1,9 @@
 // |jit-test| error: InternalError
-enableSPSProfiling();
+enableGeckoProfiling();
 var g = newGlobal();
 g.parent = this;
 g.eval("new Debugger(parent).onExceptionUnwind = function () { hits++; };");
 function f() {
     var x = f();
 }
 f();
--- a/js/src/jit-test/tests/debug/bug1330489-sps.js
+++ b/js/src/jit-test/tests/debug/bug1330489-sps.js
@@ -4,17 +4,17 @@ load(libdir + "asserts.js");
 
 if (!wasmIsSupported())
     throw "TestComplete";
 
 // Single-step profiling currently only works in the ARM simulator
 if (!getBuildConfiguration()["arm-simulator"])
     throw "TestComplete";
 
-enableSPSProfiling();
+enableGeckoProfiling();
 enableSingleStepProfiling();
 
 var g = newGlobal();
 g.parent = this;
 g.eval("Debugger(parent).onExceptionUnwind = function () {};");
 
 let module = new WebAssembly.Module(wasmTextToBinary(`
     (module
@@ -35,10 +35,10 @@ let instance = new WebAssembly.Instance(
 
 try {
     instance.exports.call(0);
     assertEq(false, true);
 } catch (e) {
     assertEq(e, "test");
 }
 
-disableSPSProfiling();
+disableGeckoProfiling();
 throw "TestComplete";
--- a/js/src/jit-test/tests/gc/bug-1214846.js
+++ b/js/src/jit-test/tests/gc/bug-1214846.js
@@ -1,7 +1,7 @@
 if (!('oomTest' in this) || helperThreadCount() === 0)
     quit();
 
-enableSPSProfiling();
+enableGeckoProfiling();
 var s = newGlobal();
 s.offThreadCompileScript('oomTest(() => {});');
 s.runOffThreadScript();
--- a/js/src/jit-test/tests/gc/bug-1216607.js
+++ b/js/src/jit-test/tests/gc/bug-1216607.js
@@ -1,12 +1,12 @@
 if (!('oomTest' in this))
     quit();
 
-enableSPSProfilingWithSlowAssertions();
+enableGeckoProfilingWithSlowAssertions();
 try {
 (function() {
    while (n--) {
    }
 })();
 } catch(exc1) {}
 function arrayProtoOutOfRange() {
     function f(obj) {}
--- a/js/src/jit-test/tests/gc/bug-1234410.js
+++ b/js/src/jit-test/tests/gc/bug-1234410.js
@@ -1,10 +1,10 @@
 if (!('oomTest' in this))
     quit();
 
-enableSPSProfiling();
+enableGeckoProfiling();
 oomTest(() => {
     try {
         for (var quit of oomTest.gcparam("//").ArrayBuffer(1)) {}
     } catch (e) {}
 });
 
--- a/js/src/jit-test/tests/gc/bug-1301377.js
+++ b/js/src/jit-test/tests/gc/bug-1301377.js
@@ -1,12 +1,12 @@
 var lfLogBuffer = `
   gczeal(14);
-  enableSPSProfiling();
+  enableGeckoProfiling();
   gczeal(15,3);
   var s = "";
   for (let i = 0; i != 30; i+=2) {}
-  readSPSProfilingStack(s, "c0d1c0d1c0d1c0d1c0d1c0d1c0d1c0");
+  readGeckoProfilingStack(s, "c0d1c0d1c0d1c0d1c0d1c0d1c0d1c0");
 `;
 loadFile(lfLogBuffer);
 function loadFile(lfVarx) {
   evaluate(lfVarx);
 }
--- a/js/src/jit-test/tests/ion/bug1022081.js
+++ b/js/src/jit-test/tests/ion/bug1022081.js
@@ -1,8 +1,8 @@
 function f() {
     (function() {
         gc()
     })()
 }
-enableSPSProfiling()
+enableGeckoProfiling()
 f()
 f()
--- a/js/src/jit-test/tests/ion/bug1195590.js
+++ b/js/src/jit-test/tests/ion/bug1195590.js
@@ -1,7 +1,7 @@
 function f(x) {
     try {
         eval(x);
     } catch (e) {}
 };
-f("enableSPSProfilingWithSlowAssertions();");
+f("enableGeckoProfilingWithSlowAssertions();");
 f("enableTrackAllocations(); throw Error();");
--- a/js/src/jit-test/tests/ion/bug1246154.js
+++ b/js/src/jit-test/tests/ion/bug1246154.js
@@ -1,5 +1,5 @@
 setJitCompilerOption('ion.forceinlineCaches', 1);
-enableSPSProfiling();
+enableGeckoProfiling();
 (function() {
     -[];
 })();
--- a/js/src/jit-test/tests/ion/bug875656.js
+++ b/js/src/jit-test/tests/ion/bug875656.js
@@ -1,2 +1,2 @@
-enableSPSProfiling();
+enableGeckoProfiling();
 Object.getOwnPropertyNames(this);
--- a/js/src/jit-test/tests/ion/bug901086.js
+++ b/js/src/jit-test/tests/ion/bug901086.js
@@ -1,9 +1,9 @@
-enableSPSProfiling();
+enableGeckoProfiling();
 function foo(obj,x,y,z) {
     if (!y)
 	assertEq(0, 1);
     obj.x = x;
     return y + z;
 }
 function bar() {
     var objz = {x:2}
--- a/js/src/jit-test/tests/ion/bug925308.js
+++ b/js/src/jit-test/tests/ion/bug925308.js
@@ -1,13 +1,13 @@
 // |jit-test| error: ReferenceError
 
 var lfcode = new Array();
 lfcode.push("3");
-lfcode.push("enableSPSProfiling();foo();");
+lfcode.push("enableGeckoProfiling();foo();");
 while (true) {
   var file = lfcode.shift(); if (file == undefined) { break; }
   loadFile(file)
 }
 function loadFile(lfVarx) {
     if (lfVarx.substr(-3) != ".js" && lfVarx.length != 1) {
         switch (lfRunTypeId) {
             default: function newFunc(x) { new Function(x)(); }; newFunc(lfVarx); break;
--- a/js/src/jit-test/tests/parser/bug-1263355-44.js
+++ b/js/src/jit-test/tests/parser/bug-1263355-44.js
@@ -1,9 +1,9 @@
 if (!('oomTest' in this))
   quit();
 
 // Adapted from randomly chosen test: js/src/jit-test/tests/profiler/bug1231925.js
 "use strict";
-enableSPSProfiling();
+enableGeckoProfiling();
 oomTest(function() {
     eval("(function() {})()");
 });
--- a/js/src/jit-test/tests/profiler/AutoEntryMonitor-01.js
+++ b/js/src/jit-test/tests/profiler/AutoEntryMonitor-01.js
@@ -26,17 +26,17 @@ var sety = { set y(v) { } };
 cold_and_warm(Object.getOwnPropertyDescriptor(sety, 'y').set,
               { object: sety, property: 'y', value: 'glerk' }, [ "set y" ]);
 
 cold_and_warm(Object.prototype.toString, { ToString: {} }, []);
 
 var toS = { toString: function myToString() { return "string"; } };
 cold_and_warm(toS.toString, { ToString: toS }, [ "myToString" ]);
 
-cold_and_warm(undefined, { ToNumber: {} }, []);
+cold_and_warm(undefined, { ToNumber: 5 }, []);
 
 var vOf = { valueOf: function myValueOf() { return 42; } };
 cold_and_warm(vOf.valueOf, { ToNumber: vOf }, [ "myValueOf" ]);
 
 var toSvOf = { toString: function relations() { return Object; },
                valueOf: function wallpaper() { return 17; } };
 cold_and_warm(() => {  toSvOf.toString(); toSvOf.valueOf(); },
               { ToString: toSvOf }, [ "relations", "wallpaper" ]);
--- a/js/src/jit-test/tests/profiler/bug1135703.js
+++ b/js/src/jit-test/tests/profiler/bug1135703.js
@@ -1,6 +1,6 @@
 
 for (var idx = 0; idx < 20; ++idx) {
-  newFunc("enableSPSProfilingWithSlowAssertions(); disableSPSProfiling();");
+  newFunc("enableGeckoProfilingWithSlowAssertions(); disableGeckoProfiling();");
 }
-newFunc("enableSPSProfiling();");
+newFunc("enableGeckoProfiling();");
 function newFunc(x) { new Function(x)(); };
--- a/js/src/jit-test/tests/profiler/bug1140643.js
+++ b/js/src/jit-test/tests/profiler/bug1140643.js
@@ -1,10 +1,10 @@
 // |jit-test| allow-oom
-enableSPSProfiling();
+enableGeckoProfiling();
 loadFile('\
 for (var i = 0; i < 2; i++) {\
     obj = { m: function () {} };\
     obj.watch("m", function () { float32 = 0 + obj.foo; });\
     obj.m = 0;\
 }\
 ');
 gcparam("maxBytes", gcparam("gcBytes") + (1)*1024);
--- a/js/src/jit-test/tests/profiler/bug1161351.js
+++ b/js/src/jit-test/tests/profiler/bug1161351.js
@@ -1,16 +1,16 @@
 function x() { n; }
 function f() {
   try  { x(); } catch(ex) {}
 }
 var g = newGlobal();
 g.parent = this;
 g.eval("new Debugger(parent).onExceptionUnwind = function () {};");
-enableSPSProfiling();
+enableGeckoProfiling();
 try {
   enableSingleStepProfiling();
 } catch (e) {
   // Not all platforms support single-step profiling.
 }
 f();
 f();
 f();
--- a/js/src/jit-test/tests/profiler/bug1164448.js
+++ b/js/src/jit-test/tests/profiler/bug1164448.js
@@ -10,17 +10,17 @@ function TestCase(n, d, e, a) {
 function jsTestDriverEnd() {
   for (var i = 0; i < gTestcases.length; i++)
     gTestcases[i].dump();
 }
 TestCase();
 var g = newGlobal();
 g.parent = this;
 g.eval("new Debugger(parent).onExceptionUnwind = function () {};");
-enableSPSProfiling();
+enableGeckoProfiling();
 if (getBuildConfiguration()["arm-simulator"])
     enableSingleStepProfiling(1);
 loadFile("jsTestDriverEnd();");
 loadFile("jsTestDriverEnd();");
 jsTestDriverEnd();
 function loadFile(lfVarx) {
     try { evaluate(lfVarx); } catch (lfVare) {}
 }
--- a/js/src/jit-test/tests/profiler/bug1211962.js
+++ b/js/src/jit-test/tests/profiler/bug1211962.js
@@ -1,12 +1,12 @@
 // |jit-test| slow;
 if (!('oomTest' in this))
     quit();
 
-enableSPSProfiling();
+enableGeckoProfiling();
 var lfGlobal = newGlobal();
 for (lfLocal in this) {
     lfGlobal[lfLocal] = this[lfLocal];
 }
 const script = 'oomTest(() => getBacktrace({args: true, locals: "123795", thisprops: true}));';
 lfGlobal.offThreadCompileScript(script);
 lfGlobal.runOffThreadScript();
--- a/js/src/jit-test/tests/profiler/bug1231925.js
+++ b/js/src/jit-test/tests/profiler/bug1231925.js
@@ -1,7 +1,7 @@
 if (!('oomTest' in this))
   quit();
 
-enableSPSProfiling();
+enableGeckoProfiling();
 oomTest(function() {
     eval("(function() {})()")
 });
--- a/js/src/jit-test/tests/profiler/bug1233921.js
+++ b/js/src/jit-test/tests/profiler/bug1233921.js
@@ -1,12 +1,12 @@
 g = newGlobal();
 g.parent = this;
 g.eval("new Debugger(parent).onExceptionUnwind = function () {}");
-enableSPSProfiling();
+enableGeckoProfiling();
 try {
     enableSingleStepProfiling();
 } catch(e) {
     quit();
 }
 f();
 f();
 function $ERROR() {
--- a/js/src/jit-test/tests/profiler/bug1242840.js
+++ b/js/src/jit-test/tests/profiler/bug1242840.js
@@ -1,12 +1,12 @@
 if (!('oomTest' in this))
     quit();
 
-enableSPSProfiling();
+enableGeckoProfiling();
 oomTest(() => {
     try {
         for (quit of ArrayBuffer);
     } catch (e) {
         switch (1) {
             case 0:
                 let x
             case 1:
--- a/js/src/jit-test/tests/profiler/bug1261324.js
+++ b/js/src/jit-test/tests/profiler/bug1261324.js
@@ -1,12 +1,12 @@
 g = newGlobal()
 g.parent = this
 g.eval("new Debugger(parent).onExceptionUnwind = function () {}")
-enableSPSProfiling()
+enableGeckoProfiling()
 
 try {
   // Only the ARM simulator supports single step profiling.
   enableSingleStepProfiling();
 } catch (e) {
   quit();
 }
 
--- a/js/src/jit-test/tests/profiler/bug925309.js
+++ b/js/src/jit-test/tests/profiler/bug925309.js
@@ -1,2 +1,2 @@
 
-for(var i = 0; i < 100; enableSPSProfiling(), i++) {}
+for(var i = 0; i < 100; enableGeckoProfiling(), i++) {}
--- a/js/src/jit-test/tests/profiler/debugmode-osr-exception-return-addr.js
+++ b/js/src/jit-test/tests/profiler/debugmode-osr-exception-return-addr.js
@@ -1,14 +1,14 @@
 // |jit-test| error: ReferenceError
 
 var g = newGlobal();
 g.parent = this;
 g.eval("new Debugger(parent).onExceptionUnwind = function () { };");
-enableSPSProfiling();
+enableGeckoProfiling();
 
 try {
   // Only the ARM simulator supports single step profiling.
   enableSingleStepProfiling();
 } catch (e) {
   throw new ReferenceError;
 }
 
--- a/js/src/jit-test/tests/profiler/debugmode-osr-resume-addr.js
+++ b/js/src/jit-test/tests/profiler/debugmode-osr-resume-addr.js
@@ -1,9 +1,9 @@
-enableSPSProfiling();
+enableGeckoProfiling();
 try {
   // Only the ARM simulator supports single step profiling.
   enableSingleStepProfiling();
 } catch (e) {
   quit(0);
 }
 var g = newGlobal();
 var dbg = Debugger(g);
--- a/js/src/jit-test/tests/profiler/enterjit-osr-disabling-earlyret.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr-disabling-earlyret.js
@@ -1,13 +1,13 @@
 setJitCompilerOption("baseline.warmup.trigger", 10);
 setJitCompilerOption("ion.warmup.trigger", 20);
 
-enableSPSProfilingWithSlowAssertions();
+enableGeckoProfilingWithSlowAssertions();
 (function() {
    var n = 50;
    while (n--) {
-       disableSPSProfiling();
+       disableGeckoProfiling();
        if (!n)
 	   return;
-       enableSPSProfilingWithSlowAssertions();
+       enableGeckoProfilingWithSlowAssertions();
    }
 })();
--- a/js/src/jit-test/tests/profiler/enterjit-osr-disabling.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr-disabling.js
@@ -1,9 +1,9 @@
 setJitCompilerOption("baseline.warmup.trigger", 10);
 setJitCompilerOption("ion.warmup.trigger", 20);
 
-enableSPSProfilingWithSlowAssertions();
+enableGeckoProfilingWithSlowAssertions();
 (function() {
-   disableSPSProfiling();
+   disableGeckoProfiling();
    var n = 50;
    while (n--);
 })();
--- a/js/src/jit-test/tests/profiler/enterjit-osr-enabling-earlyret.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr-enabling-earlyret.js
@@ -1,12 +1,12 @@
 setJitCompilerOption("baseline.warmup.trigger", 10);
 setJitCompilerOption("ion.warmup.trigger", 20);
 
 (function() {
    var n = 50;
    while (n--) {
-       enableSPSProfilingWithSlowAssertions();
+       enableGeckoProfilingWithSlowAssertions();
        if (!n)
 	   return;
-       disableSPSProfiling();
+       disableGeckoProfiling();
    }
 })();
--- a/js/src/jit-test/tests/profiler/enterjit-osr-enabling.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr-enabling.js
@@ -1,8 +1,8 @@
 setJitCompilerOption("baseline.warmup.trigger", 10);
 setJitCompilerOption("ion.warmup.trigger", 20);
 
 (function() {
-   enableSPSProfilingWithSlowAssertions();
+   enableGeckoProfilingWithSlowAssertions();
    var n = 50;
    while (n--);
 })();
--- a/js/src/jit-test/tests/profiler/enterjit-osr.js
+++ b/js/src/jit-test/tests/profiler/enterjit-osr.js
@@ -1,8 +1,8 @@
 setJitCompilerOption("baseline.warmup.trigger", 10);
 setJitCompilerOption("ion.warmup.trigger", 20);
 
-enableSPSProfilingWithSlowAssertions();
+enableGeckoProfilingWithSlowAssertions();
 (function() {
    var n = 50;
    while (n--);
 })();
--- a/js/src/jit-test/tests/profiler/getter-setter-ic.js
+++ b/js/src/jit-test/tests/profiler/getter-setter-ic.js
@@ -1,32 +1,32 @@
-// Ensure readSPSProfilingStack() doesn't crash with Ion
+// Ensure readGeckoProfilingStack() doesn't crash with Ion
 // getter/setter ICs on the stack.
 function getObjects() {
     var objs = [];
     objs.push({x: 0, get prop() {
-	readSPSProfilingStack();
+	readGeckoProfilingStack();
 	return ++this.x;
     }, set prop(v) {
-	readSPSProfilingStack();
+	readGeckoProfilingStack();
 	this.x = v + 2;
     }});
     objs.push({x: 0, y: 0, get prop() {
-	readSPSProfilingStack();
+	readGeckoProfilingStack();
 	return this.y;
     }, set prop(v) {
-	readSPSProfilingStack();
+	readGeckoProfilingStack();
 	this.y = v;
     }});
     return objs;
 }
 function f() {
     var objs = getObjects();
     var res = 0;
     for (var i=0; i<100; i++) {
 	var o = objs[i % objs.length];
 	res += o.prop;
 	o.prop = i;
     }
     assertEq(res, 4901);
 }
-enableSPSProfiling();
+enableGeckoProfiling();
 f();
--- a/js/src/jit-test/tests/profiler/test-baseline-eval-frame-profiling.js
+++ b/js/src/jit-test/tests/profiler/test-baseline-eval-frame-profiling.js
@@ -1,11 +1,11 @@
 
 setJitCompilerOption("baseline.warmup.trigger", 10);
 
 function main() {
     for (var i = 0; i < 50; i++)
-        eval("for (var j = 0; j < 50; j++) readSPSProfilingStack();");
+        eval("for (var j = 0; j < 50; j++) readGeckoProfilingStack();");
 }
 
 gczeal(2, 10000);
-enableSPSProfilingWithSlowAssertions();
+enableGeckoProfilingWithSlowAssertions();
 main();
--- a/js/src/jit-test/tests/profiler/test-bug1026485.js
+++ b/js/src/jit-test/tests/profiler/test-bug1026485.js
@@ -1,13 +1,13 @@
 
 function TestCase(n, d, e, a) {
   return TestCase.prototype.dump = function () {};
 }
-enableSPSProfiling();
+enableGeckoProfiling();
 new TestCase(typeof Number(new Number()));
 new TestCase(typeof Number(new Number(Number.NaN)));
 test();
 function test() {
     try {
         test();
     } catch (e) {
         new TestCase();
--- a/js/src/jit-test/tests/wasm/basic.js
+++ b/js/src/jit-test/tests/wasm/basic.js
@@ -415,34 +415,34 @@ assertEq(i2i(5, 100), 104);
 assertErrorMessage(() => i2v(0), Error, signatureMismatch);
 assertErrorMessage(() => i2v(1), Error, signatureMismatch);
 assertErrorMessage(() => i2v(2), Error, signatureMismatch);
 assertErrorMessage(() => i2v(3), Error, signatureMismatch);
 assertErrorMessage(() => i2v(4), Error, signatureMismatch);
 assertErrorMessage(() => i2v(5), Error, signatureMismatch);
 
 {
-    enableSPSProfiling();
+    enableGeckoProfiling();
 
     var stack;
     wasmFullPass(
         `(module
             (type $v2v (func))
             (import $foo "" "f")
             (func $a (call $foo))
             (func $b (result i32) (i32.const 0))
             (table anyfunc (elem $a $b))
             (func $bar (call_indirect $v2v (i32.const 0)))
             (export "run" $bar)
         )`,
         undefined,
         {"":{f:() => { stack = new Error().stack }}}
     );
 
-    disableSPSProfiling();
+    disableGeckoProfiling();
 
     var inner = stack.indexOf("wasm-function[1]");
     var outer = stack.indexOf("wasm-function[3]");
     assertEq(inner === -1, false);
     assertEq(outer === -1, false);
     assertEq(inner < outer, true);
 }
 
--- a/js/src/jit-test/tests/wasm/profiling.js
+++ b/js/src/jit-test/tests/wasm/profiling.js
@@ -59,24 +59,24 @@ function assertEqStacks(got, expect)
             print(`On stack ${i}, Got:\n${got[i]}\nExpect:\n${expect[i]}`);
             assertEq(got[i], expect[i]);
         }
     }
 }
 
 function test(code, importObj, expect)
 {
-    enableSPSProfiling();
+    enableGeckoProfiling();
 
     var f = wasmEvalText(code, importObj).exports[""];
     enableSingleStepProfiling();
     f();
     assertEqStacks(disableSingleStepProfiling(), expect);
 
-    disableSPSProfiling();
+    disableGeckoProfiling();
 }
 
 test(
 `(module
     (func (result i32) (i32.const 42))
     (export "" 0)
 )`,
 {},
@@ -108,22 +108,22 @@ test(
     (func $bar (call_indirect 0 (i32.const 0)))
     (export "" $bar)
 )`,
 {"":{foo:()=>{}}},
 ["", ">", "1,>", "0,1,>", "<,0,1,>", "0,1,>", "1,>", ">", ""]);
 
 function testError(code, error, expect)
 {
-    enableSPSProfiling();
+    enableGeckoProfiling();
     var f = wasmEvalText(code).exports[""];
     enableSingleStepProfiling();
     assertThrowsInstanceOf(f, error);
     assertEqStacks(disableSingleStepProfiling(), expect);
-    disableSPSProfiling();
+    disableGeckoProfiling();
 }
 
 testError(
 `(module
     (func $foo (unreachable))
     (func (export "") (call $foo))
 )`,
 WebAssembly.RuntimeError,
@@ -153,95 +153,95 @@ WebAssembly.RuntimeError,
         (table 10 anyfunc)
         (elem (i32.const 0) $foo $bar)
         (export "tbl" table)
     )`).exports;
     assertEq(e.foo(), 42);
     assertEq(e.tbl.get(0)(), 42);
     assertEq(e.tbl.get(1)(), 13);
 
-    enableSPSProfiling();
+    enableGeckoProfiling();
     enableSingleStepProfiling();
     assertEq(e.tbl.get(0)(), 42);
     assertEqStacks(disableSingleStepProfiling(), ["", ">", "0,>", ">", ""]);
-    disableSPSProfiling();
+    disableGeckoProfiling();
 
     assertEq(e.foo(), 42);
     assertEq(e.tbl.get(0)(), 42);
     assertEq(e.tbl.get(1)(), 13);
 
-    enableSPSProfiling();
+    enableGeckoProfiling();
     enableSingleStepProfiling();
     assertEq(e.tbl.get(1)(), 13);
     assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", ">", ""]);
-    disableSPSProfiling();
+    disableGeckoProfiling();
 
     assertEq(e.tbl.get(0)(), 42);
     assertEq(e.tbl.get(1)(), 13);
     assertEq(e.foo(), 42);
 
-    enableSPSProfiling();
+    enableGeckoProfiling();
     enableSingleStepProfiling();
     assertEq(e.foo(), 42);
     assertEq(e.tbl.get(1)(), 13);
     assertEqStacks(disableSingleStepProfiling(), ["", ">", "0,>", ">", "", ">", "1,>", ">", ""]);
-    disableSPSProfiling();
+    disableGeckoProfiling();
 
     var e2 = wasmEvalText(`
     (module
         (type $v2i (func (result i32)))
         (import "a" "b" (table 10 anyfunc))
         (elem (i32.const 2) $bar)
         (func $bar (result i32) (i32.const 99))
         (func $baz (param $i i32) (result i32) (call_indirect $v2i (get_local $i)))
         (export "baz" $baz)
     )`, {a:{b:e.tbl}}).exports;
 
-    enableSPSProfiling();
+    enableGeckoProfiling();
     enableSingleStepProfiling();
     assertEq(e2.baz(0), 42);
     assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
-    disableSPSProfiling();
+    disableGeckoProfiling();
 
-    enableSPSProfiling();
+    enableGeckoProfiling();
     enableSingleStepProfiling();
     assertEq(e2.baz(1), 13);
     assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "1,1,>", "1,>", ">", ""]);
-    disableSPSProfiling();
+    disableGeckoProfiling();
 
-    enableSPSProfiling();
+    enableGeckoProfiling();
     enableSingleStepProfiling();
     assertEq(e2.baz(2), 99);
     assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
-    disableSPSProfiling();
+    disableGeckoProfiling();
 })();
 
 (function() {
     var m1 = new Module(wasmTextToBinary(`(module
         (func $foo (result i32) (i32.const 42))
         (export "foo" $foo)
     )`));
     var m2 = new Module(wasmTextToBinary(`(module
         (import $foo "a" "foo" (result i32))
         (func $bar (result i32) (call $foo))
         (export "bar" $bar)
     )`));
 
     // Instantiate while not active:
     var e1 = new Instance(m1).exports;
     var e2 = new Instance(m2, {a:e1}).exports;
-    enableSPSProfiling();
+    enableGeckoProfiling();
     enableSingleStepProfiling();
     assertEq(e2.bar(), 42);
     assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
-    disableSPSProfiling();
+    disableGeckoProfiling();
     assertEq(e2.bar(), 42);
 
     // Instantiate while active:
-    enableSPSProfiling();
+    enableGeckoProfiling();
     var e3 = new Instance(m1).exports;
     var e4 = new Instance(m2, {a:e3}).exports;
     enableSingleStepProfiling();
     assertEq(e4.bar(), 42);
     assertEqStacks(disableSingleStepProfiling(), ["", ">", "1,>", "0,1,>", "1,>", ">", ""]);
-    disableSPSProfiling();
+    disableGeckoProfiling();
     assertEq(e4.bar(), 42);
 })();
--- a/js/src/jit-test/tests/wasm/regress/null-metadata-filename.js
+++ b/js/src/jit-test/tests/wasm/regress/null-metadata-filename.js
@@ -1,9 +1,9 @@
-if (typeof enableSPSProfiling === 'undefined' || !isAsmJSCompilationAvailable())
+if (typeof enableGeckoProfiling === 'undefined' || !isAsmJSCompilationAvailable())
     quit();
 
-enableSPSProfiling();
+enableGeckoProfiling();
 var code = evaluate("(function() { 'use asm'; function g() { return 43 } return g })", {
     fileName: null
 });
 
 assertEq(code()(), 43);
--- a/js/src/jit/Bailouts.cpp
+++ b/js/src/jit/Bailouts.cpp
@@ -57,17 +57,17 @@ jit::Bailout(BailoutStack* sp, BaselineB
     MOZ_ASSERT(retval == BAILOUT_RETURN_OK ||
                retval == BAILOUT_RETURN_FATAL_ERROR ||
                retval == BAILOUT_RETURN_OVERRECURSED);
     MOZ_ASSERT_IF(retval == BAILOUT_RETURN_OK, *bailoutInfo != nullptr);
 
     if (retval != BAILOUT_RETURN_OK) {
         JSScript* script = iter.script();
         probes::ExitScript(cx, script, script->functionNonDelazifying(),
-                           /* popSPSFrame = */ false);
+                           /* popProfilerFrame = */ false);
     }
 
     // This condition was wrong when we entered this bailout function, but it
     // might be true now. A GC might have reclaimed all the Jit code and
     // invalidated all frames which are currently on the stack. As we are
     // already in a bailout, we could not switch to an invalidation
     // bailout. When the code of an IonScript which is on the stack is
     // invalidated (see InvalidateActivation), we remove references to it and
@@ -131,28 +131,28 @@ jit::InvalidationBailout(InvalidationBai
     MOZ_ASSERT(retval == BAILOUT_RETURN_OK ||
                retval == BAILOUT_RETURN_FATAL_ERROR ||
                retval == BAILOUT_RETURN_OVERRECURSED);
     MOZ_ASSERT_IF(retval == BAILOUT_RETURN_OK, *bailoutInfo != nullptr);
 
     if (retval != BAILOUT_RETURN_OK) {
         // If the bailout failed, then bailout trampoline will pop the
         // current frame and jump straight to exception handling code when
-        // this function returns.  Any SPS entry pushed for this frame will
-        // be silently forgotten.
+        // this function returns.  Any Gecko Profiler entry pushed for this
+        // frame will be silently forgotten.
         //
-        // We call ExitScript here to ensure that if the ionScript had SPS
-        // instrumentation, then the SPS entry for it is popped.
+        // We call ExitScript here to ensure that if the ionScript had Gecko
+        // Profiler instrumentation, then the entry for it is popped.
         //
         // However, if the bailout was during argument check, then a
         // pseudostack frame would not have been pushed in the first
         // place, so don't pop anything in that case.
         JSScript* script = iter.script();
         probes::ExitScript(cx, script, script->functionNonDelazifying(),
-                           /* popSPSFrame = */ false);
+                           /* popProfilerFrame = */ false);
 
 #ifdef JS_JITSPEW
         JitFrameLayout* frame = iter.jsFrame();
         JitSpew(JitSpew_IonInvalidate, "Bailout failed (%s)",
                 (retval == BAILOUT_RETURN_FATAL_ERROR) ? "Fatal Error" : "Over Recursion");
         JitSpew(JitSpew_IonInvalidate, "   calleeToken %p", (void*) frame->calleeToken());
         JitSpew(JitSpew_IonInvalidate, "   frameSize %u", unsigned(frame->prevFrameLocalSize()));
         JitSpew(JitSpew_IonInvalidate, "   ra %p", (void*) frame->returnAddress());
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -1174,17 +1174,17 @@ InitFromBailout(JSContext* cx, HandleScr
 
             } else {
                 opReturnAddr = nativeCodeForPC;
             }
             builder.setResumeAddr(opReturnAddr);
             JitSpew(JitSpew_BaselineBailouts, "      Set resumeAddr=%p", opReturnAddr);
         }
 
-        if (cx->runtime()->spsProfiler.enabled()) {
+        if (cx->runtime()->geckoProfiler.enabled()) {
             // Register bailout with profiler.
             const char* filename = script->filename();
             if (filename == nullptr)
                 filename = "<unknown>";
             unsigned len = strlen(filename) + 200;
             char* buf = js_pod_malloc<char>(len);
             if (buf == nullptr) {
                 ReportOutOfMemory(cx);
@@ -1192,17 +1192,17 @@ InitFromBailout(JSContext* cx, HandleScr
             }
             snprintf(buf, len, "%s %s %s on line %u of %s:%" PRIuSIZE,
                      BailoutKindString(bailoutKind),
                      resumeAfter ? "after" : "at",
                      CodeName[op],
                      PCToLineNumber(script, pc),
                      filename,
                      script->lineno());
-            cx->runtime()->spsProfiler.markEvent(buf);
+            cx->runtime()->geckoProfiler.markEvent(buf);
             js_free(buf);
         }
 
         return true;
     }
 
     *callPC = pc;
 
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -4413,17 +4413,17 @@ BaselineCompiler::emit_JSOP_RESUME()
     masm.pushReturnAddress();
 #endif
 
     // If profiler instrumentation is on, update lastProfilingFrame on
     // current JitActivation
     {
         Register scratchReg = scratch2;
         Label skip;
-        AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
         masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skip);
         masm.loadPtr(AbsoluteAddress(cx->runtime()->addressOfProfilingActivation()), scratchReg);
         masm.storePtr(masm.getStackPointer(),
                       Address(scratchReg, JitActivation::offsetOfLastProfilingFrame()));
         masm.bind(&skip);
     }
 
     // Construct BaselineFrame.
--- a/js/src/jit/BaselineDebugModeOSR.cpp
+++ b/js/src/jit/BaselineDebugModeOSR.cpp
@@ -438,17 +438,17 @@ PatchBaselineFramesForDebugMode(JSContex
                 // If profiling is off, patch the resume address to nullptr,
                 // to ensure the old address is not used anywhere.
                 //
                 // If profiling is on, JitProfilingFrameIterator requires a
                 // valid return address.
                 MOZ_ASSERT(iter.baselineFrame()->isHandlingException());
                 MOZ_ASSERT(iter.baselineFrame()->overridePc() == pc);
                 uint8_t* retAddr;
-                if (cx->runtime()->spsProfiler.enabled())
+                if (cx->runtime()->geckoProfiler.enabled())
                     retAddr = bl->nativeCodeForPC(script, pc);
                 else
                     retAddr = nullptr;
                 SpewPatchBaselineFrameFromExceptionHandler(prev->returnAddress(), retAddr,
                                                            script, pc);
                 DebugModeOSRVolatileJitFrameIterator::forwardLiveIterators(
                     cx, prev->returnAddress(), retAddr);
                 prev->setReturnAddress(retAddr);
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -147,17 +147,17 @@ DoWarmUpCounterFallbackOSR(JSContext* cx
     if (!script->hasIonScript() || script->ionScript()->osrPc() != pc ||
         script->ionScript()->bailoutExpected() ||
         frame->isDebuggee())
     {
         return true;
     }
 
     IonScript* ion = script->ionScript();
-    MOZ_ASSERT(cx->runtime()->spsProfiler.enabled() == ion->hasProfilingInstrumentation());
+    MOZ_ASSERT(cx->runtime()->geckoProfiler.enabled() == ion->hasProfilingInstrumentation());
     MOZ_ASSERT(ion->osrPc() == pc);
 
     JitSpew(JitSpew_BaselineOSR, "  OSR possible!");
     void* jitcode = ion->method()->raw() + ion->osrEntryOffset();
 
     // Prepare the temporary heap copy of the fake InterpreterFrame and actual args list.
     JitSpew(JitSpew_BaselineOSR, "Got jitcode.  Preparing for OSR into ion.");
     IonOsrTempData* info = PrepareOsrTempData(cx, stub, frame, script, pc, jitcode);
@@ -229,17 +229,17 @@ ICWarmUpCounter_Fallback::Compiler::gene
     // the stack.
     masm.pop(scratchReg);
 
 #ifdef DEBUG
     // If profiler instrumentation is on, ensure that lastProfilingFrame is
     // the frame currently being OSR-ed
     {
         Label checkOk;
-        AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
         masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &checkOk);
         masm.loadPtr(AbsoluteAddress((void*)&cx->runtime()->jitActivation), scratchReg);
         masm.loadPtr(Address(scratchReg, JitActivation::offsetOfLastProfilingFrame()), scratchReg);
 
         // It may be the case that we entered the baseline frame with
         // profiling turned off on, then in a call within a loop (i.e. a
         // callee frame), turn on profiling, then return to this frame,
         // and then OSR with profiling turned on.  In this case, allow for
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -9797,17 +9797,18 @@ CodeGenerator::link(JSContext* cx, Compi
 
         // Mark the jitcode as having a bytecode map.
         code->setHasBytecodeMap();
     }
 
     ionScript->setMethod(code);
     ionScript->setSkipArgCheckEntryOffset(getSkipArgCheckEntryOffset());
 
-    // If SPS is enabled, mark IonScript as having been instrumented with SPS
+    // If the Gecko Profiler is enabled, mark IonScript as having been
+    // instrumented accordingly.
     if (isProfilerInstrumentationEnabled())
         ionScript->setHasProfilingInstrumentation();
 
     script->setIonScript(cx->runtime(), ionScript);
 
     // Adopt fallback shared stubs from the compiler into the ion script.
     ionScript->adoptFallbackStubs(&stubSpace_);
 
--- a/js/src/jit/CompileWrappers.cpp
+++ b/js/src/jit/CompileWrappers.cpp
@@ -95,20 +95,20 @@ CompileRuntime::getJSContext()
 }
 
 const JitRuntime*
 CompileRuntime::jitRuntime()
 {
     return runtime()->jitRuntime();
 }
 
-SPSProfiler&
-CompileRuntime::spsProfiler()
+GeckoProfiler&
+CompileRuntime::geckoProfiler()
 {
-    return runtime()->spsProfiler;
+    return runtime()->geckoProfiler;
 }
 
 bool
 CompileRuntime::jitSupportsFloatingPoint()
 {
     return runtime()->jitSupportsFloatingPoint;
 }
 
@@ -291,20 +291,20 @@ CompileCompartment::hasAllocationMetadat
 void
 CompileCompartment::setSingletonsAsValues()
 {
     compartment()->behaviors().setSingletonsAsValues();
 }
 
 JitCompileOptions::JitCompileOptions()
   : cloneSingletons_(false),
-    spsSlowAssertionsEnabled_(false),
+    profilerSlowAssertionsEnabled_(false),
     offThreadCompilationAvailable_(false)
 {
 }
 
 JitCompileOptions::JitCompileOptions(JSContext* cx)
 {
     cloneSingletons_ = cx->compartment()->creationOptions().cloneSingletons();
-    spsSlowAssertionsEnabled_ = cx->runtime()->spsProfiler.enabled() &&
-                                cx->runtime()->spsProfiler.slowAssertionsEnabled();
+    profilerSlowAssertionsEnabled_ = cx->runtime()->geckoProfiler.enabled() &&
+                                     cx->runtime()->geckoProfiler.slowAssertionsEnabled();
     offThreadCompilationAvailable_ = OffThreadCompilationAvailable(cx);
 }
--- a/js/src/jit/CompileWrappers.h
+++ b/js/src/jit/CompileWrappers.h
@@ -58,18 +58,18 @@ class CompileRuntime
     const void* addressOfInterruptUint32();
 
     // We have to bake JSContext* into JIT code, but this pointer shouldn't be
     // used/dereferenced on the background thread so we return it as void*.
     const void* getJSContext();
 
     const JitRuntime* jitRuntime();
 
-    // Compilation does not occur off thread when the SPS profiler is enabled.
-    SPSProfiler& spsProfiler();
+    // Compilation does not occur off thread when the Gecko Profiler is enabled.
+    GeckoProfiler& geckoProfiler();
 
     bool jitSupportsFloatingPoint();
     bool hadOutOfMemory();
     bool profilingScripts();
 
     const JSAtomState& names();
     const PropertyName* emptyString();
     const StaticStrings& staticStrings();
@@ -133,26 +133,26 @@ class JitCompileOptions
   public:
     JitCompileOptions();
     explicit JitCompileOptions(JSContext* cx);
 
     bool cloneSingletons() const {
         return cloneSingletons_;
     }
 
-    bool spsSlowAssertionsEnabled() const {
-        return spsSlowAssertionsEnabled_;
+    bool profilerSlowAssertionsEnabled() const {
+        return profilerSlowAssertionsEnabled_;
     }
 
     bool offThreadCompilationAvailable() const {
         return offThreadCompilationAvailable_;
     }
 
   private:
     bool cloneSingletons_;
-    bool spsSlowAssertionsEnabled_;
+    bool profilerSlowAssertionsEnabled_;
     bool offThreadCompilationAvailable_;
 };
 
 } // namespace jit
 } // namespace js
 
 #endif // jit_CompileWrappers_h
--- a/js/src/jit/ExecutableAllocatorWin.cpp
+++ b/js/src/jit/ExecutableAllocatorWin.cpp
@@ -157,33 +157,35 @@ RegisterExecutableMemory(void* p, size_t
     // jmp rax
     r->thunk[10] = 0xff;
     r->thunk[11] = 0xe0;
 
     if (!VirtualProtect(p, pageSize, PAGE_EXECUTE_READ, &oldProtect))
         return false;
 
     // XXX NB: The profiler believes this function is only called from the main
-    // thread. If that ever becomes untrue, SPS must be updated immediately.
+    // thread. If that ever becomes untrue, the profiler must be updated
+    // immediately.
     AcquireStackWalkWorkaroundLock();
 
     bool success = RtlAddFunctionTable(&r->runtimeFunction, 1, reinterpret_cast<DWORD64>(p));
 
     ReleaseStackWalkWorkaroundLock();
 
     return success;
 }
 
 static void
 UnregisterExecutableMemory(void* p, size_t bytes, size_t pageSize)
 {
     ExceptionHandlerRecord* r = reinterpret_cast<ExceptionHandlerRecord*>(p);
 
     // XXX NB: The profiler believes this function is only called from the main
-    // thread. If that ever becomes untrue, SPS must be updated immediately.
+    // thread. If that ever becomes untrue, the profiler must be updated
+    // immediately.
     AcquireStackWalkWorkaroundLock();
 
     RtlDeleteFunctionTable(&r->runtimeFunction);
 
     ReleaseStackWalkWorkaroundLock();
 }
 #endif
 
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -614,17 +614,17 @@ JitRuntime::Trace(JSTracer* trc, AutoLoc
         JitCode* code = i;
         TraceRoot(trc, &code, "wrapper");
     }
 }
 
 /* static */ void
 JitRuntime::TraceJitcodeGlobalTable(JSTracer* trc)
 {
-    if (trc->runtime()->spsProfiler.enabled() &&
+    if (trc->runtime()->geckoProfiler.enabled() &&
         trc->runtime()->hasJitRuntime() &&
         trc->runtime()->jitRuntime()->hasJitcodeGlobalTable())
     {
         trc->runtime()->jitRuntime()->getJitcodeGlobalTable()->trace(trc);
     }
 }
 
 /* static */ bool
@@ -3316,32 +3316,32 @@ jit::IonScript::invalidate(JSContext* cx
     Invalidate(cx, list, resetUses, true);
 }
 
 void
 jit::Invalidate(JSContext* cx, JSScript* script, bool resetUses, bool cancelOffThread)
 {
     MOZ_ASSERT(script->hasIonScript());
 
-    if (cx->runtime()->spsProfiler.enabled()) {
+    if (cx->runtime()->geckoProfiler.enabled()) {
         // Register invalidation with profiler.
         // Format of event payload string:
         //      "<filename>:<lineno>"
 
         // Get the script filename, if any, and its length.
         const char* filename = script->filename();
         if (filename == nullptr)
             filename = "<unknown>";
 
         // Construct the descriptive string.
         char* buf = JS_smprintf("Invalidate %s:%" PRIuSIZE, filename, script->lineno());
 
         // Ignore the event on allocation failure.
         if (buf) {
-            cx->runtime()->spsProfiler.markEvent(buf);
+            cx->runtime()->geckoProfiler.markEvent(buf);
             JS_smprintf_free(buf);
         }
     }
 
     // RecompileInfoVector has inline space for at least one element.
     RecompileInfoVector scripts;
     MOZ_ASSERT(script->hasIonScript());
     MOZ_RELEASE_ASSERT(scripts.reserve(1));
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -375,17 +375,17 @@ IonCacheIRCompiler::init()
     allocator.initAvailableRegsAfterSpill();
     return true;
 }
 
 JitCode*
 IonCacheIRCompiler::compile()
 {
     masm.setFramePushed(ionScript_->frameSize());
-    if (cx_->spsProfiler.enabled())
+    if (cx_->geckoProfiler.enabled())
         masm.enableProfilingInstrumentation();
 
     do {
         switch (reader.readOp()) {
 #define DEFINE_OP(op)                   \
           case CacheOp::op:             \
             if (!emit##op())            \
                 return nullptr;         \
--- a/js/src/jit/IonInstrumentation.h
+++ b/js/src/jit/IonInstrumentation.h
@@ -4,28 +4,28 @@
  * 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 jit_IonInstrumentatjit_h
 #define jit_IonInstrumentatjit_h
 
 namespace js {
 
-class SPSProfiler;
+class GeckoProfiler;
 
 namespace jit {
 
 class MacroAssembler;
 
-typedef SPSInstrumentation<MacroAssembler, Register> BaseInstrumentation;
+typedef GeckoProfilerInstrumentation<MacroAssembler, Register> BaseInstrumentation;
 
 class IonInstrumentation : public BaseInstrumentation
 {
   public:
-    IonInstrumentation(SPSProfiler* profiler, jsbytecode** pc)
+    IonInstrumentation(GeckoProfiler* profiler, jsbytecode** pc)
       : BaseInstrumentation(profiler)
     {
         MOZ_ASSERT(pc != nullptr);
     }
 };
 
 } // namespace jit
 } // namespace js
--- a/js/src/jit/JitCompartment.h
+++ b/js/src/jit/JitCompartment.h
@@ -368,17 +368,17 @@ class JitRuntime
     }
 
     JitcodeGlobalTable* getJitcodeGlobalTable() {
         MOZ_ASSERT(hasJitcodeGlobalTable());
         return jitcodeGlobalTable_;
     }
 
     bool isProfilerInstrumentationEnabled(JSRuntime* rt) {
-        return rt->spsProfiler.enabled();
+        return rt->geckoProfiler.enabled();
     }
 
     bool isOptimizationTrackingEnabled(JSRuntime* rt) {
         return isProfilerInstrumentationEnabled(rt);
     }
 };
 
 enum class CacheKind : uint8_t;
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -25,18 +25,18 @@
 #include "jit/MacroAssembler.h"
 #include "jit/PcScriptCache.h"
 #include "jit/Recover.h"
 #include "jit/Safepoints.h"
 #include "jit/Snapshots.h"
 #include "jit/VMFunctions.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/Debugger.h"
+#include "vm/GeckoProfiler.h"
 #include "vm/Interpreter.h"
-#include "vm/SPSProfiler.h"
 #include "vm/TraceLogging.h"
 #include "vm/TypeInference.h"
 
 #include "jsscriptinlines.h"
 #include "gc/Nursery-inl.h"
 #include "jit/JitFrameIterator-inl.h"
 #include "vm/Debugger-inl.h"
 #include "vm/Probes-inl.h"
@@ -861,17 +861,17 @@ HandleException(ResumeFromException* rfe
                 MOZ_ASSERT(rfe->kind == ResumeFromException::RESUME_ENTRY_FRAME);
 
                 // When profiling, each frame popped needs a notification that
                 // the function has exited, so invoke the probe that a function
                 // is exiting.
 
                 JSScript* script = frames.script();
                 probes::ExitScript(cx, script, script->functionNonDelazifying(),
-                                   /* popSPSFrame = */ false);
+                                   /* popProfilerFrame = */ false);
                 if (!frames.more()) {
                     TraceLogStopEvent(logger, TraceLogger_IonMonkey);
                     TraceLogStopEvent(logger, TraceLogger_Scripts);
                     break;
                 }
                 ++frames;
             }
 
@@ -911,17 +911,17 @@ HandleException(ResumeFromException* rfe
             }
 
             TraceLogStopEvent(logger, TraceLogger_Baseline);
             TraceLogStopEvent(logger, TraceLogger_Scripts);
 
             // Unwind profiler pseudo-stack
             JSScript* script = iter.script();
             probes::ExitScript(cx, script, script->functionNonDelazifying(),
-                               /* popSPSFrame = */ false);
+                               /* popProfilerFrame = */ false);
 
             if (rfe->kind == ResumeFromException::RESUME_FORCED_RETURN)
                 return;
         }
 
         JitFrameLayout* current = iter.isScripted() ? iter.jsFrame() : nullptr;
 
         ++iter;
--- a/js/src/jit/JitSpewer.cpp
+++ b/js/src/jit/JitSpewer.cpp
@@ -434,18 +434,18 @@ jit::CheckLogging()
             "  safepoints    Safepoints\n"
             "  pools         Literal Pools (ARM only for now)\n"
             "  cacheflush    Instruction Cache flushes (ARM only for now)\n"
             "  range         Range Analysis\n"
             "  unroll        Loop unrolling\n"
             "  logs          C1 and JSON visualization logging\n"
             "  logs-sync     Same as logs, but flushes between each pass (sync. compiled functions only).\n"
             "  profiling     Profiling-related information\n"
-            "  trackopts     Optimization tracking information gathered by SPS. "
-                            "(Note: call enableSPSProfiling() in your script to enable it).\n"
+            "  trackopts     Optimization tracking information gathered by the Gecko profiler. "
+                            "(Note: call enableGeckoProfiling() in your script to enable it).\n"
             "  trackopts-ext Encoding information about optimization tracking"
             "  dump-mir-expr Dump the MIR expressions\n"
             "  cfg           Control flow graph generation\n"
             "  all           Everything\n"
             "\n"
             "  bl-aborts     Baseline compiler abort messages\n"
             "  bl-scripts    Baseline script-compilation\n"
             "  bl-op         Baseline compiler detailed op-specific messages\n"
--- a/js/src/jit/JitcodeMap.cpp
+++ b/js/src/jit/JitcodeMap.cpp
@@ -16,17 +16,17 @@
 
 #include "jsprf.h"
 
 #include "gc/Marking.h"
 #include "gc/Statistics.h"
 #include "jit/BaselineJIT.h"
 #include "jit/JitSpewer.h"
 #include "js/Vector.h"
-#include "vm/SPSProfiler.h"
+#include "vm/GeckoProfiler.h"
 
 #include "jsscriptinlines.h"
 
 #include "vm/TypeInference-inl.h"
 
 using mozilla::Maybe;
 
 namespace js {
@@ -728,17 +728,17 @@ struct Unconditionally
 };
 
 void
 JitcodeGlobalTable::trace(JSTracer* trc)
 {
     // Trace all entries unconditionally. This is done during minor collection
     // to tenure and update object pointers.
 
-    MOZ_ASSERT(trc->runtime()->spsProfiler.enabled());
+    MOZ_ASSERT(trc->runtime()->geckoProfiler.enabled());
 
     AutoSuppressProfilerSampling suppressSampling(trc->runtime());
     for (Range r(*this); !r.empty(); r.popFront())
         r.front()->trace<Unconditionally>(trc);
 }
 
 struct IfUnmarked
 {
@@ -779,17 +779,17 @@ JitcodeGlobalTable::markIteratively(GCMa
 
     MOZ_ASSERT(!marker->runtime()->isHeapMinorCollecting());
 
     AutoSuppressProfilerSampling suppressSampling(marker->runtime());
     uint32_t gen = marker->runtime()->profilerSampleBufferGen();
     uint32_t lapCount = marker->runtime()->profilerSampleBufferLapCount();
 
     // If the profiler is off, all entries are considered to be expired.
-    if (!marker->runtime()->spsProfiler.enabled())
+    if (!marker->runtime()->geckoProfiler.enabled())
         gen = UINT32_MAX;
 
     bool markedAny = false;
     for (Range r(*this); !r.empty(); r.popFront()) {
         JitcodeGlobalEntry* entry = r.front();
 
         // If an entry is not sampled, reset its generation to the invalid
         // generation, and conditionally mark the rest of the entry if its
--- a/js/src/jit/MIRGenerator.h
+++ b/js/src/jit/MIRGenerator.h
@@ -86,17 +86,17 @@ class MIRGenerator
         offThreadStatus_ = result;
     }
     AbortReasonOr<Ok> getOffThreadStatus() const {
         return offThreadStatus_;
     }
 
     MOZ_MUST_USE bool instrumentedProfiling() {
         if (!instrumentedProfilingIsCached_) {
-            instrumentedProfiling_ = GetJitContext()->runtime->spsProfiler().enabled();
+            instrumentedProfiling_ = GetJitContext()->runtime->geckoProfiler().enabled();
             instrumentedProfilingIsCached_ = true;
         }
         return instrumentedProfiling_;
     }
 
     bool isProfilerInstrumentationEnabled() {
         return !compilingWasm() && instrumentedProfiling();
     }
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -2361,17 +2361,17 @@ MacroAssembler::MacroAssembler(JSContext
     initWithAllocator();
     m_buffer.id = GetJitContext()->getNextAssemblerId();
 #elif defined(JS_CODEGEN_ARM64)
     initWithAllocator();
     armbuffer_.id = GetJitContext()->getNextAssemblerId();
 #endif
     if (ion) {
         setFramePushed(ion->frameSize());
-        if (pc && cx->runtime()->spsProfiler.enabled())
+        if (pc && cx->runtime()->geckoProfiler.enabled())
             enableProfilingInstrumentation();
     }
 }
 
 MacroAssembler::AfterICSaveLive
 MacroAssembler::icSaveLive(LiveRegisterSet& liveRegs)
 {
     PushRegsInMask(liveRegs);
--- a/js/src/jit/SharedIC.h
+++ b/js/src/jit/SharedIC.h
@@ -1047,17 +1047,17 @@ class ICStubCompiler
     MOZ_MUST_USE bool callTypeUpdateIC(MacroAssembler& masm, uint32_t objectOffset);
 
     // A stub frame is used when a stub wants to call into the VM without
     // performing a tail call. This is required for the return address
     // to pc mapping to work.
     void enterStubFrame(MacroAssembler& masm, Register scratch);
     void leaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false);
 
-    // Some stubs need to emit SPS profiler updates.  This emits the guarding
+    // Some stubs need to emit Gecko Profiler updates.  This emits the guarding
     // jitcode for those stubs.  If profiling is not enabled, jumps to the
     // given label.
     void guardProfilingEnabled(MacroAssembler& masm, Register scratch, Label* skip);
 
   public:
     static inline AllocatableGeneralRegisterSet availableGeneralRegs(size_t numInputs) {
         AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
 #if defined(JS_CODEGEN_ARM)
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -3694,17 +3694,17 @@ MacroAssemblerARMCompat::handleFailureWi
     ma_mov(r11, sp);
     pop(r11);
 
     // If profiling is enabled, then update the lastProfilingFrame to refer to caller
     // frame before returning.
     {
         Label skipProfilingInstrumentation;
         // Test if profiler enabled.
-        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->spsProfiler().addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->geckoProfiler().addressOfEnabled());
         asMasm().branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
         profilerExitFrame();
         bind(&skipProfilingInstrumentation);
     }
 
     ret();
 
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -28,17 +28,17 @@ static const FloatRegisterSet NonVolatil
                      (1ULL << FloatRegisters::d10) |
                      (1ULL << FloatRegisters::d11) |
                      (1ULL << FloatRegisters::d12) |
                      (1ULL << FloatRegisters::d13) |
                      (1ULL << FloatRegisters::d14) |
                      (1ULL << FloatRegisters::d15));
 
 static void
-GenerateReturn(MacroAssembler& masm, int returnCode, SPSProfiler* prof)
+GenerateReturn(MacroAssembler& masm, int returnCode, GeckoProfiler* prof)
 {
     // Restore non-volatile floating point registers.
     masm.transferMultipleByRuns(NonVolatileFloatRegs, IsLoad, StackPointer, IA);
 
     // Get rid of padding word.
     masm.addPtr(Imm32(sizeof(void*)), sp);
 
     // Set up return value
@@ -309,17 +309,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         masm.addPtr(Imm32(BaselineFrame::Size()), framePtr);
         masm.branchIfFalseBool(ReturnReg, &error);
 
         // If OSR-ing, then emit instrumentation for setting lastProfilerFrame
         // if profiler instrumentation is enabled.
         {
             Label skipProfilingInstrumentation;
             Register realFramePtr = numStackValues;
-            AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+            AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
             masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
             masm.as_add(realFramePtr, framePtr, Imm8(sizeof(void*)));
             masm.profilerEnterFrame(realFramePtr, scratch);
             masm.bind(&skipProfilingInstrumentation);
         }
 
         masm.jump(jitcode);
@@ -371,17 +371,17 @@ JitRuntime::generateEnterJIT(JSContext* 
     // :TODO: Optimize storeValue with:
     // We're using a load-double here. In order for that to work, the data needs
     // to be stored in two consecutive registers, make sure this is the case
     //   MOZ_ASSERT(JSReturnReg_Type.code() == JSReturnReg_Data.code()+1);
     //   aasm->as_extdtr(IsStore, 64, true, Offset,
     //                   JSReturnReg_Data, EDtrAddr(r5, EDtrOffImm(0)));
 
     // Restore non-volatile registers and return.
-    GenerateReturn(masm, true, &cx->runtime()->spsProfiler);
+    GenerateReturn(masm, true, &cx->runtime()->geckoProfiler);
 
     Linker linker(masm);
     AutoFlushICache afc("EnterJIT");
     JitCode* code = linker.newCode<NoGC>(cx, OTHER_CODE);
 
 #ifdef JS_ION_PERF
     writePerfSpewerJitCodeProfile(code, "EnterJIT");
 #endif
@@ -1037,17 +1037,17 @@ JitRuntime::generateDebugTrapHandler(JSC
                    JSReturnOperand);
     masm.mov(r11, sp);
     masm.pop(r11);
 
     // Before returning, if profiling is turned on, make sure that lastProfilingFrame
     // is set to the correct caller frame.
     {
         Label skipProfilingInstrumentation;
-        AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
         masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skipProfilingInstrumentation);
         masm.profilerExitFrame();
         masm.bind(&skipProfilingInstrumentation);
     }
 
     masm.ret();
 
     Linker linker(masm);
--- a/js/src/jit/arm64/Trampoline-arm64.cpp
+++ b/js/src/jit/arm64/Trampoline-arm64.cpp
@@ -113,17 +113,17 @@ JitRuntime::generateEnterJIT(JSContext* 
 
         Label noArguments;
         Label loopHead;
 
         masm.movePtr(reg_argc, tmp_argc.asUnsized());
 
         // sp -= 8
         // Since we're using PostIndex Str below, this is necessary to avoid overwriting
-        // the SPS mark pushed above.
+        // the Gecko Profiler mark pushed above.
         masm.subFromStackPtr(Imm32(8));
 
         // sp -= 8 * argc
         masm.Sub(PseudoStackPointer64, PseudoStackPointer64, Operand(tmp_argc, vixl::SXTX, 3));
 
         // Give sp 16-byte alignment and sync stack pointers.
         masm.andToStackPtr(Imm32(~0xff));
         masm.moveStackPtrTo(tmp_sp.asUnsized());
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -1907,17 +1907,17 @@ MacroAssemblerMIPSCompat::handleFailureW
     ma_move(StackPointer, BaselineFrameReg);
     pop(BaselineFrameReg);
 
     // If profiling is enabled, then update the lastProfilingFrame to refer to caller
     // frame before returning.
     {
         Label skipProfilingInstrumentation;
         // Test if profiler enabled.
-        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->spsProfiler().addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->geckoProfiler().addressOfEnabled());
         asMasm().branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
         profilerExitFrame();
         bind(&skipProfilingInstrumentation);
     }
 
     ret();
 
--- a/js/src/jit/mips32/Trampoline-mips32.cpp
+++ b/js/src/jit/mips32/Trampoline-mips32.cpp
@@ -278,17 +278,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         masm.addPtr(Imm32(BaselineFrame::Size()), framePtr);
         masm.branchIfFalseBool(ReturnReg, &error);
 
         // If OSR-ing, then emit instrumentation for setting lastProfilerFrame
         // if profiler instrumentation is enabled.
         {
             Label skipProfilingInstrumentation;
             Register realFramePtr = numStackValues;
-            AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+            AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
             masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
             masm.ma_addu(realFramePtr, framePtr, Imm32(sizeof(void*)));
             masm.profilerEnterFrame(realFramePtr, scratch);
             masm.bind(&skipProfilingInstrumentation);
         }
 
         masm.jump(jitcode);
@@ -1015,17 +1015,17 @@ JitRuntime::generateDebugTrapHandler(JSC
                    JSReturnOperand);
     masm.movePtr(s5, StackPointer);
     masm.pop(s5);
 
     // Before returning, if profiling is turned on, make sure that lastProfilingFrame
     // is set to the correct caller frame.
     {
         Label skipProfilingInstrumentation;
-        AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
         masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skipProfilingInstrumentation);
         masm.profilerExitFrame();
         masm.bind(&skipProfilingInstrumentation);
     }
 
     masm.ret();
 
     Linker linker(masm);
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -2082,17 +2082,17 @@ MacroAssemblerMIPS64Compat::handleFailur
     ma_move(StackPointer, BaselineFrameReg);
     pop(BaselineFrameReg);
 
     // If profiling is enabled, then update the lastProfilingFrame to refer to caller
     // frame before returning.
     {
         Label skipProfilingInstrumentation;
         // Test if profiler enabled.
-        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->spsProfiler().addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->geckoProfiler().addressOfEnabled());
         asMasm().branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
         profilerExitFrame();
         bind(&skipProfilingInstrumentation);
     }
 
     ret();
 
--- a/js/src/jit/mips64/Trampoline-mips64.cpp
+++ b/js/src/jit/mips64/Trampoline-mips64.cpp
@@ -294,17 +294,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         masm.addPtr(Imm32(BaselineFrame::Size()), framePtr);
         masm.branchIfFalseBool(ReturnReg, &error);
 
         // If OSR-ing, then emit instrumentation for setting lastProfilerFrame
         // if profiler instrumentation is enabled.
         {
             Label skipProfilingInstrumentation;
             Register realFramePtr = numStackValues;
-            AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+            AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
             masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
             masm.ma_daddu(realFramePtr, framePtr, Imm32(sizeof(void*)));
             masm.profilerEnterFrame(realFramePtr, scratch);
             masm.bind(&skipProfilingInstrumentation);
         }
 
         masm.jump(jitcode);
@@ -960,17 +960,17 @@ JitRuntime::generateDebugTrapHandler(JSC
                    JSReturnOperand);
     masm.movePtr(s5, StackPointer);
     masm.pop(s5);
 
     // Before returning, if profiling is turned on, make sure that lastProfilingFrame
     // is set to the correct caller frame.
     {
         Label skipProfilingInstrumentation;
-        AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
         masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skipProfilingInstrumentation);
         masm.profilerExitFrame();
         masm.bind(&skipProfilingInstrumentation);
     }
 
     masm.ret();
 
     Linker linker(masm);
--- a/js/src/jit/shared/BaselineCompiler-shared.cpp
+++ b/js/src/jit/shared/BaselineCompiler-shared.cpp
@@ -28,17 +28,17 @@ BaselineCompilerShared::BaselineCompiler
     stubSpace_(),
     icEntries_(),
     pcMappingEntries_(),
     icLoadLabels_(),
     pushedBeforeCall_(0),
 #ifdef DEBUG
     inCall_(false),
 #endif
-    spsPushToggleOffset_(),
+    profilerPushToggleOffset_(),
     profilerEnterFrameToggleOffset_(),
     profilerExitFrameToggleOffset_(),
     traceLoggerToggleOffsets_(cx),
     traceLoggerScriptTextIdOffset_()
 { }
 
 void
 BaselineCompilerShared::prepareVMCall()
--- a/js/src/jit/shared/BaselineCompiler-shared.h
+++ b/js/src/jit/shared/BaselineCompiler-shared.h
@@ -57,17 +57,17 @@ class BaselineCompilerShared
     };
     js::Vector<ICLoadLabel, 16, SystemAllocPolicy> icLoadLabels_;
 
     uint32_t pushedBeforeCall_;
 #ifdef DEBUG
     bool inCall_;
 #endif
 
-    CodeOffset spsPushToggleOffset_;
+    CodeOffset profilerPushToggleOffset_;
     CodeOffset profilerEnterFrameToggleOffset_;
     CodeOffset profilerExitFrameToggleOffset_;
 
     Vector<CodeOffset> traceLoggerToggleOffsets_;
     CodeOffset traceLoggerScriptTextIdOffset_;
 
     BaselineCompilerShared(JSContext* cx, TempAllocator& alloc, JSScript* script);
 
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -1285,18 +1285,18 @@ CodeGeneratorShared::verifyOsiPointRegs(
     // Do not profile the callWithABI that occurs below.  This is to avoid a
     // rare corner case that occurs when profiling interacts with itself:
     //
     // When slow profiling assertions are turned on, FunctionBoundary ops
     // (which update the profiler pseudo-stack) may emit a callVM, which
     // forces them to have an osi point associated with them.  The
     // FunctionBoundary for inline function entry is added to the caller's
     // graph with a PC from the caller's code, but during codegen it modifies
-    // SPS instrumentation to add the callee as the current top-most script.
-    // When codegen gets to the OSIPoint, and the callWithABI below is
+    // Gecko Profiler instrumentation to add the callee as the current top-most
+    // script. When codegen gets to the OSIPoint, and the callWithABI below is
     // emitted, the codegen thinks that the current frame is the callee, but
     // the PC it's using from the OSIPoint refers to the caller.  This causes
     // the profiler instrumentation of the callWithABI below to ASSERT, since
     // the script and pc are mismatched.  To avoid this, we simply omit
     // instrumentation for these callWithABIs.
 
     // Any live register captured by a safepoint (other than temp registers)
     // must remain unchanged between the call and the OsiPoint instruction.
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -357,17 +357,17 @@ MacroAssemblerX64::handleFailureWithHand
     loadValue(Address(rbp, BaselineFrame::reverseOffsetOfReturnValue()), JSReturnOperand);
     movq(rbp, rsp);
     pop(rbp);
 
     // If profiling is enabled, then update the lastProfilingFrame to refer to caller
     // frame before returning.
     {
         Label skipProfilingInstrumentation;
-        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->spsProfiler().addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->geckoProfiler().addressOfEnabled());
         asMasm().branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skipProfilingInstrumentation);
         profilerExitFrame();
         bind(&skipProfilingInstrumentation);
     }
 
     ret();
 
     // If we are bailing out to baseline to handle an exception, jump to
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -252,17 +252,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         masm.addPtr(Imm32(BaselineFrame::Size()), framePtr);
         masm.branchIfFalseBool(ReturnReg, &error);
 
         // If OSR-ing, then emit instrumentation for setting lastProfilerFrame
         // if profiler instrumentation is enabled.
         {
             Label skipProfilingInstrumentation;
             Register realFramePtr = numStackValues;
-            AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+            AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
             masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
             masm.lea(Operand(framePtr, sizeof(void*)), realFramePtr);
             masm.profilerEnterFrame(realFramePtr, scratch);
             masm.bind(&skipProfilingInstrumentation);
         }
 
         masm.jump(reg_code);
@@ -911,17 +911,17 @@ JitRuntime::generateDebugTrapHandler(JSC
                    JSReturnOperand);
     masm.mov(rbp, rsp);
     masm.pop(rbp);
 
     // Before returning, if profiling is turned on, make sure that lastProfilingFrame
     // is set to the correct caller frame.
     {
         Label skipProfilingInstrumentation;
-        AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
         masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skipProfilingInstrumentation);
         masm.profilerExitFrame();
         masm.bind(&skipProfilingInstrumentation);
     }
 
     masm.ret();
 
     Linker linker(masm);
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -263,17 +263,17 @@ MacroAssemblerX86::handleFailureWithHand
     movl(ebp, esp);
     pop(ebp);
 
     // If profiling is enabled, then update the lastProfilingFrame to refer to caller
     // frame before returning.
     {
         Label skipProfilingInstrumentation;
         // Test if profiler enabled.
-        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->spsProfiler().addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(GetJitContext()->runtime->geckoProfiler().addressOfEnabled());
         asMasm().branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
         profilerExitFrame();
         bind(&skipProfilingInstrumentation);
     }
 
     ret();
 
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -245,17 +245,17 @@ JitRuntime::generateEnterJIT(JSContext* 
         masm.addPtr(Imm32(BaselineFrame::Size()), framePtr);
         masm.branchIfFalseBool(ReturnReg, &error);
 
         // If OSR-ing, then emit instrumentation for setting lastProfilerFrame
         // if profiler instrumentation is enabled.
         {
             Label skipProfilingInstrumentation;
             Register realFramePtr = numStackValues;
-            AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+            AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
             masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0),
                           &skipProfilingInstrumentation);
             masm.lea(Operand(framePtr, sizeof(void*)), realFramePtr);
             masm.profilerEnterFrame(realFramePtr, scratch);
             masm.bind(&skipProfilingInstrumentation);
         }
 
         masm.jump(jitcode);
@@ -941,17 +941,17 @@ JitRuntime::generateDebugTrapHandler(JSC
                    JSReturnOperand);
     masm.mov(ebp, esp);
     masm.pop(ebp);
 
     // Before returning, if profiling is turned on, make sure that lastProfilingFrame
     // is set to the correct caller frame.
     {
         Label skipProfilingInstrumentation;
-        AbsoluteAddress addressOfEnabled(cx->runtime()->spsProfiler.addressOfEnabled());
+        AbsoluteAddress addressOfEnabled(cx->runtime()->geckoProfiler.addressOfEnabled());
         masm.branch32(Assembler::Equal, addressOfEnabled, Imm32(0), &skipProfilingInstrumentation);
         masm.profilerExitFrame();
         masm.bind(&skipProfilingInstrumentation);
     }
 
     masm.ret();
 
     Linker linker(masm);
--- a/js/src/jsapi-tests/testProfileStrings.cpp
+++ b/js/src/jsapi-tests/testProfileStrings.cpp
@@ -15,18 +15,18 @@ static js::ProfileEntry pstack[10];
 static uint32_t psize = 0;
 static uint32_t max_stack = 0;
 
 static void
 reset(JSContext* cx)
 {
     psize = max_stack = 0;
     memset(pstack, 0, sizeof(pstack));
-    cx->spsProfiler.stringsReset();
-    cx->spsProfiler.enableSlowAssertions(true);
+    cx->geckoProfiler.stringsReset();
+    cx->geckoProfiler.enableSlowAssertions(true);
     js::EnableContextProfilingStack(cx, true);
 }
 
 static const JSClass ptestClass = {
     "Prof", 0
 };
 
 static bool
@@ -103,31 +103,31 @@ BEGIN_TEST(testProfileStrings_isCalledWi
     reset(cx);
     {
         JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
                                   &rval));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
-        CHECK(cx->runtime()->spsProfiler.stringsCount() == 8);
+        CHECK(cx->runtime()->geckoProfiler.stringsCount() == 8);
         /* Make sure the stack resets and we added no new entries */
         max_stack = 0;
         CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
                                   &rval));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
-        CHECK(cx->runtime()->spsProfiler.stringsCount() == 8);
+        CHECK(cx->runtime()->geckoProfiler.stringsCount() == 8);
     }
     reset(cx);
     {
         JS::RootedValue rval(cx);
         CHECK(JS_CallFunctionName(cx, global, "check2", JS::HandleValueArray::empty(),
                                   &rval));
-        CHECK(cx->runtime()->spsProfiler.stringsCount() == 5);
+        CHECK(cx->runtime()->geckoProfiler.stringsCount() == 5);
         CHECK(max_stack >= 6);
         CHECK(psize == 0);
     }
     js::EnableContextProfilingStack(cx, false);
     js::SetContextProfilingStack(cx, pstack, &psize, 3);
     reset(cx);
     {
         JS::RootedValue rval(cx);
@@ -163,22 +163,22 @@ BEGIN_TEST(testProfileStrings_isCalledWi
         JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
                                   &rval));
         CHECK(psize == 0);
         CHECK(max_stack >= 8);
 
         /* Make sure the stack resets and we added no new entries */
-        uint32_t cnt = cx->runtime()->spsProfiler.stringsCount();
+        uint32_t cnt = cx->runtime()->geckoProfiler.stringsCount();
         max_stack = 0;
         CHECK(JS_CallFunctionName(cx, global, "check", JS::HandleValueArray::empty(),
                                   &rval));
         CHECK(psize == 0);
-        CHECK(cx->runtime()->spsProfiler.stringsCount() == cnt);
+        CHECK(cx->runtime()->geckoProfiler.stringsCount() == cnt);
         CHECK(max_stack >= 8);
     }
 
     js::EnableContextProfilingStack(cx, false);
     js::SetContextProfilingStack(cx, pstack, &psize, 3);
     reset(cx);
     {
         /* Limit the size of the stack and make sure we don't overflow */
@@ -205,17 +205,17 @@ BEGIN_TEST(testProfileStrings_isCalledWh
     reset(cx);
     {
         JS::RootedValue rval(cx);
         /* Make sure the stack resets and we have an entry for each stack */
         bool ok = JS_CallFunctionName(cx, global, "check2", JS::HandleValueArray::empty(),
                                       &rval);
         CHECK(!ok);
         CHECK(psize == 0);
-        CHECK(cx->runtime()->spsProfiler.stringsCount() == 1);
+        CHECK(cx->runtime()->geckoProfiler.stringsCount() == 1);
 
         JS_ClearPendingException(cx);
     }
     return true;
 }
 END_TEST(testProfileStrings_isCalledWhenError)
 
 BEGIN_TEST(testProfileStrings_worksWhenEnabledOnTheFly)
@@ -229,17 +229,17 @@ BEGIN_TEST(testProfileStrings_worksWhenE
     reset(cx);
     js::EnableContextProfilingStack(cx, false);
     {
         /* enable it in the middle of JS and make sure things check out */
         JS::RootedValue rval(cx);
         JS_CallFunctionName(cx, global, "a", JS::HandleValueArray::empty(), &rval);
         CHECK(psize == 0);
         CHECK(max_stack >= 1);
-        CHECK(cx->runtime()->spsProfiler.stringsCount() == 1);
+        CHECK(cx->runtime()->geckoProfiler.stringsCount() == 1);
     }
 
     EXEC("function d(p) { p.disable(); }");
     EXEC("function c() { var p = new Prof(); d(p); }");
     reset(cx);
     {
         /* now disable in the middle of js */
         JS::RootedValue rval(cx);
@@ -256,17 +256,17 @@ BEGIN_TEST(testProfileStrings_worksWhenE
         CHECK(psize == 0);
         CHECK(max_stack >= 3);
     }
 
     EXEC("function h() { }");
     EXEC("function g(p) { p.disable(); for (var i = 0; i < 100; i++) i++; }");
     EXEC("function f() { g(new Prof()); }");
     reset(cx);
-    cx->runtime()->spsProfiler.enableSlowAssertions(false);
+    cx->runtime()->geckoProfiler.enableSlowAssertions(false);
     {
         JS::RootedValue rval(cx);
         /* disable, and make sure that if we try to re-enter the JIT the pop
          * will still happen */
         JS_CallFunctionName(cx, global, "f", JS::HandleValueArray::empty(), &rval);
         CHECK(psize == 0);
     }
     return true;
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1168,17 +1168,17 @@ ArrayJoinKernel(JSContext* cx, Separator
 }
 
 /* ES5 15.4.4.5 */
 bool
 js::array_join(JSContext* cx, unsigned argc, Value* vp)
 {
     JS_CHECK_RECURSION(cx, return false);
 
-    AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.join");
+    AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.join");
     CallArgs args = CallArgsFromVp(argc, vp);
 
     // Step 1
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     AutoCycleDetector detector(cx, obj);
@@ -1423,17 +1423,17 @@ ArrayReverseDenseKernel(JSContext* cx, H
 }
 
 DefineBoxedOrUnboxedFunctor3(ArrayReverseDenseKernel,
                              JSContext*, HandleObject, uint32_t);
 
 bool
 js::array_reverse(JSContext* cx, unsigned argc, Value* vp)
 {
-    AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.reverse");
+    AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.reverse");
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     uint32_t len;
     if (!GetLengthProperty(cx, obj, &len))
         return false;
@@ -2040,17 +2040,17 @@ js::NewbornArrayPush(JSContext* cx, Hand
     arr->initDenseElementWithType(cx, length, v);
     return true;
 }
 
 /* ES5 15.4.4.7 */
 bool
 js::array_push(JSContext* cx, unsigned argc, Value* vp)
 {
-    AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.push");
+    AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.push");
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     /* Steps 2-3. */
@@ -2092,17 +2092,17 @@ js::array_push(JSContext* cx, unsigned a
     args.rval().setNumber(newlength);
     return SetLengthProperty(cx, obj, newlength);
 }
 
 /* ES6 20130308 draft 15.4.4.6. */
 bool
 js::array_pop(JSContext* cx, unsigned argc, Value* vp)
 {
-    AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.pop");
+    AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.pop");
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     /* Steps 2-3. */
@@ -2198,17 +2198,17 @@ ArrayShiftDenseKernel(JSContext* cx, Han
 
 DefineBoxedOrUnboxedFunctor3(ArrayShiftDenseKernel,
                              JSContext*, HandleObject, MutableHandleValue);
 
 /* ES5 15.4.4.9 */
 bool
 js::array_shift(JSContext* cx, unsigned argc, Value* vp)
 {
-    AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.shift");
+    AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.shift");
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     /* Steps 2-3. */
@@ -2266,17 +2266,17 @@ js::array_shift(JSContext* cx, unsigned 
 
     /* Step 9. */
     return SetLengthProperty(cx, obj, newlen);
 }
 
 bool
 js::array_unshift(JSContext* cx, unsigned argc, Value* vp)
 {
-    AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.unshift");
+    AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.unshift");
     CallArgs args = CallArgsFromVp(argc, vp);
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     uint32_t length;
     if (!GetLengthProperty(cx, obj, &length))
         return false;
@@ -2434,17 +2434,17 @@ ArraySpliceCopy(JSContext* cx, HandleObj
 
     /* Steps 16-17. */
     return SetLengthProperty(cx, arr, actualDeleteCount);
 }
 
 bool
 js::array_splice_impl(JSContext* cx, unsigned argc, Value* vp, bool returnValueIsUsed)
 {
-    AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.splice");
+    AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.splice");
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     /* Step 2. */
@@ -2895,17 +2895,17 @@ ArraySliceOrdinary(JSContext* cx, Handle
     arr.set(narr);
     return true;
 }
 
 /* ES 2016 draft Mar 25, 2016 22.1.3.23. */
 bool
 js::array_slice(JSContext* cx, unsigned argc, Value* vp)
 {
-    AutoSPSEntry pseudoFrame(cx->runtime(), "Array.prototype.slice");
+    AutoGeckoProfilerEntry pseudoFrame(cx->runtime(), "Array.prototype.slice");
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
     if (!obj)
         return false;
 
     /* Step 2. */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -221,19 +221,19 @@
 #include "gc/Memory.h"
 #include "gc/Policy.h"
 #include "jit/BaselineJIT.h"
 #include "jit/IonCode.h"
 #include "jit/JitcodeMap.h"
 #include "js/SliceBudget.h"
 #include "proxy/DeadObjectProxy.h"
 #include "vm/Debugger.h"
+#include "vm/GeckoProfiler.h"
 #include "vm/ProxyObject.h"
 #include "vm/Shape.h"
-#include "vm/SPSProfiler.h"
 #include "vm/String.h"
 #include "vm/Symbol.h"
 #include "vm/Time.h"
 #include "vm/TraceLogging.h"
 #include "vm/WrapperObject.h"
 
 #include "jsobjinlines.h"
 #include "jsscriptinlines.h"
@@ -2524,17 +2524,17 @@ GCRuntime::updatePointersToRelocatedCell
     MovingTracer trc(rt);
 
     zone->fixupAfterMovingGC();
 
     // Fixup compartment global pointers as these get accessed during marking.
     for (CompartmentsInZoneIter comp(zone); !comp.done(); comp.next())
         comp->fixupAfterMovingGC();
     JSCompartment::fixupCrossCompartmentWrappersAfterMovingGC(&trc);
-    rt->spsProfiler.fixupStringsMapAfterMovingGC();
+    rt->geckoProfiler.fixupStringsMapAfterMovingGC();
 
     // Iterate through all cells that can contain relocatable pointers to update
     // them. Since updating each cell is independent we try to parallelize this
     // as much as possible.
     updateAllCellPointers(&trc, zone);
 
     // Mark roots to update them.
     {
@@ -7118,17 +7118,17 @@ JS::GCCellPtr::mayBeOwnedByOtherRuntime(
 #ifdef JSGC_HASH_TABLE_CHECKS
 void
 js::gc::CheckHashTablesAfterMovingGC(JSRuntime* rt)
 {
     /*
      * Check that internal hash tables no longer have any pointers to things
      * that have been moved.
      */
-    rt->spsProfiler.checkStringsMapAfterMovingGC();
+    rt->geckoProfiler.checkStringsMapAfterMovingGC();
     for (ZonesIter zone(rt, SkipAtoms); !zone.done(); zone.next()) {
         zone->checkUniqueIdTableAfterMovingGC();
         zone->checkInitialShapesTableAfterMovingGC();
         zone->checkBaseShapeTableAfterMovingGC();
 
         JS::AutoCheckCannotGC nogc;
         for (auto baseShape = zone->cellIter<BaseShape>(); !baseShape.done(); baseShape.next()) {
             if (ShapeTable* table = baseShape->maybeTable(nogc))
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -2858,17 +2858,17 @@ JSScript::finalize(FreeOp* fop)
     // JSScript::Create(), but not yet finished initializing it with
     // fullyInitFromEmitter() or fullyInitTrivial().
 
     // Collect code coverage information for this script and all its inner
     // scripts, and store the aggregated information on the compartment.
     if (fop->runtime()->lcovOutput.isEnabled())
         compartment()->lcovOutput.collectCodeCoverageInfo(compartment(), sourceObject(), this);
 
-    fop->runtime()->spsProfiler.onScriptFinalized(this);
+    fop->runtime()->geckoProfiler.onScriptFinalized(this);
 
     if (types_)
         types_->destroy();
 
     jit::DestroyJitScripts(fop, this);
 
     destroyScriptCounts(fop);
     destroyDebugScript(fop);
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -317,16 +317,17 @@ UNIFIED_SOURCES += [
     'vm/CodeCoverage.cpp',
     'vm/Compression.cpp',
     'vm/DateTime.cpp',
     'vm/Debugger.cpp',
     'vm/DebuggerMemory.cpp',
     'vm/EnvironmentObject.cpp',
     'vm/ErrorObject.cpp',
     'vm/ForOfIterator.cpp',
+    'vm/GeckoProfiler.cpp',
     'vm/GeneratorObject.cpp',
     'vm/GlobalObject.cpp',
     'vm/HelperThreads.cpp',
     'vm/Id.cpp',
     'vm/JSONParser.cpp',
     'vm/MemoryMetrics.cpp',
     'vm/NativeObject.cpp',
     'vm/ObjectGroup.cpp',
@@ -340,17 +341,16 @@ UNIFIED_SOURCES += [
     'vm/RegExpStatics.cpp',
     'vm/Runtime.cpp',
     'vm/SavedStacks.cpp',
     'vm/Scope.cpp',
     'vm/SelfHosting.cpp',
     'vm/Shape.cpp',
     'vm/SharedArrayObject.cpp',
     'vm/SharedImmutableStringsCache.cpp',
-    'vm/SPSProfiler.cpp',
     'vm/Stack.cpp',
     'vm/Stopwatch.cpp',
     'vm/String.cpp',
     'vm/StringBuffer.cpp',
     'vm/StructuredClone.cpp',
     'vm/Symbol.cpp',
     'vm/TaggedProto.cpp',
     'vm/Time.cpp',
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -281,19 +281,19 @@ struct ShellContext
     ConditionVariable sleepWakeup;
 
     int exitCode;
     bool quitting;
 
     UniqueChars readLineBuf;
     size_t readLineBufPos;
 
-    static const uint32_t SpsProfilingMaxStackSize = 1000;
-    ProfileEntry spsProfilingStack[SpsProfilingMaxStackSize];
-    uint32_t spsProfilingStackSize;
+    static const uint32_t GeckoProfilingMaxStackSize = 1000;
+    ProfileEntry geckoProfilingStack[GeckoProfilingMaxStackSize];
+    uint32_t geckoProfilingStackSize;
 
     OffThreadState offThreadState;
 };
 
 struct MOZ_STACK_CLASS EnvironmentPreparer : public js::ScriptEnvironmentPreparer {
     JSContext* cx;
     explicit EnvironmentPreparer(JSContext* cx)
       : cx(cx)
@@ -432,17 +432,17 @@ ShellContext::ShellContext(JSContext* cx
     lastWarning(cx, NullValue()),
     promiseRejectionTrackerCallback(cx, NullValue()),
     asyncTasks(mutexid::ShellAsyncTasks, cx),
     drainingJobQueue(false),
     watchdogLock(mutexid::ShellContextWatchdog),
     exitCode(0),
     quitting(false),
     readLineBufPos(0),
-    spsProfilingStackSize(0)
+    geckoProfilingStackSize(0)
 {}
 
 static ShellContext*
 GetShellContext(JSContext* cx)
 {
     ShellContext* sc = static_cast<ShellContext*>(JS_GetContextPrivate(cx));
     MOZ_ASSERT(sc);
     return sc;
@@ -4839,33 +4839,33 @@ PrintProfilerEvents_Callback(const char*
 {
     fprintf(stderr, "PROFILER EVENT: %s\n", msg);
 }
 
 static bool
 PrintProfilerEvents(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    if (cx->runtime()->spsProfiler.enabled())
+    if (cx->runtime()->geckoProfiler.enabled())
         js::RegisterContextProfilingEventMarker(cx, &PrintProfilerEvents_Callback);
     args.rval().setUndefined();
     return true;
 }
 
 #if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64)
 typedef Vector<char16_t, 0, SystemAllocPolicy> StackChars;
 Vector<StackChars, 0, SystemAllocPolicy> stacks;
 
 static void
 SingleStepCallback(void* arg, jit::Simulator* sim, void* pc)
 {
     JSContext* cx = reinterpret_cast<JSContext*>(arg);
 
     // If profiling is not enabled, don't do anything.
-    if (!cx->spsProfiler.enabled())
+    if (!cx->geckoProfiler.enabled())
         return;
 
     JS::ProfilingFrameIterator::RegisterState state;
     state.pc = pc;
 #if defined(JS_SIMULATOR_ARM)
     state.sp = (void*)sim->get_register(jit::Simulator::sp);
     state.lr = (void*)sim->get_register(jit::Simulator::lr);
 #elif defined(JS_SIMULATOR_MIPS64)
@@ -4958,72 +4958,72 @@ IsLatin1(JSContext* cx, unsigned argc, V
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     bool isLatin1 = args.get(0).isString() && args[0].toString()->hasLatin1Chars();
     args.rval().setBoolean(isLatin1);
     return true;
 }
 
 static bool
-EnableSPSProfiling(JSContext* cx, unsigned argc, Value* vp)
+EnableGeckoProfiling(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     ShellContext* sc = GetShellContext(cx);
 
-    // Disable before re-enabling; see the assertion in |SPSProfiler::setProfilingStack|.
-    if (cx->spsProfiler.installed())
-        cx->spsProfiler.enable(false);
-
-    SetContextProfilingStack(cx, sc->spsProfilingStack, &sc->spsProfilingStackSize,
-                             ShellContext::SpsProfilingMaxStackSize);
-    cx->spsProfiler.enableSlowAssertions(false);
-    cx->spsProfiler.enable(true);
+    // Disable before re-enabling; see the assertion in |GeckoProfiler::setProfilingStack|.
+    if (cx->geckoProfiler.installed())
+        cx->geckoProfiler.enable(false);
+
+    SetContextProfilingStack(cx, sc->geckoProfilingStack, &sc->geckoProfilingStackSize,
+                             ShellContext::GeckoProfilingMaxStackSize);
+    cx->geckoProfiler.enableSlowAssertions(false);
+    cx->geckoProfiler.enable(true);
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
-EnableSPSProfilingWithSlowAssertions(JSContext* cx, unsigned argc, Value* vp)
+EnableGeckoProfilingWithSlowAssertions(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setUndefined();
 
     ShellContext* sc = GetShellContext(cx);
 
-    if (cx->spsProfiler.enabled()) {
+    if (cx->geckoProfiler.enabled()) {
         // If profiling already enabled with slow assertions disabled,
         // this is a no-op.
-        if (cx->spsProfiler.slowAssertionsEnabled())
+        if (cx->geckoProfiler.slowAssertionsEnabled())
             return true;
 
         // Slow assertions are off.  Disable profiling before re-enabling
         // with slow assertions on.
-        cx->spsProfiler.enable(false);
-    }
-
-    // Disable before re-enabling; see the assertion in |SPSProfiler::setProfilingStack|.
-    if (cx->spsProfiler.installed())
-        cx->spsProfiler.enable(false);
-
-    SetContextProfilingStack(cx, sc->spsProfilingStack, &sc->spsProfilingStackSize,
-                             ShellContext::SpsProfilingMaxStackSize);
-    cx->spsProfiler.enableSlowAssertions(true);
-    cx->spsProfiler.enable(true);
+        cx->geckoProfiler.enable(false);
+    }
+
+    // Disable before re-enabling; see the assertion in |GeckoProfiler::setProfilingStack|.
+    if (cx->geckoProfiler.installed())
+        cx->geckoProfiler.enable(false);
+
+    SetContextProfilingStack(cx, sc->geckoProfilingStack, &sc->geckoProfilingStackSize,
+                             ShellContext::GeckoProfilingMaxStackSize);
+    cx->geckoProfiler.enableSlowAssertions(true);
+    cx->geckoProfiler.enable(true);
 
     return true;
 }
 
 static bool
-DisableSPSProfiling(JSContext* cx, unsigned argc, Value* vp)
+DisableGeckoProfiling(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    if (cx->runtime()->spsProfiler.installed())
-        cx->runtime()->spsProfiler.enable(false);
+    if (cx->runtime()->geckoProfiler.installed())
+        cx->runtime()->geckoProfiler.enable(false);
     args.rval().setUndefined();
     return true;
 }
 
 // Global mailbox that is used to communicate a SharedArrayBuffer
 // value from one worker to another.
 //
 // For simplicity we store only the SharedArrayRawBuffer; retaining
@@ -6052,29 +6052,29 @@ static const JSFunctionSpecWithHelp shel
 "  (currently everything but ARM-simulator). When enabled, at every instruction a\n"
 "  backtrace will be recorded and stored in an array. Adjacent duplicate backtraces\n"
 "  are discarded."),
 
     JS_FN_HELP("disableSingleStepProfiling", DisableSingleStepProfiling, 0, 0,
 "disableSingleStepProfiling()",
 "  Return the array of backtraces recorded by enableSingleStepProfiling."),
 
-    JS_FN_HELP("enableSPSProfiling", EnableSPSProfiling, 0, 0,
-"enableSPSProfiling()",
-"  Enables SPS instrumentation and corresponding assertions, with slow\n"
+    JS_FN_HELP("enableGeckoProfiling", EnableGeckoProfiling, 0, 0,
+"enableGeckoProfiling()",
+"  Enables Gecko Profiler instrumentation and corresponding assertions, with slow\n"
 "  assertions disabled.\n"),
 
-    JS_FN_HELP("enableSPSProfilingWithSlowAssertions", EnableSPSProfilingWithSlowAssertions, 0, 0,
-"enableSPSProfilingWithSlowAssertions()",
-"  Enables SPS instrumentation and corresponding assertions, with slow\n"
+    JS_FN_HELP("enableGeckoProfilingWithSlowAssertions", EnableGeckoProfilingWithSlowAssertions, 0, 0,
+"enableGeckoProfilingWithSlowAssertions()",
+"  Enables Gecko Profiler instrumentation and corresponding assertions, with slow\n"
 "  assertions enabled.\n"),
 
-    JS_FN_HELP("disableSPSProfiling", DisableSPSProfiling, 0, 0,
-"disableSPSProfiling()",
-"  Disables SPS instrumentation"),
+    JS_FN_HELP("disableGeckoProfiling", DisableGeckoProfiling, 0, 0,
+"disableGeckoProfiling()",
+"  Disables Gecko Profiler instrumentation"),
 
     JS_FN_HELP("isLatin1", IsLatin1, 1, 0,
 "isLatin1(s)",
 "  Return true iff the string's characters are stored as Latin1."),
 
     JS_FN_HELP("stackPointerInfo", StackPointerInfo, 0, 0,
 "stackPointerInfo()",
 "  Return an int32 value which corresponds to the offset of the latest stack\n"
--- a/js/src/tests/js1_8_5/extensions/sps-generators.js
+++ b/js/src/tests/js1_8_5/extensions/sps-generators.js
@@ -1,37 +1,37 @@
 // |reftest| skip-if(!xulRuntime.shell)
 
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 
 //-----------------------------------------------------------------------------
 var BUGNUMBER = 822041;
-var summary = "Live generators should not cache SPS state";
+var summary = "Live generators should not cache Gecko Profiler state";
 
 print(BUGNUMBER + ": " + summary);
 
 function gen() {
   var x = yield turnoff();
   yield x;
   yield 'bye';
 }
 
 function turnoff() {
   print("Turning off profiler\n");
-  disableSPSProfiling();
+  disableGeckoProfiling();
   return 'hi';
 }
 
 for (var slowAsserts of [ true, false ]) {
   // The slowAssertions setting is not expected to matter
   if (slowAsserts)
-    enableSPSProfilingWithSlowAssertions();
+    enableGeckoProfilingWithSlowAssertions();
   else
-    enableSPSProfiling();
+    enableGeckoProfiling();
 
   g = gen();
   assertEq(g.next(), 'hi');
   assertEq(g.send('gurgitating...'), 'gurgitating...');
   for (var x in g)
     assertEq(x, 'bye');
 }
 
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -238,16 +238,17 @@
     macro(objectString, objectString, "[object String]") \
     macro(objectUndefined, objectUndefined, "[object Undefined]") \
     macro(of, of, "of") \
     macro(offset, offset, "offset") \
     macro(optimizedOut, optimizedOut, "optimizedOut") \
     macro(other, other, "other") \
     macro(outOfMemory, outOfMemory, "out of memory") \
     macro(ownKeys, ownKeys, "ownKeys") \
+    macro(Object_valueOf, Object_valueOf, "Object_valueOf") \
     macro(parseFloat, parseFloat, "parseFloat") \
     macro(parseInt, parseInt, "parseInt") \
     macro(pattern, pattern, "pattern") \
     macro(pending, pending, "pending") \
     macro(PluralRules, PluralRules, "PluralRules") \
     macro(PluralRulesSelect, PluralRulesSelect, "Intl_PluralRules_Select") \
     macro(percentSign, percentSign, "percentSign") \
     macro(plusSign, plusSign, "plusSign") \
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -29,18 +29,18 @@
 #include "js/Date.h"
 #include "js/GCAPI.h"
 #include "js/UbiNodeBreadthFirst.h"
 #include "js/Vector.h"
 #include "proxy/ScriptedProxyHandler.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/AsyncFunction.h"
 #include "vm/DebuggerMemory.h"
+#include "vm/GeckoProfiler.h"
 #include "vm/GeneratorObject.h"
-#include "vm/SPSProfiler.h"
 #include "vm/TraceLogging.h"
 #include "vm/WrapperObject.h"
 #include "wasm/WasmInstance.h"
 
 #include "jsgcinlines.h"
 #include "jsobjinlines.h"
 #include "jsopcodeinlines.h"
 #include "jsscriptinlines.h"
rename from js/src/vm/SPSProfiler.cpp
rename to js/src/vm/GeckoProfiler.cpp
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/GeckoProfiler.cpp
@@ -1,15 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "vm/SPSProfiler.h"
+#include "vm/GeckoProfiler.h"
 
 #include "mozilla/DebugOnly.h"
 
 #include "jsnum.h"
 #include "jsprf.h"
 #include "jsscript.h"
 
 #include "jit/BaselineFrame.h"
@@ -18,58 +18,58 @@
 #include "jit/JitFrameIterator.h"
 #include "jit/JitFrames.h"
 #include "vm/StringBuffer.h"
 
 using namespace js;
 
 using mozilla::DebugOnly;
 
-SPSProfiler::SPSProfiler(JSRuntime* rt)
+GeckoProfiler::GeckoProfiler(JSRuntime* rt)
   : rt(rt),
-    strings(mutexid::SPSProfilerStrings),
+    strings(mutexid::GeckoProfilerStrings),
     stack_(nullptr),
     size_(nullptr),
     max_(0),
     slowAssertions(false),
     enabled_(false),
     eventMarker_(nullptr)
 {
     MOZ_ASSERT(rt != nullptr);
 }
 
 bool
-SPSProfiler::init()
+GeckoProfiler::init()
 {
     auto locked = strings.lock();
     if (!locked->init())
         return false;
 
     return true;
 }
 
 void
-SPSProfiler::setProfilingStack(ProfileEntry* stack, uint32_t* size, uint32_t max)
+GeckoProfiler::setProfilingStack(ProfileEntry* stack, uint32_t* size, uint32_t max)
 {
     MOZ_ASSERT_IF(size_ && *size_ != 0, !enabled());
     MOZ_ASSERT(strings.lock()->initialized());
 
     stack_ = stack;
     size_  = size;
     max_   = max;
 }
 
 void
-SPSProfiler::setEventMarker(void (*fn)(const char*))
+GeckoProfiler::setEventMarker(void (*fn)(const char*))
 {
     eventMarker_ = fn;
 }
 
 void
-SPSProfiler::enable(bool enabled)
+GeckoProfiler::enable(bool enabled)
 {
     MOZ_ASSERT(installed());
 
     if (enabled_ == enabled)
         return;
 
     /*
      * Ensure all future generated code will be instrumented, or that all
@@ -89,17 +89,17 @@ SPSProfiler::enable(bool enabled)
     // Ensure that lastProfilingFrame is null before 'enabled' becomes true.
     if (rt->jitActivation) {
         rt->jitActivation->setLastProfilingFrame(nullptr);
         rt->jitActivation->setLastProfilingCallSite(nullptr);
     }
 
     enabled_ = enabled;
 
-    /* Toggle SPS-related jumps on baseline jitcode.
+    /* Toggle Gecko Profiler-related jumps on baseline jitcode.
      * The call to |ReleaseAllJITCode| above will release most baseline jitcode, but not
      * jitcode for scripts with active frames on the stack.  These scripts need to have
      * their profiler state toggled so they behave properly.
      */
     jit::ToggleBaselineProfiling(rt, enabled);
 
     /* Update lastProfilingFrame to point to the top-most JS jit-frame currently on
      * stack.
@@ -124,61 +124,61 @@ SPSProfiler::enable(bool enabled)
                 jitActivation = jitActivation->prevJitActivation();
             }
         }
     }
 }
 
 /* Lookup the string for the function/script, creating one if necessary */
 const char*
-SPSProfiler::profileString(JSScript* script, JSFunction* maybeFun)
+GeckoProfiler::profileString(JSScript* script, JSFunction* maybeFun)
 {
     auto locked = strings.lock();
     MOZ_ASSERT(locked->initialized());
 
     ProfileStringMap::AddPtr s = locked->lookupForAdd(script);
 
     if (!s) {
         auto str = allocProfileString(script, maybeFun);
         if (!str || !locked->add(s, script, mozilla::Move(str)))
             return nullptr;
     }
 
     return s->value().get();
 }
 
 void
-SPSProfiler::onScriptFinalized(JSScript* script)
+GeckoProfiler::onScriptFinalized(JSScript* script)
 {
     /*
      * This function is called whenever a script is destroyed, regardless of
      * whether profiling has been turned on, so don't invoke a function on an
      * invalid hash set. Also, even if profiling was enabled but then turned
      * off, we still want to remove the string, so no check of enabled() is
      * done.
      */
     auto locked = strings.lock();
     if (!locked->initialized())
         return;
     if (ProfileStringMap::Ptr entry = locked->lookup(script))
         locked->remove(entry);
 }
 
 void
-SPSProfiler::markEvent(const char* event)
+GeckoProfiler::markEvent(const char* event)
 {
     MOZ_ASSERT(enabled());
     if (eventMarker_) {
         JS::AutoSuppressGCAnalysis nogc;
         eventMarker_(event);
     }
 }
 
 bool
-SPSProfiler::enter(JSContext* cx, JSScript* script, JSFunction* maybeFun)
+GeckoProfiler::enter(JSContext* cx, JSScript* script, JSFunction* maybeFun)
 {
     const char* str = profileString(script, maybeFun);
     if (str == nullptr) {
         ReportOutOfMemory(cx);
         return false;
     }
 
 #ifdef DEBUG
@@ -192,17 +192,17 @@ SPSProfiler::enter(JSContext* cx, JSScri
     }
 #endif
 
     push(str, nullptr, script, script->code(), /* copy = */ true);
     return true;
 }
 
 void
-SPSProfiler::exit(JSScript* script, JSFunction* maybeFun)
+GeckoProfiler::exit(JSScript* script, JSFunction* maybeFun)
 {
     pop();
 
 #ifdef DEBUG
     /* Sanity check to make sure push/pop balanced */
     if (*size_ < max_) {
         const char* str = profileString(script, maybeFun);
         /* Can't fail lookup because we should already be in the set */
@@ -225,34 +225,34 @@ SPSProfiler::exit(JSScript* script, JSFu
         MOZ_ASSERT(strcmp((const char*) stack_[*size_].label(), str) == 0);
         stack_[*size_].setLabel(nullptr);
         stack_[*size_].setPC(nullptr);
     }
 #endif
 }
 
 void
-SPSProfiler::beginPseudoJS(const char* string, void* sp)
+GeckoProfiler::beginPseudoJS(const char* string, void* sp)
 {
     /* these operations cannot be re-ordered, so volatile-ize operations */
     volatile ProfileEntry* stack = stack_;
     volatile uint32_t* size = size_;
     uint32_t current = *size;
 
     MOZ_ASSERT(installed());
     if (current < max_) {
         stack[current].setLabel(string);
         stack[current].initCppFrame(sp, 0);
         stack[current].setFlag(ProfileEntry::BEGIN_PSEUDO_JS);
     }
     *size = current + 1;
 }
 
 void
-SPSProfiler::push(const char* string, void* sp, JSScript* script, jsbytecode* pc, bool copy,
+GeckoProfiler::push(const char* string, void* sp, JSScript* script, jsbytecode* pc, bool copy,
                   ProfileEntry::Category category)
 {
     MOZ_ASSERT_IF(sp != nullptr, script == nullptr && pc == nullptr);
     MOZ_ASSERT_IF(sp == nullptr, script != nullptr && pc != nullptr);
 
     /* these operations cannot be re-ordered, so volatile-ize operations */
     volatile ProfileEntry* stack = stack_;
     volatile uint32_t* size = size_;
@@ -279,31 +279,31 @@ SPSProfiler::push(const char* string, vo
             entry.setFlag(js::ProfileEntry::FRAME_LABEL_COPY);
         else
             entry.unsetFlag(js::ProfileEntry::FRAME_LABEL_COPY);
     }
     *size = current + 1;
 }
 
 void
-SPSProfiler::pop()
+GeckoProfiler::pop()
 {
     MOZ_ASSERT(installed());
     MOZ_ASSERT(*size_ > 0);
     (*size_)--;
 }
 
 /*
  * Serializes the script/function pair into a "descriptive string" which is
  * allowed to fail. This function cannot trigger a GC because it could finalize
  * some scripts, resize the hash table of profile strings, and invalidate the
  * AddPtr held while invoking allocProfileString.
  */
 UniqueChars
-SPSProfiler::allocProfileString(JSScript* script, JSFunction* maybeFun)
+GeckoProfiler::allocProfileString(JSScript* script, JSFunction* maybeFun)
 {
     // Note: this profiler string is regexp-matched by
     // devtools/client/profiler/cleopatra/js/parserWorker.js.
 
     // Get the function name, if any.
     JSAtom* atom = maybeFun ? maybeFun->displayAtom() : nullptr;
 
     // Get the script filename, if any, and its length.
@@ -341,44 +341,44 @@ SPSProfiler::allocProfileString(JSScript
     }
 
     MOZ_ASSERT(ret == len, "Computed length should match actual length!");
 
     return cstr;
 }
 
 void
-SPSProfiler::trace(JSTracer* trc)
+GeckoProfiler::trace(JSTracer* trc)
 {
     if (stack_) {
         size_t limit = Min(*size_, max_);
         for (size_t i = 0; i < limit; i++)
             stack_[i].trace(trc);
     }
 }
 
 void
-SPSProfiler::fixupStringsMapAfterMovingGC()
+GeckoProfiler::fixupStringsMapAfterMovingGC()
 {
     auto locked = strings.lock();
     if (!locked->initialized())
         return;
 
     for (ProfileStringMap::Enum e(locked.get()); !e.empty(); e.popFront()) {
         JSScript* script = e.front().key();
         if (IsForwarded(script)) {
             script = Forwarded(script);
             e.rekeyFront(script);
         }
     }
 }
 
 #ifdef JSGC_HASH_TABLE_CHECKS
 void
-SPSProfiler::checkStringsMapAfterMovingGC()
+GeckoProfiler::checkStringsMapAfterMovingGC()
 {
     auto locked = strings.lock();
     if (!locked->initialized())
         return;
 
     for (auto r = locked->all(); !r.empty(); r.popFront()) {
         JSScript* script = r.front().key();
         CheckGCThingAfterMovingGC(script);
@@ -393,88 +393,89 @@ ProfileEntry::trace(JSTracer* trc)
 {
     if (isJs()) {
         JSScript* s = rawScript();
         TraceNullableRoot(trc, &s, "ProfileEntry script");
         spOrScript = s;
     }
 }
 
-SPSEntryMarker::SPSEntryMarker(JSRuntime* rt,
-                               JSScript* script
-                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-    : profiler(&rt->spsProfiler)
+GeckoProfilerEntryMarker::GeckoProfilerEntryMarker(JSRuntime* rt,
+                                                   JSScript* script
+                                                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+    : profiler(&rt->geckoProfiler)
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     if (!profiler->installed()) {
         profiler = nullptr;
         return;
     }
     size_before = *profiler->size_;
     // We want to push a CPP frame so the profiler can correctly order JS and native stacks.
     profiler->beginPseudoJS("js::RunScript", this);
     profiler->push("js::RunScript", nullptr, script, script->code(), /* copy = */ false);
 }
 
-SPSEntryMarker::~SPSEntryMarker()
+GeckoProfilerEntryMarker::~GeckoProfilerEntryMarker()
 {
     if (profiler == nullptr)
         return;
 
     profiler->pop();
     profiler->endPseudoJS();
     MOZ_ASSERT(size_before == *profiler->size_);
 }
 
-AutoSPSEntry::AutoSPSEntry(JSRuntime* rt, const char* label, ProfileEntry::Category category
-                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-    : profiler_(&rt->spsProfiler)
+AutoGeckoProfilerEntry::AutoGeckoProfilerEntry(JSRuntime* rt, const char* label,
+                                               ProfileEntry::Category category
+                                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+    : profiler_(&rt->geckoProfiler)
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     if (!profiler_->installed()) {
         profiler_ = nullptr;
         return;
     }
     sizeBefore_ = *profiler_->size_;
     profiler_->beginPseudoJS(label, this);
     profiler_->push(label, this, nullptr, nullptr, /* copy = */ false, category);
 }
 
-AutoSPSEntry::~AutoSPSEntry()
+AutoGeckoProfilerEntry::~AutoGeckoProfilerEntry()
 {
     if (!profiler_)
         return;
 
     profiler_->pop();
     profiler_->endPseudoJS();
     MOZ_ASSERT(sizeBefore_ == *profiler_->size_);
 }
 
-SPSBaselineOSRMarker::SPSBaselineOSRMarker(JSRuntime* rt, bool hasSPSFrame
-                                           MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
-    : profiler(&rt->spsProfiler)
+GeckoProfilerBaselineOSRMarker::GeckoProfilerBaselineOSRMarker(JSRuntime* rt, bool hasProfilerFrame
+                                                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
+    : profiler(&rt->geckoProfiler)
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-    if (!hasSPSFrame || !profiler->enabled() ||
+    if (!hasProfilerFrame || !profiler->enabled() ||
         profiler->size() >= profiler->maxSize())
     {
         profiler = nullptr;
         return;
     }
 
     size_before = profiler->size();
     if (profiler->size() == 0)
         return;
 
     ProfileEntry& entry = profiler->stack()[profiler->size() - 1];
     MOZ_ASSERT(entry.isJs());
     entry.setOSR();
 }
 
-SPSBaselineOSRMarker::~SPSBaselineOSRMarker()
+GeckoProfilerBaselineOSRMarker::~GeckoProfilerBaselineOSRMarker()
 {
     if (profiler == nullptr)
         return;
 
     MOZ_ASSERT(size_before == *profiler->size_);
     if (profiler->size() == 0)
         return;
 
@@ -520,36 +521,36 @@ ProfileEntry::setPC(jsbytecode* pc) vola
     JSScript* script = this->script();
     MOZ_ASSERT(script); // This should not be called while profiling is suppressed.
     lineOrPcOffset = pc == nullptr ? NullPCOffset : script->pcToOffset(pc);
 }
 
 JS_FRIEND_API(void)
 js::SetContextProfilingStack(JSContext* cx, ProfileEntry* stack, uint32_t* size, uint32_t max)
 {
-    cx->spsProfiler.setProfilingStack(stack, size, max);
+    cx->geckoProfiler.setProfilingStack(stack, size, max);
 }
 
 JS_FRIEND_API(void)
 js::EnableContextProfilingStack(JSContext* cx, bool enabled)
 {
-    cx->spsProfiler.enable(enabled);
+    cx->geckoProfiler.enable(enabled);
 }
 
 JS_FRIEND_API(void)
 js::RegisterContextProfilingEventMarker(JSContext* cx, void (*fn)(const char*))
 {
-    MOZ_ASSERT(cx->spsProfiler.enabled());
-    cx->spsProfiler.setEventMarker(fn);
+    MOZ_ASSERT(cx->geckoProfiler.enabled());
+    cx->geckoProfiler.setEventMarker(fn);
 }
 
 JS_FRIEND_API(jsbytecode*)
 js::ProfilingGetPC(JSContext* cx, JSScript* script, void* ip)
 {
-    return cx->spsProfiler.ipToPC(script, size_t(ip));
+    return cx->geckoProfiler.ipToPC(script, size_t(ip));
 }
 
 AutoSuppressProfilerSampling::AutoSuppressProfilerSampling(JSContext* cx
                                                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
   : rt_(cx->runtime()),
     previouslyEnabled_(rt_->isProfilerSamplingEnabled())
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
rename from js/src/vm/SPSProfiler.h
rename to js/src/vm/GeckoProfiler.h
--- a/js/src/vm/SPSProfiler.h
+++ b/js/src/vm/GeckoProfiler.h
@@ -1,93 +1,95 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef vm_SPSProfiler_h
-#define vm_SPSProfiler_h
+#ifndef vm_GeckoProfiler_h
+#define vm_GeckoProfiler_h
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/GuardObjects.h"
 
 #include <stddef.h>
 
 #include "jsscript.h"
 
 #include "js/ProfilingStack.h"
 #include "threading/ExclusiveData.h"
 #include "vm/MutexIDs.h"
 
 /*
- * SPS Profiler integration with the JS Engine
+ * Gecko Profiler integration with the JS Engine
  * https://developer.mozilla.org/en/Performance/Profiling_with_the_Built-in_Profiler
  *
- * The SPS profiler (found in tools/profiler) is an implementation of a profiler
- * which has the ability to walk the C++ stack as well as use instrumentation to
- * gather information. When dealing with JS, however, SPS needs integration
- * with the engine because otherwise it is very difficult to figure out what
- * javascript is executing.
+ * The Gecko Profiler (found in tools/profiler) is an implementation of a
+ * profiler which has the ability to walk the C++ stack as well as use
+ * instrumentation to gather information. When dealing with JS, however, the
+ * profiler needs integration with the engine because otherwise it is very
+ * difficult to figure out what javascript is executing.
  *
- * The current method of integration with SPS is a form of instrumentation:
- * every time a JS function is entered, a bit of information is pushed onto a
- * stack that SPS owns and maintains. This information is then popped at the end
- * of the JS function. SPS informs the JS engine of this stack at runtime, and
- * it can by turned on/off dynamically.
+ * The current method of integration with the profiler is a form of
+ * instrumentation: every time a JS function is entered, a bit of information
+ * is pushed onto a stack that the profiler owns and maintains. This
+ * information is then popped at the end of the JS function. The profiler
+ * informs the JS engine of this stack at runtime, and it can by turned on/off
+ * dynamically.
  *
- * The SPS stack has three parameters: a base pointer, a size, and a maximum
- * size. The stack is the ProfileEntry stack which will have information written
- * to it. The size location is a pointer to an integer which represents the
- * current size of the stack (number of valid frames). This size will be
- * modified when JS functions are called. The maximum specified is the maximum
- * capacity of the ProfileEntry stack.
+ * The profiler stack has three parameters: a base pointer, a size, and a
+ * maximum size. The stack is the ProfileEntry stack which will have
+ * information written to it. The size location is a pointer to an integer
+ * which represents the current size of the stack (number of valid frames).
+ * This size will be modified when JS functions are called. The maximum
+ * specified is the maximum capacity of the ProfileEntry stack.
  *
  * Throughout execution, the size of the stack recorded in memory may exceed the
  * maximum. The JS engine will not write any information past the maximum limit,
- * but it will still maintain the size of the stack. SPS code is aware of this
- * and iterates the stack accordingly.
+ * but it will still maintain the size of the stack. Profiler code is aware of
+ * this and iterates the stack accordingly.
  *
- * There is some information pushed on the SPS stack for every JS function that
- * is entered. First is a char* pointer of a description of what function was
- * entered. Currently this string is of the form "function (file:line)" if
+ * There is some information pushed on the profiler stack for every JS function
+ * that is entered. First is a char* pointer of a description of what function
+ * was entered. Currently this string is of the form "function (file:line)" if
  * there's a function name, or just "file:line" if there's no function name
  * available. The other bit of information is the relevant C++ (native) stack
  * pointer. This stack pointer is what enables the interleaving of the C++ and
  * the JS stack. Finally, throughout execution of the function, some extra
  * information may be updated on the ProfileEntry structure.
  *
  * = Profile Strings
  *
  * The profile strings' allocations and deallocation must be carefully
  * maintained, and ideally at a very low overhead cost. For this reason, the JS
  * engine maintains a mapping of all known profile strings. These strings are
  * keyed in lookup by a JSScript*, but are serialized with a JSFunction*,
  * JSScript* pair. A JSScript will destroy its corresponding profile string when
  * the script is finalized.
  *
- * For this reason, a char* pointer pushed on the SPS stack is valid only while
- * it is on the SPS stack. SPS uses sampling to read off information from this
- * instrumented stack, and it therefore copies the string byte for byte when a
- * JS function is encountered during sampling.
+ * For this reason, a char* pointer pushed on the profiler stack is valid only
+ * while it is on the profiler stack. The profiler uses sampling to read off
+ * information from this instrumented stack, and it therefore copies the string
+ * byte for byte when a JS function is encountered during sampling.
  *
  * = Native Stack Pointer
  *
  * The actual value pushed as the native pointer is nullptr for most JS
  * functions. The reason for this is that there's actually very little
  * correlation between the JS stack and the C++ stack because many JS functions
  * all run in the same C++ frame, or can even go backwards in C++ when going
  * from the JIT back to the interpreter.
  *
  * To alleviate this problem, all JS functions push nullptr as their "native
  * stack pointer" to indicate that it's a JS function call. The function
- * RunScript(), however, pushes an actual C++ stack pointer onto the SPS stack.
- * This way when interleaving C++ and JS, if SPS sees a nullptr native stack
- * pointer on the SPS stack, it looks backwards for the first non-nullptr
- * pointer and uses that for all subsequent nullptr native stack pointers.
+ * RunScript(), however, pushes an actual C++ stack pointer onto the profiler
+ * stack. This way when interleaving C++ and JS, if the Gecko Profiler sees a
+ * nullptr native stack pointer on the profiler stack, it looks backwards for
+ * the first non-nullptr pointer and uses that for all subsequent nullptr
+ * native stack pointers.
  *
  * = Line Numbers
  *
  * One goal of sampling is to get both a backtrace of the JS stack, but also
  * know where within each function on the stack execution currently is. For
  * this, each ProfileEntry has a 'pc' field to tell where its execution
  * currently is. This field is updated whenever a call is made to another JS
  * function, and for the JIT it is also updated whenever the JIT is left.
@@ -104,48 +106,48 @@
  * JIT code to pc which can be accessed safely because they will only be
  * accessed from a signal handler when the JIT code is executing.
  */
 
 namespace js {
 
 // The `ProfileStringMap` weakly holds its `JSScript*` keys and owns its string
 // values. Entries are removed when the `JSScript` is finalized; see
-// `SPSProfiler::onScriptFinalized`.
+// `GeckoProfiler::onScriptFinalized`.
 using ProfileStringMap = HashMap<JSScript*,
                                  UniqueChars,
                                  DefaultHasher<JSScript*>,
                                  SystemAllocPolicy>;
 
-class AutoSPSEntry;
-class SPSEntryMarker;
-class SPSBaselineOSRMarker;
+class AutoGeckoProfilerEntry;
+class GeckoProfilerEntryMarker;
+class GeckoProfilerBaselineOSRMarker;
 
-class SPSProfiler
+class GeckoProfiler
 {
-    friend class AutoSPSEntry;
-    friend class SPSEntryMarker;
-    friend class SPSBaselineOSRMarker;
+    friend class AutoGeckoProfilerEntry;
+    friend class GeckoProfilerEntryMarker;
+    friend class GeckoProfilerBaselineOSRMarker;
 
     JSRuntime*           rt;
     ExclusiveData<ProfileStringMap> strings;
     ProfileEntry*        stack_;
     uint32_t*            size_;
     uint32_t             max_;
     bool                 slowAssertions;
     uint32_t             enabled_;
     void                (*eventMarker_)(const char*);
 
     UniqueChars allocProfileString(JSScript* script, JSFunction* function);
     void push(const char* string, void* sp, JSScript* script, jsbytecode* pc, bool copy,
               ProfileEntry::Category category = ProfileEntry::Category::JS);
     void pop();
 
   public:
-    explicit SPSProfiler(JSRuntime* rt);
+    explicit GeckoProfiler(JSRuntime* rt);
 
     bool init();
 
     uint32_t** addressOfSizePointer() {
         return &size_;
     }
 
     uint32_t* addressOfMaxSize() {
@@ -229,113 +231,112 @@ class MOZ_RAII AutoSuppressProfilerSampl
 
   private:
     JSRuntime* rt_;
     bool previouslyEnabled_;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 inline size_t
-SPSProfiler::stringsCount()
+GeckoProfiler::stringsCount()
 {
     return strings.lock()->count();
 }
 
 inline void
-SPSProfiler::stringsReset()
+GeckoProfiler::stringsReset()
 {
     strings.lock()->clear();
 }
 
 /*
  * This class is used in RunScript() to push the marker onto the sampling stack
  * that we're about to enter JS function calls. This is the only time in which a
  * valid stack pointer is pushed to the sampling stack.
  */
-class MOZ_RAII SPSEntryMarker
+class MOZ_RAII GeckoProfilerEntryMarker
 {
   public:
-    explicit SPSEntryMarker(JSRuntime* rt,
-                            JSScript* script
-                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
-    ~SPSEntryMarker();
+    explicit GeckoProfilerEntryMarker(JSRuntime* rt,
+                                      JSScript* script
+                                      MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+    ~GeckoProfilerEntryMarker();
 
   private:
-    SPSProfiler* profiler;
+    GeckoProfiler* profiler;
     mozilla::DebugOnly<uint32_t> size_before;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 /*
- * RAII class to automatically add SPS psuedo frame entries.
+ * RAII class to automatically add Gecko Profiler pseudo frame entries.
  *
  * NB: The `label` string must be statically allocated.
  */
-class MOZ_NONHEAP_CLASS AutoSPSEntry
+class MOZ_NONHEAP_CLASS AutoGeckoProfilerEntry
 {
   public:
-    explicit AutoSPSEntry(JSRuntime* rt, const char* label,
-                          ProfileEntry::Category category = ProfileEntry::Category::JS
-                          MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
-    ~AutoSPSEntry();
+    explicit AutoGeckoProfilerEntry(JSRuntime* rt, const char* label,
+                                    ProfileEntry::Category category = ProfileEntry::Category::JS
+                                    MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+    ~AutoGeckoProfilerEntry();
 
   private:
-    SPSProfiler* profiler_;
+    GeckoProfiler* profiler_;
     mozilla::DebugOnly<uint32_t> sizeBefore_;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 /*
  * This class is used in the interpreter to bound regions where the baseline JIT
  * being entered via OSR.  It marks the current top pseudostack entry as
  * OSR-ed
  */
-class MOZ_RAII SPSBaselineOSRMarker
+class MOZ_RAII GeckoProfilerBaselineOSRMarker
 {
   public:
-    explicit SPSBaselineOSRMarker(JSRuntime* rt, bool hasSPSFrame
-                                  MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
-    ~SPSBaselineOSRMarker();
+    explicit GeckoProfilerBaselineOSRMarker(JSRuntime* rt, bool hasProfilerFrame
+                                            MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
+    ~GeckoProfilerBaselineOSRMarker();
 
   private:
-    SPSProfiler* profiler;
+    GeckoProfiler* profiler;
     mozilla::DebugOnly<uint32_t> size_before;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 /*
- * SPS is the profiling backend used by the JS engine to enable time profiling.
- * More information can be found in vm/SPSProfiler.{h,cpp}. This class manages
- * the instrumentation portion of the profiling for JIT code.
+ * This class manages the instrumentation portion of the profiling for JIT
+ * code.
  *
  * The instrumentation tracks entry into functions, leaving those functions via
  * a function call, reentering the functions from a function call, and exiting
  * the functions from returning. This class also handles inline frames and
  * manages the instrumentation which needs to be attached to them as well.
  *
  * The basic methods which emit instrumentation are at the end of this class,
  * and the management functions are all described in the middle.
  */
 template<class Assembler, class Register>
-class SPSInstrumentation
+class GeckoProfilerInstrumentation
 {
-    SPSProfiler* profiler_; // Instrumentation location management
+    GeckoProfiler* profiler_; // Instrumentation location management
 
   public:
     /*
      * Creates instrumentation which writes information out the the specified
      * profiler's stack and constituent fields.
      */
-    explicit SPSInstrumentation(SPSProfiler* profiler) : profiler_(profiler) {}
+    explicit GeckoProfilerInstrumentation(GeckoProfiler* profiler) : profiler_(profiler) {}
 
-    /* Small proxies around SPSProfiler */
+    /* Small proxies around GeckoProfiler */
     bool enabled() { return profiler_ && profiler_->enabled(); }
-    SPSProfiler* profiler() { MOZ_ASSERT(enabled()); return profiler_; }
+    GeckoProfiler* profiler() { MOZ_ASSERT(enabled()); return profiler_; }
     void disable() { profiler_ = nullptr; }
 };
 
 
 /* Get a pointer to the top-most profiling frame, given the exit frame pointer. */
 void* GetTopProfilingJitFrame(uint8_t* exitFramePtr);
 
 } /* namespace js */
 
-#endif /* vm_SPSProfiler_h */
+#endif /* vm_GeckoProfiler_h */
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -369,17 +369,17 @@ js::RunScript(JSContext* cx, RunState& s
 
     if (!Debugger::checkNoExecute(cx, state.script()))
         return false;
 
 #if defined(MOZ_HAVE_RDTSC)
     js::AutoStopwatch stopwatch(cx);
 #endif // defined(MOZ_HAVE_RDTSC)
 
-    SPSEntryMarker marker(cx->runtime(), state.script());
+    GeckoProfilerEntryMarker marker(cx->runtime(), state.script());
 
     state.script()->ensureNonLazyCanonicalFunction();
 
     if (jit::IsIonEnabled(cx)) {
         jit::MethodStatus status = jit::CanEnter(cx, state);
         if (status == jit::Method_Error)
             return false;
         if (status == jit::Method_Compiled) {
@@ -1920,34 +1920,35 @@ END_CASE(JSOP_LABEL)
 CASE(JSOP_LOOPENTRY)
     COUNT_COVERAGE();
     // Attempt on-stack replacement with Baseline code.
     if (jit::IsBaselineEnabled(cx)) {
         jit::MethodStatus status = jit::CanEnterBaselineAtBranch(cx, REGS.fp(), false);
         if (status == jit::Method_Error)
             goto error;
         if (status == jit::Method_Compiled) {
-            bool wasSPS = REGS.fp()->hasPushedSPSFrame();
+            bool wasProfiler = REGS.fp()->hasPushedGeckoProfilerFrame();
 
             jit::JitExecStatus maybeOsr;
             {
-                SPSBaselineOSRMarker spsOSR(cx->runtime(), wasSPS);
+                GeckoProfilerBaselineOSRMarker osr(cx->runtime(), wasProfiler);
                 maybeOsr = jit::EnterBaselineAtBranch(cx, REGS.fp(), REGS.pc);
             }
 
             // We failed to call into baseline at all, so treat as an error.
             if (maybeOsr == jit::JitExec_Aborted)
                 goto error;
 
             interpReturnOK = (maybeOsr == jit::JitExec_Ok);
 
-            // Pop the SPS frame pushed by the interpreter.  (The compiled version of the
-            // function popped a copy of the frame pushed by the OSR trampoline.)
-            if (wasSPS)
-                cx->runtime()->spsProfiler.exit(script, script->functionNonDelazifying());
+            // Pop the profiler frame pushed by the interpreter.  (The compiled
+            // version of the function popped a copy of the frame pushed by the
+            // OSR trampoline.)
+            if (wasProfiler)
+                cx->runtime()->geckoProfiler.exit(script, script->functionNonDelazifying());
 
             if (activation.entryFrame() != REGS.fp())
                 goto jit_return_pop_frame;
             goto leave_on_safe_point;
         }
     }
 END_CASE(JSOP_LOOPENTRY)
 
@@ -2878,18 +2879,18 @@ CASE(JSOP_STRICTEVAL)
     REGS.sp = args.spAfterCall();
     TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
 }
 END_CASE(JSOP_EVAL)
 
 CASE(JSOP_SPREADNEW)
 CASE(JSOP_SPREADCALL)
 CASE(JSOP_SPREADSUPERCALL)
-    if (REGS.fp()->hasPushedSPSFrame())
-        cx->runtime()->spsProfiler.updatePC(script, REGS.pc);
+    if (REGS.fp()->hasPushedGeckoProfilerFrame())
+        cx->runtime()->geckoProfiler.updatePC(script, REGS.pc);
     /* FALL THROUGH */
 
 CASE(JSOP_SPREADEVAL)
 CASE(JSOP_STRICTSPREADEVAL)
 {
     static_assert(JSOP_SPREADEVAL_LENGTH == JSOP_STRICTSPREADEVAL_LENGTH,
                   "spreadeval and strictspreadeval must be the same size");
     bool construct = JSOp(*REGS.pc) == JSOP_SPREADNEW || JSOp(*REGS.pc) == JSOP_SPREADSUPERCALL;;
@@ -2923,18 +2924,18 @@ CASE(JSOP_FUNAPPLY)
 }
 
 CASE(JSOP_NEW)
 CASE(JSOP_CALL)
 CASE(JSOP_CALLITER)
 CASE(JSOP_SUPERCALL)
 CASE(JSOP_FUNCALL)
 {
-    if (REGS.fp()->hasPushedSPSFrame())
-        cx->runtime()->spsProfiler.updatePC(script, REGS.pc);
+    if (REGS.fp()->hasPushedGeckoProfilerFrame())
+        cx->runtime()->geckoProfiler.updatePC(script, REGS.pc);
 
     MaybeConstruct construct = MaybeConstruct(*REGS.pc == JSOP_NEW || *REGS.pc == JSOP_SUPERCALL);
     unsigned argStackSlots = GET_ARGC(REGS.pc) + construct;
 
     MOZ_ASSERT(REGS.stackDepth() >= 2u + GET_ARGC(REGS.pc));
     CallArgs args = CallArgsFromSp(argStackSlots, REGS.sp, construct);
 
     JSFunction* maybeFun;
--- a/js/src/vm/MutexIDs.h
+++ b/js/src/vm/MutexIDs.h
@@ -23,17 +23,17 @@
                                       \
   _(ShellAsyncTasks,             350) \
                                       \
   _(GCLock,                      400) \
                                       \
   _(SharedImmutableStringsCache, 500) \
   _(FutexRuntime,                500) \
   _(PromiseTaskPtrVector,        500) \
-  _(SPSProfilerStrings,          500) \
+  _(GeckoProfilerStrings,        500) \
   _(ProtectedRegionTree,         500) \
   _(WasmSigIdSet,                500) \
   _(ShellOffThreadState,         500) \
   _(SimulatorCacheLock,          500) \
   _(Arm64SimulatorLock,          500) \
   _(IonSpewer,                   500) \
   _(PerfSpewer,                  500) \
   _(TraceLoggerThreadState,      500) \
--- a/js/src/vm/Probes-inl.h
+++ b/js/src/vm/Probes-inl.h
@@ -33,36 +33,36 @@ probes::EnterScript(JSContext* cx, JSScr
                     InterpreterFrame* fp)
 {
 #ifdef INCLUDE_MOZILLA_DTRACE
     if (JAVASCRIPT_FUNCTION_ENTRY_ENABLED())
         DTraceEnterJSFun(cx, maybeFun, script);
 #endif
 
     JSRuntime* rt = cx->runtime();
-    if (rt->spsProfiler.enabled()) {
-        if (!rt->spsProfiler.enter(cx, script, maybeFun))
+    if (rt->geckoProfiler.enabled()) {
+        if (!rt->geckoProfiler.enter(cx, script, maybeFun))
             return false;
-        MOZ_ASSERT_IF(!fp->script()->isGenerator(), !fp->hasPushedSPSFrame());
-        fp->setPushedSPSFrame();
+        MOZ_ASSERT_IF(!fp->script()->isGenerator(), !fp->hasPushedGeckoProfilerFrame());
+        fp->setPushedGeckoProfilerFrame();
     }
 
     return true;
 }
 
 inline void
-probes::ExitScript(JSContext* cx, JSScript* script, JSFunction* maybeFun, bool popSPSFrame)
+probes::ExitScript(JSContext* cx, JSScript* script, JSFunction* maybeFun, bool popProfilerFrame)
 {
 #ifdef INCLUDE_MOZILLA_DTRACE
     if (JAVASCRIPT_FUNCTION_RETURN_ENABLED())
         DTraceExitJSFun(cx, maybeFun, script);
 #endif
 
-    if (popSPSFrame)
-        cx->runtime()->spsProfiler.exit(script, maybeFun);
+    if (popProfilerFrame)
+        cx->runtime()->geckoProfiler.exit(script, maybeFun);
 }
 
 inline bool
 probes::StartExecution(JSScript* script)
 {
     bool ok = true;
 
 #ifdef INCLUDE_MOZILLA_DTRACE
--- a/js/src/vm/Probes.h
+++ b/js/src/vm/Probes.h
@@ -58,17 +58,17 @@ extern const char anonymousName[];
  * firing.
  */
 bool CallTrackingActive(JSContext*);
 
 /* Entering a JS function */
 bool EnterScript(JSContext*, JSScript*, JSFunction*, InterpreterFrame*);
 
 /* About to leave a JS function */
-void ExitScript(JSContext*, JSScript*, JSFunction*, bool popSPSFrame);
+void ExitScript(JSContext*, JSScript*, JSFunction*, bool popProfilerFrame);
 
 /* Executing a script */
 bool StartExecution(JSScript* script);
 
 /* Script has completed execution */
 bool StopExecution(JSScript* script);
 
 /*
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -192,17 +192,17 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
     simulator_(nullptr),
 #endif
     scriptAndCountsVector(nullptr),
     lcovOutput(),
     NaNValue(DoubleNaNValue()),
     negativeInfinityValue(DoubleValue(NegativeInfinity<double>())),
     positiveInfinityValue(DoubleValue(PositiveInfinity<double>())),
     emptyString(nullptr),
-    spsProfiler(thisFromCtor()),
+    geckoProfiler(thisFromCtor()),
     profilingScripts(false),
     suppressProfilerSampling(false),
     hadOutOfMemory(false),
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     runningOOMTest(false),
 #endif
     allowRelazificationForTesting(false),
     defaultFreeOp_(nullptr),
@@ -345,17 +345,17 @@ JSRuntime::init(uint32_t maxbytes, uint3
 
     jitSupportsFloatingPoint = js::jit::JitSupportsFloatingPoint();
     jitSupportsUnalignedAccesses = js::jit::JitSupportsUnalignedAccesses();
     jitSupportsSimd = js::jit::JitSupportsSimd();
 
     if (!wasm::EnsureSignalHandlers(this))
         return false;
 
-    if (!spsProfiler.init())
+    if (!geckoProfiler.init())
         return false;
 
     if (!fx.initInstance())
         return false;
 
     if (!parentRuntime) {
         sharedImmutableStrings_ = js::SharedImmutableStringsCache::Create();
         if (!sharedImmutableStrings_)
@@ -922,17 +922,17 @@ JS::UpdateJSContextProfilerSampleBufferG
     cx->setProfilerSampleBufferGen(generation);
     cx->updateProfilerSampleBufferLapCount(lapCount);
 }
 
 JS_FRIEND_API(bool)
 JS::IsProfilingEnabledForContext(JSContext* cx)
 {
     MOZ_ASSERT(cx);
-    return cx->spsProfiler.enabled();
+    return cx->geckoProfiler.enabled();
 }
 
 JSRuntime::IonBuilderList&
 JSRuntime::ionLazyLinkList()
 {
     MOZ_ASSERT(TlsPerThreadData.get()->runtimeFromMainThread(),
                "Should only be mutated by the main thread.");
     return ionLazyLinkList_;
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -40,20 +40,20 @@
 # include "js/Proxy.h" // For AutoEnterPolicy
 #endif
 #include "js/UniquePtr.h"
 #include "js/Vector.h"
 #include "threading/Thread.h"
 #include "vm/CodeCoverage.h"
 #include "vm/CommonPropertyNames.h"
 #include "vm/DateTime.h"
+#include "vm/GeckoProfiler.h"
 #include "vm/MallocProvider.h"
 #include "vm/Scope.h"
 #include "vm/SharedImmutableStringsCache.h"
-#include "vm/SPSProfiler.h"
 #include "vm/Stack.h"
 #include "vm/Stopwatch.h"
 #include "vm/Symbol.h"
 
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
 #endif
@@ -904,18 +904,18 @@ struct JSRuntime : public JS::shadow::Ru
     const js::Value     NaNValue;
     const js::Value     negativeInfinityValue;
     const js::Value     positiveInfinityValue;
 
     js::PropertyName*   emptyString;
 
     mozilla::UniquePtr<js::SourceHook> sourceHook;
 
-    /* SPS profiling metadata */
-    js::SPSProfiler     spsProfiler;
+    /* Gecko profiling metadata */
+    js::GeckoProfiler   geckoProfiler;
 
     /* If true, new scripts must be created with PC counter information. */
     bool                profilingScripts;
 
     /* Whether sampling should be enabled or not. */
   private:
     mozilla::Atomic<bool, mozilla::SequentiallyConsistent> suppressProfilerSampling;
 
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -23,18 +23,18 @@
 #include "jsscript.h"
 
 #include "gc/Marking.h"
 #include "gc/Policy.h"
 #include "gc/Rooting.h"
 #include "js/CharacterEncoding.h"
 #include "js/Vector.h"
 #include "vm/Debugger.h"
+#include "vm/GeckoProfiler.h"
 #include "vm/SavedFrame.h"
-#include "vm/SPSProfiler.h"
 #include "vm/StringBuffer.h"
 #include "vm/Time.h"
 #include "vm/WrapperObject.h"
 
 #include "jscntxtinlines.h"
 
 #include "vm/NativeObject-inl.h"
 #include "vm/Stack-inl.h"
@@ -1142,17 +1142,17 @@ SavedStacks::saveCurrentStack(JSContext*
         cx->isExceptionPending() ||
         !cx->global() ||
         !cx->global()->isStandardClassResolved(JSProto_Object))
     {
         frame.set(nullptr);
         return true;
     }
 
-    AutoSPSEntry psuedoFrame(cx->runtime(), "js::SavedStacks::saveCurrentStack");
+    AutoGeckoProfilerEntry psuedoFrame(cx->runtime(), "js::SavedStacks::saveCurrentStack");
     FrameIter iter(cx);
     return insertFrames(cx, iter, frame, mozilla::Move(capture));
 }
 
 bool
 SavedStacks::copyAsyncStack(JSContext* cx, HandleObject asyncStack, HandleString asyncCause,
                             MutableHandleSavedFrame adoptedStack, uint32_t maxFrameCount)
 {
--- a/js/src/vm/Stack.cpp
+++ b/js/src/vm/Stack.cpp
@@ -260,17 +260,17 @@ InterpreterFrame::prologue(JSContext* cx
 
     return probes::EnterScript(cx, script, script->functionNonDelazifying(), this);
 }
 
 void
 InterpreterFrame::epilogue(JSContext* cx, jsbytecode* pc)
 {
     RootedScript script(cx, this->script());
-    probes::ExitScript(cx, script, script->functionNonDelazifying(), hasPushedSPSFrame());
+    probes::ExitScript(cx, script, script->functionNonDelazifying(), hasPushedGeckoProfilerFrame());
 
     // Check that the scope matches the environment at the point of leaving
     // the frame.
     AssertScopeMatchesEnvironment(this, pc);
 
     EnvironmentIter ei(cx, this, pc);
     UnwindAllEnvironmentsInFrame(cx, ei);
 
@@ -1723,18 +1723,18 @@ ActivationIterator::settle()
 
 JS::ProfilingFrameIterator::ProfilingFrameIterator(JSContext* cx, const RegisterState& state,
                                                    uint32_t sampleBufferGen)
   : rt_(cx),
     sampleBufferGen_(sampleBufferGen),
     activation_(nullptr),
     savedPrevJitTop_(nullptr)
 {
-    if (!cx->spsProfiler.enabled())
-        MOZ_CRASH("ProfilingFrameIterator called when spsProfiler not enabled for runtime.");
+    if (!cx->geckoProfiler.enabled())
+        MOZ_CRASH("ProfilingFrameIterator called when geckoProfiler not enabled for runtime.");
 
     if (!cx->profilingActivation())
         return;
 
     // If profiler sampling is not enabled, skip.
     if (!cx->isProfilerSamplingEnabled())
         return;
 
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -36,17 +36,17 @@ class AutoEntryMonitor;
 
 namespace js {
 
 class InterpreterRegs;
 class CallObject;
 class FrameIter;
 class EnvironmentObject;
 class ScriptFrameIter;
-class SPSProfiler;
+class GeckoProfiler;
 class InterpreterFrame;
 class LexicalEnvironmentObject;
 class EnvironmentIter;
 class EnvironmentCoordinate;
 
 class SavedFrame;
 
 namespace jit {
@@ -312,18 +312,18 @@ class InterpreterFrame
         PREV_UP_TO_DATE        =       0x20,  /* see DebugScopes::updateLiveScopes */
 
         /*
          * See comment above 'isDebuggee' in jscompartment.h for explanation of
          * invariants of debuggee compartments, scripts, and frames.
          */
         DEBUGGEE               =       0x40,  /* Execution is being observed by Debugger */
 
-        /* Used in tracking calls and profiling (see vm/SPSProfiler.cpp) */
-        HAS_PUSHED_SPS_FRAME   =       0x80,  /* SPS was notified of entry */
+        /* Used in tracking calls and profiling (see vm/GeckoProfiler.cpp) */
+        HAS_PUSHED_PROF_FRAME  =       0x80,  /* Gecko Profiler was notified of entry */
 
         /*
          * If set, we entered one of the JITs and ScriptFrameIter should skip
          * this frame.
          */
         RUNNING_IN_JIT         =      0x100,
 
         /* Miscellaneous state. */
@@ -661,26 +661,26 @@ class InterpreterFrame
             unsigned pushedArgs = Max(numFormalArgs(), numActualArgs());
             return argv()[pushedArgs];
         }
         return UndefinedValue();
     }
 
     /* Profiler flags */
 
-    bool hasPushedSPSFrame() {
-        return !!(flags_ & HAS_PUSHED_SPS_FRAME);
+    bool hasPushedGeckoProfilerFrame() {
+        return !!(flags_ & HAS_PUSHED_PROF_FRAME);
     }
 
-    void setPushedSPSFrame() {
-        flags_ |= HAS_PUSHED_SPS_FRAME;
+    void setPushedGeckoProfilerFrame() {
+        flags_ |= HAS_PUSHED_PROF_FRAME;
     }
 
-    void unsetPushedSPSFrame() {
-        flags_ &= ~HAS_PUSHED_SPS_FRAME;
+    void unsetPushedGeckoProfilerFrame() {
+        flags_ &= ~HAS_PUSHED_PROF_FRAME;
     }
 
     /* Return value */
 
     bool hasReturnValue() const {
         return flags_ & HAS_RVAL;
     }
 
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -12,17 +12,17 @@
 #include "mozilla/RangedPtr.h"
 #include "mozilla/SizePrintfMacros.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Unused.h"
 
 #include "gc/Marking.h"
 #include "js/GCAPI.h"
 #include "js/UbiNode.h"
-#include "vm/SPSProfiler.h"
+#include "vm/GeckoProfiler.h"
 
 #include "jscntxtinlines.h"
 #include "jscompartmentinlines.h"
 
 using namespace js;
 
 using mozilla::IsSame;
 using mozilla::PodCopy;
@@ -575,19 +575,19 @@ JSRope::flattenInternal(ExclusiveContext
     if (hasTwoByteChars())
         return flattenInternal<b, char16_t>(maybecx);
     return flattenInternal<b, Latin1Char>(maybecx);
 }
 
 JSFlatString*
 JSRope::flatten(ExclusiveContext* maybecx)
 {
-    mozilla::Maybe<AutoSPSEntry> sps;
+    mozilla::Maybe<AutoGeckoProfilerEntry> entry;
     if (maybecx && maybecx->isJSContext())
-        sps.emplace(maybecx->asJSContext()->runtime(), "JSRope::flatten");
+        entry.emplace(maybecx->asJSContext()->runtime(), "JSRope::flatten");
 
     if (zone()->needsIncrementalBarrier())
         return flattenInternal<WithIncrementalBarrier>(maybecx);
     return flattenInternal<NoBarrier>(maybecx);
 }
 
 template <AllowGC allowGC>
 static JSLinearString*
--- a/js/src/wasm/AsmJS.cpp
+++ b/js/src/wasm/AsmJS.cpp
@@ -29,16 +29,17 @@
 #include "jsutil.h"
 
 #include "jswrapper.h"
 
 #include "builtin/SIMD.h"
 #include "frontend/Parser.h"
 #include "gc/Policy.h"
 #include "js/MemoryMetrics.h"
+#include "vm/SelfHosting.h"
 #include "vm/StringBuffer.h"
 #include "vm/Time.h"
 #include "vm/TypedArrayObject.h"
 #include "wasm/WasmCompile.h"
 #include "wasm/WasmGenerator.h"
 #include "wasm/WasmInstance.h"
 #include "wasm/WasmJS.h"
 #include "wasm/WasmSerialize.h"
@@ -7445,32 +7446,46 @@ static bool
 GetDataProperty(JSContext* cx, HandleValue objVal, ImmutablePropertyNamePtr field, MutableHandleValue v)
 {
     // Help the conversion along for all the cx->names().* users.
     HandlePropertyName fieldHandle = field;
     return GetDataProperty(cx, objVal, fieldHandle, v);
 }
 
 static bool
+HasObjectValueOfMethodPure(JSObject* obj, JSContext* cx)
+{
+    Value v;
+    if (!GetPropertyPure(cx, obj, NameToId(cx->names().valueOf), &v))
+        return false;
+
+    JSFunction* fun;
+    if (!IsFunctionObject(v, &fun))
+        return false;
+
+    return IsSelfHostedFunctionWithName(fun, cx->names().Object_valueOf);
+}
+
+static bool
 HasPureCoercion(JSContext* cx, HandleValue v)
 {
     // Unsigned SIMD types are not allowed in function signatures.
     if (IsVectorObject<Int32x4>(v) || IsVectorObject<Float32x4>(v) || IsVectorObject<Bool32x4>(v))
         return true;
 
     // Ideally, we'd reject all non-SIMD non-primitives, but Emscripten has a
     // bug that generates code that passes functions for some imports. To avoid
     // breaking all the code that contains this bug, we make an exception for
     // functions that don't have user-defined valueOf or toString, for their
     // coercions are not observable and coercion via ToNumber/ToInt32
     // definitely produces NaN/0. We should remove this special case later once
     // most apps have been built with newer Emscripten.
     if (v.toObject().is<JSFunction>() &&
         HasNoToPrimitiveMethodPure(&v.toObject(), cx) &&
-        HasNativeMethodPure(&v.toObject(), cx->names().valueOf, obj_valueOf, cx) &&
+        HasObjectValueOfMethodPure(&v.toObject(), cx) &&
         HasNativeMethodPure(&v.toObject(), cx->names().toString, fun_toString, cx))
     {
         return true;
     }
 
     return false;
 }
 
--- a/js/src/wasm/WasmCompartment.cpp
+++ b/js/src/wasm/WasmCompartment.cpp
@@ -137,17 +137,17 @@ Compartment::lookupInstanceDeprecated(co
         return nullptr;
 
     return instances_[index];
 }
 
 bool
 Compartment::ensureProfilingState(JSContext* cx)
 {
-    bool newProfilingEnabled = cx->spsProfiler.enabled();
+    bool newProfilingEnabled = cx->geckoProfiler.enabled();
     if (profilingEnabled_ == newProfilingEnabled)
         return true;
 
     // Since one Instance can call another Instance in the same compartment
     // directly without calling through Instance::callExport(), when profiling
     // is enabled, enable it for the entire compartment at once. It is only safe
     // to enable profiling when the wasm is not on the stack, so delay enabling
     // profiling until there are no live WasmActivations in this compartment.
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -38,16 +38,17 @@
 #include "mozilla/StyleSetHandle.h"
 #include "mozilla/StyleSetHandleInlines.h"
 #include "nsViewManager.h"
 #include "nsStyleConsts.h"
 #include "nsIDOMXULElement.h"
 #include "nsContainerFrame.h"
 #include "nsNameSpaceManager.h"
 #include "nsIComboboxControlFrame.h"
+#include "nsComboboxControlFrame.h"
 #include "nsIListControlFrame.h"
 #include "nsIDOMCharacterData.h"
 #include "nsPlaceholderFrame.h"
 #include "nsTableRowGroupFrame.h"
 #include "nsIFormControl.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsTextFragment.h"
 #include "nsIAnonymousContentCreator.h"
@@ -4119,36 +4120,36 @@ nsCSSFrameConstructor::CreateAnonymousFr
                                                            aPendingBinding);
   TreeMatchContext::AutoAncestorPusher ancestorPusher(aState.mTreeMatchContext);
   if (aState.mTreeMatchContext.mAncestorFilter.HasFilter()) {
     ancestorPusher.PushAncestorAndStyleScope(aParent->AsElement());
   } else {
     ancestorPusher.PushStyleScope(aParent->AsElement());
   }
 
-  nsIAnonymousContentCreator* creator = do_QueryFrame(aParentFrame);
-  NS_ASSERTION(creator,
-               "How can that happen if we have nodes to construct frames for?");
-
+  nsComboboxControlFrame* comboboxFrame = do_QueryFrame(aParentFrame);
   InsertionPoint insertion(aParentFrame, aParent);
   for (uint32_t i=0; i < count; i++) {
     nsIContent* content = newAnonymousItems[i].mContent;
     NS_ASSERTION(content, "null anonymous content?");
     NS_ASSERTION(!newAnonymousItems[i].mStyleContext, "Unexpected style context");
     NS_ASSERTION(newAnonymousItems[i].mChildren.IsEmpty(),
                  "This method is not currently used with frames that implement "
                  "nsIAnonymousContentCreator::CreateAnonymousContent to "
                  "output a list where the items have their own children");
 
-    nsIFrame* newFrame = creator->CreateFrameFor(content);
-    if (newFrame) {
-      NS_ASSERTION(content->GetPrimaryFrame(),
-                   "Content must have a primary frame now");
-      newFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
-      aChildItems.AddChild(newFrame);
+    if (comboboxFrame && comboboxFrame->GetDisplayNode() == content) {
+      // Combo box frames have a custom hook to create frames for the anonymous
+      // text node. This is the last vestigial trace of an old custom hook that
+      // allowed arbitrary custom frame creation by any nsIAnonymousContentCreator
+      // implementation. It's possible that this could all be refactored away.
+      nsIFrame* customFrame = comboboxFrame->CreateFrameForDisplayNode();
+      MOZ_ASSERT(customFrame);
+      customFrame->AddStateBits(NS_FRAME_ANONYMOUSCONTENTCREATOR_CONTENT);
+      aChildItems.AddChild(customFrame);
     } else {
       FrameConstructionItemList items;
       {
         // Skip parent display based style-fixup during our
         // AddFrameConstructionItems() call:
         TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper
           parentDisplayBasedStyleFixupSkipper(aState.mTreeMatchContext);
 
@@ -10701,23 +10702,16 @@ nsCSSFrameConstructor::AddFCItemsForAnon
             nsFrameConstructorState& aState,
             nsContainerFrame* aFrame,
             nsTArray<nsIAnonymousContentCreator::ContentInfo>& aAnonymousItems,
             FrameConstructionItemList& aItemsToConstruct,
             uint32_t aExtraFlags)
 {
   for (uint32_t i = 0; i < aAnonymousItems.Length(); ++i) {
     nsIContent* content = aAnonymousItems[i].mContent;
-#ifdef DEBUG
-    nsIAnonymousContentCreator* creator = do_QueryFrame(aFrame);
-    NS_ASSERTION(!creator || !creator->CreateFrameFor(content),
-                 "If you need to use CreateFrameFor, you need to call "
-                 "CreateAnonymousFrames manually and not follow the standard "
-                 "ProcessChildren() codepath for this frame");
-#endif
     // Gecko-styled nodes should have no pending restyle flags.
     MOZ_ASSERT_IF(!content->IsStyledByServo(),
                   !content->IsElement() ||
                   !(content->GetFlags() & ELEMENT_ALL_RESTYLE_FLAGS));
     // Assert some things about this content
     MOZ_ASSERT(!(content->GetFlags() &
                  (NODE_DESCENDANTS_NEED_FRAMES | NODE_NEEDS_FRAME)),
                "Should not be marked as needing frames");
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6560,18 +6560,19 @@ nsLayoutUtils::DrawSingleImage(gfxContex
                                const SVGImageContext* aSVGContext,
                                uint32_t               aImageFlags,
                                const nsPoint*         aAnchorPoint,
                                const nsRect*          aSourceArea)
 {
   nscoord appUnitsPerCSSPixel = nsDeviceContext::AppUnitsPerCSSPixel();
   CSSIntSize pixelImageSize(ComputeSizeForDrawingWithFallback(aImage, aDest.Size()));
   if (pixelImageSize.width < 1 || pixelImageSize.height < 1) {
-    NS_WARNING("Image width or height is non-positive");
-    return DrawResult::TEMPORARY_ERROR;
+    NS_ASSERTION(pixelImageSize.width >= 0 && pixelImageSize.height >= 0,
+                 "Image width or height is negative");
+    return DrawResult::SUCCESS;  // no point in drawing a zero size image
   }
 
   nsSize imageSize(CSSPixel::ToAppUnits(pixelImageSize));
   nsRect source;
   nsCOMPtr<imgIContainer> image;
   if (aSourceArea) {
     source = *aSourceArea;
     nsIntRect subRect(source.x, source.y, source.width, source.height);
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -45,17 +45,20 @@
 #include "nsTreeSanitizer.h"
 #include "nsCellMap.h"
 #include "nsTextFrame.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsTextFragment.h"
 #include "nsCSSRuleProcessor.h"
 #include "nsCORSListenerProxy.h"
 #include "nsHTMLDNSPrefetch.h"
+#include "nsHtml5Atoms.h"
 #include "nsHtml5Module.h"
+#include "nsHTMLTags.h"
+#include "nsIRDFContentSink.h"	// for RDF atom initialization
 #include "mozilla/dom/FallbackEncoding.h"
 #include "nsFocusManager.h"
 #include "nsListControlFrame.h"
 #include "mozilla/dom/HTMLInputElement.h"
 #include "SVGElementFactory.h"
 #include "nsSVGUtils.h"
 #include "nsMathMLAtoms.h"
 #include "nsMathMLOperators.h"
@@ -154,16 +157,22 @@ nsLayoutStatics::Initialize()
   // Register all of our atoms once
   nsCSSAnonBoxes::AddRefAtoms();
   nsCSSPseudoClasses::AddRefAtoms();
   nsCSSPseudoElements::AddRefAtoms();
   nsCSSKeywords::AddRefTable();
   nsCSSProps::AddRefTable();
   nsColorNames::AddRefTable();
   nsGkAtoms::AddRefAtoms();
+  nsHtml5Atoms::AddRefAtoms();
+  nsTextServicesDocument::RegisterAtoms();
+  nsHTMLTags::RegisterAtoms();
+  nsRDFAtoms::RegisterAtoms();
+
+  NS_SealStaticAtomTable();
 
   StartupJSEnvironment();
   rv = nsRegion::InitStatic();
   if (NS_FAILED(rv)) {
     NS_ERROR("Could not initialize nsRegion");
     return rv;
   }
 
@@ -206,18 +215,16 @@ nsLayoutStatics::Initialize()
     NS_ERROR("Could not initialize nsXULContentUtils");
     return rv;
   }
 
 #endif
 
   nsMathMLOperators::AddRefTable();
 
-  nsTextServicesDocument::RegisterAtoms();
-
 #ifdef DEBUG
   nsFrame::DisplayReflowStartup();
 #endif
   Attr::Initialize();
 
   rv = txMozillaXSLTProcessor::Startup();
   if (NS_FAILED(rv)) {
     NS_ERROR("Could not initialize txMozillaXSLTProcessor");
@@ -262,18 +269,16 @@ nsLayoutStatics::Initialize()
   mozilla::dom::FallbackEncoding::Initialize();
   nsLayoutUtils::Initialize();
   nsIPresShell::InitializeStatics();
   TouchManager::InitializeStatics();
   nsPrincipal::InitializeStatics();
 
   nsCORSListenerProxy::Startup();
 
-  NS_SealStaticAtomTable();
-
   nsWindowMemoryReporter::Init();
 
   SVGElementFactory::Init();
   nsSVGUtils::Init();
 
   ProcessPriorityManager::Init();
 
   nsPermissionManager::ClearOriginDataObserverInit();
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -244,16 +244,17 @@ nsComboboxControlFrame::nsComboboxContro
 nsComboboxControlFrame::~nsComboboxControlFrame()
 {
   REFLOW_COUNTER_DUMP("nsCCF");
 }
 
 //--------------------------------------------------------------
 
 NS_QUERYFRAME_HEAD(nsComboboxControlFrame)
+  NS_QUERYFRAME_ENTRY(nsComboboxControlFrame)
   NS_QUERYFRAME_ENTRY(nsIComboboxControlFrame)
   NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
   NS_QUERYFRAME_ENTRY(nsISelectControlFrame)
   NS_QUERYFRAME_ENTRY(nsIStatefulFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
 
 #ifdef ACCESSIBILITY
@@ -1342,26 +1343,19 @@ nsComboboxDisplayFrame::BuildDisplayList
   if (mComboBox->IsThemed()) {
     set.BorderBackground()->DeleteAll();
   }
 
   set.MoveTo(aLists);
 }
 
 nsIFrame*
-nsComboboxControlFrame::CreateFrameFor(nsIContent*      aContent)
+nsComboboxControlFrame::CreateFrameForDisplayNode()
 {
-  NS_PRECONDITION(nullptr != aContent, "null ptr");
-
-  NS_ASSERTION(mDisplayContent, "mDisplayContent can't be null!");
-
-  if (mDisplayContent != aContent) {
-    // We only handle the frames for mDisplayContent here
-    return nullptr;
-  }
+  MOZ_ASSERT(mDisplayContent);
 
   // Get PresShell
   nsIPresShell *shell = PresContext()->PresShell();
   StyleSetHandle styleSet = shell->StyleSet();
 
   // create the style contexts for the anonymous block frame and text frame
   RefPtr<nsStyleContext> styleContext;
   styleContext = styleSet->
@@ -1376,17 +1370,17 @@ nsComboboxControlFrame::CreateFrameFor(n
   // Start by creating our anonymous block frame
   mDisplayFrame = new (shell) nsComboboxDisplayFrame(styleContext, this);
   mDisplayFrame->Init(mContent, this, nullptr);
 
   // Create a text frame and put it inside the block frame
   nsIFrame* textFrame = NS_NewTextFrame(shell, textStyleContext);
 
   // initialize the text frame
-  textFrame->Init(aContent, mDisplayFrame, nullptr);
+  textFrame->Init(mDisplayContent, mDisplayFrame, nullptr);
   mDisplayContent->SetPrimaryFrame(textFrame);
 
   nsFrameList textList(textFrame, textFrame);
   mDisplayFrame->SetInitialChildList(kPrincipalList, textList);
   return mDisplayFrame;
 }
 
 void
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -49,32 +49,35 @@ class nsComboboxControlFrame final : pub
                                      public nsIAnonymousContentCreator,
                                      public nsISelectControlFrame,
                                      public nsIRollupListener,
                                      public nsIStatefulFrame
 {
   typedef mozilla::gfx::DrawTarget DrawTarget;
 
 public:
+  NS_DECL_QUERYFRAME_TARGET(nsComboboxControlFrame)
   friend nsContainerFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell,
                                                       nsStyleContext* aContext,
                                                       nsFrameState aFlags);
   friend class nsComboboxDisplayFrame;
 
   explicit nsComboboxControlFrame(nsStyleContext* aContext);
   ~nsComboboxControlFrame();
 
   NS_DECL_QUERYFRAME
   NS_DECL_FRAMEARENA_HELPERS
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
   virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
                                         uint32_t aFilter) override;
-  virtual nsIFrame* CreateFrameFor(nsIContent* aContent) override;
+
+  nsIContent* GetDisplayNode() { return mDisplayContent; }
+  nsIFrame* CreateFrameForDisplayNode();
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
   virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
 
   virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
--- a/layout/forms/nsGfxButtonControlFrame.cpp
+++ b/layout/forms/nsGfxButtonControlFrame.cpp
@@ -73,40 +73,16 @@ void
 nsGfxButtonControlFrame::AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
                                                   uint32_t aFilter)
 {
   if (mTextContent) {
     aElements.AppendElement(mTextContent);
   }
 }
 
-// Create the text content used as label for the button.
-// The frame will be generated by the frame constructor.
-nsIFrame*
-nsGfxButtonControlFrame::CreateFrameFor(nsIContent*      aContent)
-{
-  nsIFrame * newFrame = nullptr;
-
-  if (aContent == mTextContent) {
-    nsContainerFrame* parentFrame = do_QueryFrame(mFrames.FirstChild());
-
-    nsPresContext* presContext = PresContext();
-    RefPtr<nsStyleContext> textStyleContext;
-    textStyleContext = presContext->StyleSet()->
-      ResolveStyleForText(mTextContent, mStyleContext);
-
-    newFrame = NS_NewTextFrame(presContext->PresShell(), textStyleContext);
-    // initialize the text frame
-    newFrame->Init(mTextContent, parentFrame, nullptr);
-    mTextContent->SetPrimaryFrame(newFrame);
-  }
-
-  return newFrame;
-}
-
 NS_QUERYFRAME_HEAD(nsGfxButtonControlFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsHTMLButtonControlFrame)
 
 // Initially we hardcoded the default strings here.
 // Next, we used html.css to store the default label for various types
 // of buttons. (nsGfxButtonControlFrame::DoNavQuirksReflow rev 1.20)
 // However, since html.css is not internationalized, we now grab the default
--- a/layout/forms/nsGfxButtonControlFrame.h
+++ b/layout/forms/nsGfxButtonControlFrame.h
@@ -37,17 +37,16 @@ public:
 #endif
 
   NS_DECL_QUERYFRAME
 
   // nsIAnonymousContentCreator
   virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
   virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
                                         uint32_t aFilter) override;
-  virtual nsIFrame* CreateFrameFor(nsIContent* aContent) override;
 
   virtual nsresult AttributeChanged(int32_t         aNameSpaceID,
                                     nsIAtom*        aAttribute,
                                     int32_t         aModType) override;
 
   virtual bool IsLeaf() const override;
 
   virtual nsContainerFrame* GetContentInsertionFrame() override;
--- a/layout/generic/nsIAnonymousContentCreator.h
+++ b/layout/generic/nsIAnonymousContentCreator.h
@@ -67,20 +67,12 @@ public:
    * to the given content list depending on the filter.
    *
    * @see nsIContent::GetChildren for set of values used for filter.  Currently,
    *   eSkipPlaceholderContent is the only flag that any implementation of
    *   this method heeds.
    */
   virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
                                         uint32_t aFilter) = 0;
-
-  /**
-   * Implementations can override this method to create special frames for the
-   * anonymous content returned from CreateAnonymousContent.
-   * By default this method returns nullptr, which means the default frame
-   * is created.
-   */
-  virtual nsIFrame* CreateFrameFor(nsIContent* aContent) { return nullptr; }
 };
 
 #endif
 
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1619,25 +1619,25 @@ fuzzy-if(Android,8,20) == 602200-3.html 
 == 605138-1.html 605138-1-ref.html
 == 605157-1.xhtml 605157-1-ref.xhtml
 == 607267-1.html 607267-1-ref.html
 == 608636-1.html 608636-1-ref.html
 == 608756-1a.html 608756-1-ref.html
 == 608756-1b.html 608756-1-ref.html
 == 608756-2.html 608756-2-ref.html
 fuzzy-if(Android,4,196) == 609272-1.html 609272-1-ref.html
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-1.html 613433-1-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-1.html 613433-2-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-1.html 613433-3-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-2.html 613433-1-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-2.html 613433-2-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-2.html 613433-3-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-3.html 613433-1-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-3.html 613433-2-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
-needs-focus skip-if(/^Linux\x20i686/.test(http.oscpu)) == 613433-3.html 613433-3-ref.html # bug 1292460 - doesn't get the focus it needs if it's first in a chunk
+needs-focus == 613433-1.html 613433-1-ref.html
+needs-focus == 613433-1.html 613433-2-ref.html
+needs-focus == 613433-1.html 613433-3-ref.html
+needs-focus == 613433-2.html 613433-1-ref.html
+needs-focus == 613433-2.html 613433-2-ref.html
+needs-focus == 613433-2.html 613433-3-ref.html
+needs-focus == 613433-3.html 613433-1-ref.html
+needs-focus == 613433-3.html 613433-2-ref.html
+needs-focus == 613433-3.html 613433-3-ref.html
 == 614272-1.svg  614272-1-ref.svg
 HTTP(..) == 615121-1.html 615121-1-ref.html
 HTTP(..) != 615121-2.html 615121-2-notref.html
 == 617242-1.html 617242-1-ref.html
 != 618071.html 618071-notref.html
 == 619117-1.html 619117-1-ref.html
 HTTP(..) == 619511-1.html 619511-1-ref.html
 skip-if(Android) HTTP(..) == 621253-1-externalFilter.html 621253-1-ref.html
--- a/layout/reftests/layers/reftest.list
+++ b/layout/reftests/layers/reftest.list
@@ -17,8 +17,17 @@ skip-if(!asyncPan) != pull-background-di
 skip-if(!asyncPan) != pull-background-displayport-3.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
 skip-if(!asyncPan) != pull-background-displayport-4.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
 skip-if(!asyncPan) != pull-background-displayport-5.html about:blank
 skip-if(!asyncPan) != pull-background-displayport-6.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
 fuzzy(2,30150) == opacity-blending.html opacity-blending-ref.html
 fuzzy(16,5) == mask-layer-transform.html mask-layer-transform-ref.html
 fuzzy-if(gtkWidget,1,17) == forced-bg-color-outside-visible-region.html forced-bg-color-outside-visible-region-ref.html
 != layerize-over-fixed-bg-1.html about:blank
+
+# These tests check whether the GPU process is working. We expect it to work if:
+#   E10S is enabled, and
+#   Direct2D 1.1 works (as a proxy for Windows 7 SP1 + Platform Update or higher), OR
+#   The GPU process has been forced on.
+# If these conditions are met, but the GPU process is not on, these tests will turn on
+# and compare false.
+skip-if(!browserIsRemote||!d2d||gpuProcess) == data:text/plain,FAIL about:blank
+skip-if(!gpuProcessForceEnabled||gpuProcess) == data:text/plain,FAIL about:blank
--- a/layout/tools/reftest/reftest.jsm
+++ b/layout/tools/reftest/reftest.jsm
@@ -426,20 +426,21 @@ function InitAndStartRefTests()
         //gBrowser.loadURI('data:text/plain,' + ex);
         ++gTestResults.Exception;
         logger.error("EXCEPTION: " + ex);
         DoneTests();
     }
 
     // Focus the content browser.
     if (gFocusFilterMode != FOCUS_FILTER_NON_NEEDS_FOCUS_TESTS) {
+        gBrowser.addEventListener("focus", StartTests, true);
         gBrowser.focus();
+    } else {
+        StartTests();
     }
-
-    StartTests();
 }
 
 function StartHTTPServer()
 {
     gServer.registerContentType("sjs", "sjs");
     gServer.start(-1);
     gHttpServerPort = gServer.identity.primaryPort;
 }
@@ -452,16 +453,20 @@ function Shuffle(array)
         var temp = array[i];
         array[i] = array[j];
         array[j] = temp;
     }
 }
 
 function StartTests()
 {
+    if (gFocusFilterMode != FOCUS_FILTER_NON_NEEDS_FOCUS_TESTS) {
+        gBrowser.removeEventListener("focus", StartTests, true);
+    }
+
     var manifests;
     /* These prefs are optional, so we don't need to spit an error to the log */
     try {
         var prefs = Components.classes["@mozilla.org/preferences-service;1"].
                     getService(Components.interfaces.nsIPrefBranch);
     } catch(e) {
         logger.error("EXCEPTION: " + e);
     }
@@ -741,16 +746,21 @@ function BuildConditionSandbox(aURL) {
 
     var prefs = CC["@mozilla.org/preferences-service;1"].
                 getService(CI.nsIPrefBranch);
     try {
         sandbox.nativeThemePref = !prefs.getBoolPref("mozilla.widget.disable-native-theme");
     } catch (e) {
         sandbox.nativeThemePref = true;
     }
+    try {
+        sandbox.gpuProcessForceEnabled = prefs.getBoolPref("layers.gpu-process.force-enabled");
+    } catch (e) {
+        sandbox.gpuProcessForceEnabled = false;
+    }
 
     sandbox.prefs = CU.cloneInto({
         getBoolPref: function(p) { return prefs.getBoolPref(p); },
         getIntPref:  function(p) { return prefs.getIntPref(p); }
     }, sandbox, { cloneFunctions: true });
 
     // Tests shouldn't care about this except for when they need to
     // crash the content process
--- a/parser/html/nsHtml5Module.cpp
+++ b/parser/html/nsHtml5Module.cpp
@@ -25,17 +25,16 @@ bool nsHtml5Module::sOffMainThread = tru
 nsIThread* nsHtml5Module::sStreamParserThread = nullptr;
 nsIThread* nsHtml5Module::sMainThread = nullptr;
 
 // static
 void
 nsHtml5Module::InitializeStatics()
 {
   Preferences::AddBoolVarCache(&sOffMainThread, "html5.offmainthread");
-  nsHtml5Atoms::AddRefAtoms();
   nsHtml5AttributeName::initializeStatics();
   nsHtml5ElementName::initializeStatics();
   nsHtml5HtmlAttributes::initializeStatics();
   nsHtml5NamedCharacters::initializeStatics();
   nsHtml5Portability::initializeStatics();
   nsHtml5StackNode::initializeStatics();
   nsHtml5Tokenizer::initializeStatics();
   nsHtml5TreeBuilder::initializeStatics();
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -1332,17 +1332,17 @@ nsHtml5StreamParser::FlushTreeOpsAndDisa
     mFlushTimerArmed = false;
   }
   if (mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML) {
     mTokenizer->FlushViewSource();
   }
   mTreeBuilder->Flush();
   nsCOMPtr<nsIRunnable> runnable(mExecutorFlusher);
   if (NS_FAILED(mExecutor->GetDocument()->Dispatch("nsHtml5ExecutorFlusher",
-                                                   dom::TaskCategory::Other,
+                                                   TaskCategory::Other,
                                                    runnable.forget()))) {
     NS_WARNING("failed to dispatch executor flush event");
   }
 }
 
 void
 nsHtml5StreamParser::ParseAvailableData()
 {
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -261,17 +261,17 @@ FlushTimerCallback(nsITimer* aTimer, voi
 }
 
 void
 nsHtml5TreeOpExecutor::ContinueInterruptedParsingAsync()
 {
   if (!mDocument || !mDocument->IsInBackgroundWindow()) {
     nsCOMPtr<nsIRunnable> flusher = new nsHtml5ExecutorReflusher(this);  
     if (NS_FAILED(mDocument->Dispatch("nsHtml5ExecutorReflusher",
-                                      dom::TaskCategory::Other,
+                                      TaskCategory::Other,
                                       flusher.forget()))) {
       NS_WARNING("failed to dispatch executor flush event");
     }
   } else {
     if (!gBackgroundFlushList) {
       gBackgroundFlushList = new mozilla::LinkedList<nsHtml5TreeOpExecutor>();
     }
     if (!isInList()) {
--- a/parser/htmlparser/nsHTMLTags.cpp
+++ b/parser/htmlparser/nsHTMLTags.cpp
@@ -51,41 +51,74 @@ HTMLTagsKeyCompareUCPtr(const void *key1
 static PLHashNumber
 HTMLTagsHashCodeAtom(const void *key)
 {
   return NS_PTR_TO_INT32(key) >> 2;
 }
 
 #define NS_HTMLTAG_NAME_MAX_LENGTH 10
 
+// static
+void
+nsHTMLTags::RegisterAtoms(void)
+{
 #define HTML_TAG(_tag, _classname, _interfacename) NS_STATIC_ATOM_BUFFER(Atombuffer_##_tag, #_tag)
 #define HTML_OTHER(_tag)
 #include "nsHTMLTagList.h"
 #undef HTML_TAG
 #undef HTML_OTHER
 
-
-// static
-nsresult
-nsHTMLTags::AddRefTable(void)
-{
-  // static array of tag StaticAtom structs
+// static array of tag StaticAtom structs
 #define HTML_TAG(_tag, _classname, _interfacename) NS_STATIC_ATOM(Atombuffer_##_tag, &nsHTMLTags::sTagAtomTable[eHTMLTag_##_tag - 1]),
 #define HTML_OTHER(_tag)
   static const nsStaticAtom sTagAtoms_info[] = {
 #include "nsHTMLTagList.h"
   };
 #undef HTML_TAG
 #undef HTML_OTHER
 
-  if (gTableRefCount++ == 0) {
-    // Fill in our static atom pointers
-    NS_RegisterStaticAtoms(sTagAtoms_info);
+  // Fill in our static atom pointers
+  NS_RegisterStaticAtoms(sTagAtoms_info);
 
 
+#if defined(DEBUG)
+  {
+    // let's verify that all names in the the table are lowercase...
+    for (int32_t i = 0; i &