Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 19 Feb 2014 15:37:55 -0500
changeset 169943 918802901b62670754197c4c6895359dd04af012
parent 169942 8497ffecbacd85e047c8a8d0e525844f5f1c9594 (current diff)
parent 169902 995cfd42e045b89fd6c1e4f7b5a5b7119bc6f648 (diff)
child 169944 3762e1037b596a3f6f36bf42144aae70482f1ecf
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
Merge inbound to m-c.
media/webrtc/signaling/src/sipcc/cpr/android/cpr_android_ipc.c
media/webrtc/signaling/src/sipcc/cpr/android/cpr_android_ipc.h
media/webrtc/signaling/src/sipcc/cpr/darwin/cpr_darwin_ipc.c
media/webrtc/signaling/src/sipcc/cpr/darwin/cpr_darwin_ipc.h
media/webrtc/signaling/src/sipcc/cpr/linux/cpr_linux_ipc.c
media/webrtc/signaling/src/sipcc/cpr/linux/cpr_linux_ipc.h
media/webrtc/signaling/src/sipcc/cpr/win32/cpr_win_ipc.c
media/webrtc/signaling/src/sipcc/cpr/win32/cpr_win_ipc.h
profile/dirserviceprovider/src/objs.mozbuild
profile/dirserviceprovider/standalone/Makefile.in
profile/dirserviceprovider/standalone/moz.build
--- a/addon-sdk/source/lib/toolkit/loader.js
+++ b/addon-sdk/source/lib/toolkit/loader.js
@@ -132,35 +132,39 @@ exports.sourceURI = iced(sourceURI);
 function isntLoaderFrame(frame) { return frame.fileName !== module.uri }
 
 var parseStack = iced(function parseStack(stack) {
   let lines = String(stack).split("\n");
   return lines.reduce(function(frames, line) {
     if (line) {
       let atIndex = line.indexOf("@");
       let columnIndex = line.lastIndexOf(":");
-      let fileName = sourceURI(line.slice(atIndex + 1, columnIndex));
-      let lineNumber = parseInt(line.slice(columnIndex + 1));
+      let lineIndex = line.lastIndexOf(":", columnIndex - 1);
+      let fileName = sourceURI(line.slice(atIndex + 1, lineIndex));
+      let lineNumber = parseInt(line.slice(lineIndex + 1, columnIndex));
+      let columnNumber = parseInt(line.slice(columnIndex + 1));
       let name = line.slice(0, atIndex).split("(").shift();
       frames.unshift({
         fileName: fileName,
         name: name,
-        lineNumber: lineNumber
+        lineNumber: lineNumber,
+        columnNumber: columnNumber
       });
     }
     return frames;
   }, []);
 })
 exports.parseStack = parseStack
 
 var serializeStack = iced(function serializeStack(frames) {
   return frames.reduce(function(stack, frame) {
     return frame.name + "@" +
            frame.fileName + ":" +
-           frame.lineNumber + "\n" +
+           frame.lineNumber + ":" +
+           frame.columnNumber + "\n" +
            stack;
   }, "");
 })
 exports.serializeStack = serializeStack
 
 function readURI(uri) {
   let stream = NetUtil.newChannel(uri, 'UTF-8', null).open();
   let count = stream.available();
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -679,17 +679,17 @@ var gPluginHandler = {
     gPluginHandler._showClickToPlayNotification(browser, null, false);
   },
 
   _clickToPlayNotificationEventCallback: function PH_ctpEventCallback(event) {
     if (event == "showing") {
       Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_SHOWN")
         .add(!this.options.primaryPlugin);
       // Histograms always start at 0, even though our data starts at 1
-      let histogramCount = this.options.centerActions.size - 1;
+      let histogramCount = this.options.pluginData.size - 1;
       if (histogramCount > 4) {
         histogramCount = 4;
       }
       Services.telemetry.getHistogramById("PLUGINS_NOTIFICATION_PLUGIN_COUNT")
         .add(histogramCount);
     }
     else if (event == "dismissed") {
       // Once the popup is dismissed, clicking the icon should show the full
@@ -839,34 +839,34 @@ var gPluginHandler = {
           PopupNotifications.remove(notification);
         }
         return;
       }
     } else {
       plugins = [aPlugin];
     }
 
-    // If this is a new notification, create a centerActions map, otherwise append
-    let centerActions;
+    // If this is a new notification, create a pluginData map, otherwise append
+    let pluginData;
     if (notification) {
-      centerActions = notification.options.centerActions;
+      pluginData = notification.options.pluginData;
     } else {
-      centerActions = new Map();
+      pluginData = new Map();
     }
 
     let principal = aBrowser.contentDocument.nodePrincipal;
     let principalHost = this._getHostFromPrincipal(principal);
 
     for (var plugin of plugins) {
       let pluginInfo = this._getPluginInfo(plugin);
       if (pluginInfo.permissionString === null) {
         Cu.reportError("No permission string for active plugin.");
         continue;
       }
-      if (centerActions.has(pluginInfo.permissionString)) {
+      if (pluginData.has(pluginInfo.permissionString)) {
         continue;
       }
 
       let permissionObj = Services.perms.
         getPermissionObject(principal, pluginInfo.permissionString, false);
       if (permissionObj) {
         pluginInfo.pluginPermissionHost = permissionObj.host;
         pluginInfo.pluginPermissionType = permissionObj.expireType;
@@ -883,18 +883,18 @@ var gPluginHandler = {
       }
       else if (pluginInfo.blocklistState != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
         url = Services.blocklist.getPluginBlocklistURL(pluginInfo.pluginTag);
       }
       else {
         url = Services.urlFormatter.formatURLPref("app.support.baseURL") + "clicktoplay";
       }
       pluginInfo.detailsLink = url;
-      
-      centerActions.set(pluginInfo.permissionString, pluginInfo);
+
+      pluginData.set(pluginInfo.permissionString, pluginInfo);
     }
 
     let primaryPluginPermission = null;
     if (aShowNow) {
       primaryPluginPermission = this._getPluginInfo(aPlugin).permissionString;
     }
 
     if (notification) {
@@ -907,17 +907,17 @@ var gPluginHandler = {
       }
       return;
     }
 
     let options = {
       dismissed: !aShowNow,
       eventCallback: this._clickToPlayNotificationEventCallback,
       primaryPlugin: primaryPluginPermission,
-      centerActions: centerActions
+      pluginData: pluginData
     };
     PopupNotifications.show(aBrowser, "click-to-play-plugins",
                             "", "plugins-notification-icon",
                             null, null, options);
     setTimeout(() => { this._setPluginNotificationIcon(aBrowser); }, 0);
   },
 
   _setPluginNotificationIcon : function PH_setPluginNotificationIcon(aBrowser) {
@@ -929,17 +929,17 @@ var gPluginHandler = {
     let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
     if (!notification)
       return;
 
     // Make a copy of the actions, removing active plugins and checking for
     // outdated plugins.
     let haveInsecure = false;
     let actions = new Map();
-    for (let action of notification.options.centerActions.values()) {
+    for (let action of notification.options.pluginData.values()) {
       switch (action.fallbackType) {
         // haveInsecure will trigger the red flashing icon and the infobar
         // styling below
         case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_UPDATABLE:
         case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
           haveInsecure = true;
           // fall through
 
--- a/browser/base/content/test/general/browser_CTP_data_urls.js
+++ b/browser/base/content/test/general/browser_CTP_data_urls.js
@@ -110,20 +110,20 @@ function test2a() {
 }
 
 function test2b() {
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 2b, Should have a click-to-play notification");
 
   // Simulate choosing "Allow now" for the test plugin
   notification.reshow();
-  is(notification.options.centerActions.size, 2, "Test 2b, Should have two types of plugin in the notification");
+  is(notification.options.pluginData.size, 2, "Test 2b, Should have two types of plugin in the notification");
 
   var centerAction = null;
-  for (var action of notification.options.centerActions.values()) {
+  for (var action of notification.options.pluginData.values()) {
     if (action.pluginName == "Test") {
       centerAction = action;
       break;
     }
   }
   ok(centerAction, "Test 2b, found center action for the Test plugin");
 
   var centerItem = null;
--- a/browser/base/content/test/general/browser_CTP_multi_allow.js
+++ b/browser/base/content/test/general/browser_CTP_multi_allow.js
@@ -71,17 +71,17 @@ function test1a() {
   let plugin = doc.getElementById("test");
   let objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(!objLoadingContent.activated, "Test1a, Plugin should not be activated");
 
   let notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 1a, Should have a click-to-play notification");
   notification.reshow();
 
-  is(notification.options.centerActions.size, 2,
+  is(notification.options.pluginData.size, 2,
      "Test 1a, Should have two types of plugin in the notification");
 
   let pluginItem = null;
   for (let item of PopupNotifications.panel.firstChild.childNodes) {
     is(item.value, "block", "Test 1a, all plugins should start out blocked");
     if (item.action.pluginName == "Test") {
       pluginItem = item;
     }
--- a/browser/base/content/test/general/browser_bug820497.js
+++ b/browser/base/content/test/general/browser_bug820497.js
@@ -35,25 +35,25 @@ function pluginBindingAttached() {
     var testplugin = doc.getElementById("test");
     ok(testplugin, "should have test plugin");
     var secondtestplugin = doc.getElementById("secondtest");
     ok(!secondtestplugin, "should not yet have second test plugin");
     var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
     ok(notification, "should have popup notification");
     // We don't set up the action list until the notification is shown
     notification.reshow();
-    is(notification.options.centerActions.size, 1, "should be 1 type of plugin in the popup notification");
+    is(notification.options.pluginData.size, 1, "should be 1 type of plugin in the popup notification");
     XPCNativeWrapper.unwrap(gTestBrowser.contentWindow).addSecondPlugin();
   } else if (gNumPluginBindingsAttached == 2) {
     var doc = gTestBrowser.contentDocument;
     var testplugin = doc.getElementById("test");
     ok(testplugin, "should have test plugin");
     var secondtestplugin = doc.getElementById("secondtest");
     ok(secondtestplugin, "should have second test plugin");
     var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
     ok(notification, "should have popup notification");
     notification.reshow();
-    is(notification.options.centerActions.size, 2, "should be 2 types of plugin in the popup notification");
+    is(notification.options.pluginData.size, 2, "should be 2 types of plugin in the popup notification");
     finish();
   } else {
     ok(false, "if we've gotten here, something is quite wrong");
   }
 }
--- a/browser/base/content/test/general/browser_pluginnotification.js
+++ b/browser/base/content/test/general/browser_pluginnotification.js
@@ -174,17 +174,17 @@ function prepareTest5() {
 function test5() {
   info("test5");
   ok(!PopupNotifications.getNotification("plugins-not-found", gTestBrowser), "Test 5, Should not have displayed the missing plugin notification");
   let notification = PopupNotifications.getNotification("click-to-play-plugins");
   ok(notification, "Test 5: There should be a plugin notification for blocked plugins");
   ok(notification.dismissed, "Test 5: The plugin notification should be dismissed by default");
 
   notification.reshow();
-  is(notification.options.centerActions.size, 1, "Test 5: Only the blocked plugin should be present in the notification");
+  is(notification.options.pluginData.size, 1, "Test 5: Only the blocked plugin should be present in the notification");
   ok(PopupNotifications.panel.firstChild._buttonContainer.hidden, "Part 5: The blocked plugins notification should not have any buttons visible.");
 
   ok(!gTestBrowser.missingPlugins, "Test 5, Should not be a missing plugin list");
   var pluginNode = gTestBrowser.contentDocument.getElementById("test");
   ok(pluginNode, "Test 5, Found plugin in page");
   var objLoadingContent = pluginNode.QueryInterface(Ci.nsIObjectLoadingContent);
   is(objLoadingContent.pluginFallbackType, Ci.nsIObjectLoadingContent.PLUGIN_BLOCKLISTED, "Test 5, plugin fallback type should be PLUGIN_BLOCKLISTED");
 
@@ -599,20 +599,20 @@ function test21a() {
     ok(rect.width == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
     ok(rect.height == 200, "Test 21a, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
     var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(!objLoadingContent.activated, "Test 21a, Plugin with id=" + plugin.id + " should not be activated");
   }
 
   // we have to actually show the panel to get the bindings to instantiate
   notification.reshow();
-  is(notification.options.centerActions.size, 2, "Test 21a, Should have two types of plugin in the notification");
+  is(notification.options.pluginData.size, 2, "Test 21a, Should have two types of plugin in the notification");
 
   var centerAction = null;
-  for (var action of notification.options.centerActions.values()) {
+  for (var action of notification.options.pluginData.values()) {
     if (action.pluginName == "Test") {
       centerAction = action;
       break;
     }
   }
   ok(centerAction, "Test 21b, found center action for the Test plugin");
 
   var centerItem = null;
@@ -636,17 +636,17 @@ function test21a() {
   waitForCondition(condition, test21c, "Test 21b, Waited too long for plugin to activate");
 }
 
 function test21c() {
   var notification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   ok(notification, "Test 21c, Should have a click-to-play notification");
 
   notification.reshow();
-  ok(notification.options.centerActions.size == 2, "Test 21c, Should have one type of plugin in the notification");
+  ok(notification.options.pluginData.size == 2, "Test 21c, Should have one type of plugin in the notification");
 
   var doc = gTestBrowser.contentDocument;
   var plugin = doc.getElementById("test");
   var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
   ok(rect.width == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px width after being clicked");
   ok(rect.height == 0, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 0px height after being clicked");
   var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
   ok(objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should be activated");
@@ -657,17 +657,17 @@ function test21c() {
     var rect = doc.getAnonymousElementByAttribute(plugin, "anonid", "main").getBoundingClientRect();
     ok(rect.width == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px width before being clicked");
     ok(rect.height == 200, "Test 21c, Plugin with id=" + plugin.id + " overlay rect should have 200px height before being clicked");
     var objLoadingContent = plugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(!objLoadingContent.activated, "Test 21c, Plugin with id=" + plugin.id + " should not be activated");
   }
 
   var centerAction = null;
-  for (var action of notification.options.centerActions.values()) {
+  for (var action of notification.options.pluginData.values()) {
     if (action.pluginName == "Second Test") {
       centerAction = action;
       break;
     }
   }
   ok(centerAction, "Test 21d, found center action for the Second Test plugin");
 
   var centerItem = null;
--- a/browser/base/content/test/general/browser_plugins_added_dynamically.js
+++ b/browser/base/content/test/general/browser_plugins_added_dynamically.js
@@ -63,17 +63,17 @@ function testActivateAddSameTypePart2() 
 
   popupNotification.reshow();
   testActivateAddSameTypePart3();
 }
 
 function testActivateAddSameTypePart3() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
   let centerAction = null;
-  for (let action of popupNotification.options.centerActions.values()) {
+  for (let action of popupNotification.options.pluginData.values()) {
     if (action.pluginName == "Test") {
       centerAction = action;
       break;
     }
   }
   ok(centerAction, "testActivateAddSameTypePart3: found center action for the Test plugin");
 
   let centerItem = null;
@@ -137,17 +137,17 @@ function testActivateAddDifferentTypePar
 
   // we have to actually show the panel to get the bindings to instantiate
   popupNotification.reshow();
   testActivateAddDifferentTypePart3();
 }
 
 function testActivateAddDifferentTypePart3() {
   let popupNotification = PopupNotifications.getNotification("click-to-play-plugins", gTestBrowser);
-  is(popupNotification.options.centerActions.size, 1, "Should be one plugin action");
+  is(popupNotification.options.pluginData.size, 1, "Should be one plugin action");
 
   let plugin = gTestBrowser.contentDocument.getElementsByTagName("embed")[0];
   ok(!plugin.activated, "testActivateAddDifferentTypePart3: plugin should not be activated");
 
   // "click" the button to activate the Test plugin
   PopupNotifications.panel.firstChild._primaryButton.click();
 
   let condition = function() plugin.activated;
--- a/browser/base/content/test/general/browser_tabopen_reflows.js
+++ b/browser/base/content/test/general/browser_tabopen_reflows.js
@@ -80,17 +80,17 @@ function test() {
     finish();
   });
 }
 
 let observer = {
   reflow: function (start, end) {
     // Gather information about the current code path.
     let path = (new Error().stack).split("\n").slice(1).map(line => {
-      return line.replace(/:\d+$/, "");
+      return line.replace(/:\d+:\d+$/, "");
     }).join("|");
     let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|");
 
     // Stack trace is empty. Reflow was triggered by native code.
     if (path === "") {
       return;
     }
 
--- a/browser/base/content/test/general/browser_windowopen_reflows.js
+++ b/browser/base/content/test/general/browser_windowopen_reflows.js
@@ -70,17 +70,17 @@ function test() {
   });
 }
 
 let observer = {
   reflow: function (start, end) {
     // Gather information about the current code path.
     let stack = new Error().stack;
     let path = stack.split("\n").slice(1).map(line => {
-      return line.replace(/:\d+$/, "");
+      return line.replace(/:\d+:\d+$/, "");
     }).join("|");
     let pathWithLineNumbers = (new Error().stack).split("\n").slice(1).join("|");
 
     // Stack trace is empty. Reflow was triggered by native code.
     if (path === "") {
       return;
     }
 
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1559,17 +1559,17 @@
       </field>
       <field name="_brandShortName">
         document.getElementById("bundle_brand").getString("brandShortName")
       </field>
       <field name="_items">[]</field>
       <constructor><![CDATA[
         const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
         let sortedActions = [];
-        for (let action of this.notification.options.centerActions.values()) {
+        for (let action of this.notification.options.pluginData.values()) {
           sortedActions.push(action);
         }
         sortedActions.sort((a, b) => a.pluginName.localeCompare(b.pluginName));
 
         for (let action of sortedActions) {
           let item = document.createElementNS(XUL_NS, "row");
           item.setAttribute("class", "plugin-popupnotification-centeritem");
           item.action = action;
--- a/browser/components/preferences/in-content/moz.build
+++ b/browser/components/preferences/in-content/moz.build
@@ -1,13 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+TEST_DIRS += ['tests']
+
 for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
     DEFINES[var] = CONFIG[var]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'cocoa'):
     DEFINES['HAVE_SHELL_SERVICE'] = 1
 
-JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
+JAR_MANIFESTS += ['jar.mn']
--- a/browser/components/preferences/in-content/tests/Makefile.in
+++ b/browser/components/preferences/in-content/tests/Makefile.in
@@ -4,14 +4,8 @@
 
 ifdef ENABLE_TESTS
 pp_mochitest_browser_files := \
     browser_privacypane_4.js \
     $(NULL)
 pp_mochitest_browser_files_PATH := $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
 PP_TARGETS += pp_mochitest_browser_files
 endif # ENABLE_TESTS
-
-ifdef MOZ_SERVICES_HEALTHREPORT
-MOCHITEST_BROWSER_FILES += \
-  browser_healthreport.js \
-  $(NULL)
-endif
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -2,12 +2,14 @@
 support-files =
   head.js
   privacypane_tests_perwindow.js
 
 [browser_advanced_update.js]
 [browser_bug410900.js]
 [browser_bug731866.js]
 [browser_connection.js]
+[browser_healthreport.js]
+skip-if = (!healthreport) || (os == 'linux' && debug)
 [browser_privacypane_1.js]
 [browser_privacypane_3.js]
 [browser_privacypane_5.js]
 [browser_privacypane_8.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/moz.build
@@ -0,0 +1,5 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
--- a/browser/components/preferences/moz.build
+++ b/browser/components/preferences/moz.build
@@ -1,20 +1,21 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 PARALLEL_DIRS += ['in-content']
+TEST_DIRS += ['tests']
 
 BROWSER_CHROME_MANIFESTS += [
     'in-content/tests/browser.ini',
     'tests/browser.ini',
 ]
 
 for var in ('MOZ_APP_NAME', 'MOZ_MACBUNDLE_NAME'):
     DEFINES[var] = CONFIG[var]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'):
     DEFINES['HAVE_SHELL_SERVICE'] = 1
 
-JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
+JAR_MANIFESTS += ['jar.mn']
--- a/browser/components/preferences/tests/Makefile.in
+++ b/browser/components/preferences/tests/Makefile.in
@@ -4,12 +4,8 @@
 
 ifdef ENABLE_TESTS
 pp_mochitest_browser_files := \
     browser_privacypane_4.js \
     $(NULL)
 pp_mochitest_browser_files_PATH := $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
 PP_TARGETS += pp_mochitest_browser_files
 endif # ENABLE_TESTS
-
-ifdef MOZ_SERVICES_HEALTHREPORT
-MOCHITEST_BROWSER_FILES += browser_healthreport.js
-endif
--- a/browser/components/preferences/tests/browser.ini
+++ b/browser/components/preferences/tests/browser.ini
@@ -2,13 +2,15 @@
 support-files =
   head.js
   privacypane_tests_perwindow.js
 
 [browser_advanced_update.js]
 [browser_bug410900.js]
 [browser_bug705422.js]
 [browser_chunk_permissions.js]
+[browser_healthreport.js]
+skip-if = (!healthreport) || (os == 'linux' && debug)
 [browser_permissions.js]
 [browser_privacypane_1.js]
 [browser_privacypane_3.js]
 [browser_privacypane_5.js]
 [browser_privacypane_8.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/tests/moz.build
@@ -0,0 +1,5 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
--- a/browser/devtools/scratchpad/test/browser_scratchpad_display_non_error_exceptions.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_display_non_error_exceptions.js
@@ -36,17 +36,17 @@ function runTests()
     result: message + openComment + "Hello World!" + closeComment,
     label: "message display output"
   },
   {
     // Display error1, throw new Error("Ouch")
     method: "display",
     code: error1,
     result: error1 + openComment +
-            "Exception: Ouch!\n@" + scratchpad.uniqueName + ":1" + closeComment,
+            "Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:1" + closeComment,
     label: "error display output"
   },
   {
     // Display error2, throw "A thrown string"
     method: "display",
     code: error2,
     result: error2 + openComment + "Exception: A thrown string" + closeComment,
     label: "thrown string display output"
@@ -73,17 +73,17 @@ function runTests()
     result: message,
     label: "message run output"
   },
   {
     // Run error1, throw new Error("Ouch")
     method: "run",
     code: error1,
     result: error1 + openComment +
-            "Exception: Ouch!\n@" + scratchpad.uniqueName + ":1" + closeComment,
+            "Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:1" + closeComment,
     label: "error run output"
   },
   {
     // Run error2, throw "A thrown string"
     method: "run",
     code: error2,
     result: error2 + openComment + "Exception: A thrown string" + closeComment,
     label: "thrown string run output"
--- a/browser/devtools/scratchpad/test/browser_scratchpad_display_outputs_errors.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_display_outputs_errors.js
@@ -32,17 +32,17 @@ function runTests()
     code: message,
     result: message + openComment + "Hello World!" + closeComment,
     label: "message display output"
   },
   {
     method: "display",
     code: error,
     result: error + openComment + "Exception: Ouch!\n@" +
-            scratchpad.uniqueName + ":1" + closeComment,
+            scratchpad.uniqueName + ":1:1" + closeComment,
     label: "error display output",
   },
   {
     method: "display",
     code: syntaxError,
     result: syntaxError + openComment + "Exception: syntax error\n@" +
             scratchpad.uniqueName + ":1" + closeComment,
     label: "syntaxError display output",
@@ -52,17 +52,17 @@ function runTests()
     code: message,
     result: message,
     label: "message run output",
   },
   {
     method: "run",
     code: error,
     result: error + openComment + "Exception: Ouch!\n@" +
-            scratchpad.uniqueName + ":1" + closeComment,
+            scratchpad.uniqueName + ":1:1" + closeComment,
     label: "error run output",
   },
   {
     method: "run",
     code: syntaxError,
     result: syntaxError + openComment + "Exception: syntax error\n@" +
             scratchpad.uniqueName + ":1" + closeComment,
     label: "syntaxError run output",
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -3219,26 +3219,30 @@ WebGLContext::CompileShader(WebGLShader 
 #endif
         }
 
 #ifdef WEBGL2_BYPASS_ANGLE
         if (!ShCompile(compiler, &angleShaderCode, 1, compileOptions)) {
 #else
         if (!ShCompile(compiler, &s, 1, compileOptions)) {
 #endif
-            size_t len = 0;
-            ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &len);
-
-            if (len) {
+            size_t lenWithNull = 0;
+            ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &lenWithNull);
+
+            if (!lenWithNull) {
+                // Error in ShGetInfo.
+                shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
+            } else {
+                size_t len = lenWithNull - 1;
+
                 nsAutoCString info;
-                info.SetLength(len);
+                info.SetLength(len); // Allocates len+1, for the null-term.
                 ShGetInfoLog(compiler, info.BeginWriting());
+
                 shader->SetTranslationFailure(info);
-            } else {
-                shader->SetTranslationFailure(NS_LITERAL_CSTRING("Internal error: failed to get shader info log"));
             }
             ShDestruct(compiler);
             shader->SetCompileStatus(false);
             return;
         }
 
         size_t num_attributes = 0;
         ShGetInfo(compiler, SH_ACTIVE_ATTRIBUTES, &num_attributes);
--- a/content/html/content/public/HTMLCanvasElement.h
+++ b/content/html/content/public/HTMLCanvasElement.h
@@ -78,28 +78,25 @@ public:
   {
     SetUnsignedIntAttr(nsGkAtoms::width, aWidth, aRv);
   }
   already_AddRefed<nsISupports>
   GetContext(JSContext* aCx, const nsAString& aContextId,
              JS::Handle<JS::Value> aContextOptions,
              ErrorResult& aRv);
   void ToDataURL(JSContext* aCx, const nsAString& aType,
-                 const Optional<JS::Handle<JS::Value> >& aParams,
+                 JS::Handle<JS::Value> aParams,
                  nsAString& aDataURL, ErrorResult& aRv)
   {
-    JS::Handle<JS::Value> params = aParams.WasPassed()
-                                 ? aParams.Value()
-                                 : JS::UndefinedHandleValue;
-    aRv = ToDataURL(aType, params, aCx, aDataURL);
+    aRv = ToDataURL(aType, aParams, aCx, aDataURL);
   }
   void ToBlob(JSContext* aCx,
               FileCallback& aCallback,
               const nsAString& aType,
-              const Optional<JS::Handle<JS::Value> >& aParams,
+              JS::Handle<JS::Value> aParams,
               ErrorResult& aRv);
 
   bool MozOpaque() const
   {
     return GetBoolAttr(nsGkAtoms::moz_opaque);
   }
   void SetMozOpaque(bool aValue, ErrorResult& aRv)
   {
--- a/content/html/content/src/HTMLCanvasElement.cpp
+++ b/content/html/content/src/HTMLCanvasElement.cpp
@@ -482,38 +482,34 @@ HTMLCanvasElement::ToDataURLImpl(JSConte
 
   return Base64EncodeInputStream(stream, aDataURL, (uint32_t)count, aDataURL.Length());
 }
 
 void
 HTMLCanvasElement::ToBlob(JSContext* aCx,
                           FileCallback& aCallback,
                           const nsAString& aType,
-                          const Optional<JS::Handle<JS::Value> >& aParams,
+                          JS::Handle<JS::Value> aParams,
                           ErrorResult& aRv)
 {
   // do a trust check if this is a write-only canvas
   if (mWriteOnly && !nsContentUtils::IsCallerChrome()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return;
   }
 
   nsAutoString type;
   aRv = nsContentUtils::ASCIIToLower(aType, type);
   if (aRv.Failed()) {
     return;
   }
 
-  JS::Value encoderOptions = aParams.WasPassed()
-                             ? aParams.Value()
-                             : JS::UndefinedValue();
-
   nsAutoString params;
   bool usingCustomParseOptions;
-  aRv = ParseParams(aCx, type, encoderOptions, params, &usingCustomParseOptions);
+  aRv = ParseParams(aCx, type, aParams, params, &usingCustomParseOptions);
   if (aRv.Failed()) {
     return;
   }
 
 #ifdef DEBUG
   if (mCurrentContext) {
     // We disallow canvases of width or height zero, and set them to 1, so
     // we will have a discrepancy with the sizes of the canvas and the context.
--- a/content/media/gstreamer/GStreamerReader.cpp
+++ b/content/media/gstreamer/GStreamerReader.cpp
@@ -221,16 +221,25 @@ void GStreamerReader::PlayBinSourceSetup
 }
 
 void GStreamerReader::PlayBinSourceSetup(GstAppSrc* aSource)
 {
   mSource = GST_APP_SRC(aSource);
   gst_app_src_set_callbacks(mSource, &mSrcCallbacks, (gpointer) this, nullptr);
   MediaResource* resource = mDecoder->GetResource();
 
+  /* do a short read to trigger a network request so that GetLength() below
+   * returns something meaningful and not -1
+   */
+  char buf[512];
+  unsigned int size = 0;
+  resource->Read(buf, sizeof(buf), &size);
+  resource->Seek(SEEK_SET, 0);
+
+  /* now we should have a length */
   int64_t resourceLength = resource->GetLength();
   gst_app_src_set_size(mSource, resourceLength);
   if (resource->IsDataCachedToEndOfResource(0) ||
       (resourceLength != -1 && resourceLength <= SHORT_FILE_SIZE)) {
     /* let the demuxer work in pull mode for local files (or very short files)
      * so that we get optimal seeking accuracy/performance
      */
     LOG(PR_LOG_DEBUG, ("configuring random access, len %lld", resourceLength));
@@ -367,37 +376,16 @@ nsresult GStreamerReader::ReadMetadata(M
 
   if (NS_SUCCEEDED(ret))
     ret = CheckSupportedFormats();
 
   if (NS_FAILED(ret))
     /* we couldn't get this to play */
     return ret;
 
-  /* FIXME: workaround for a bug in matroskademux. This seek makes matroskademux
-   * parse the index */
-  LOG(PR_LOG_DEBUG, ("doing matroskademux seek hack"));
-  if (gst_element_seek_simple(mPlayBin, GST_FORMAT_TIME,
-        GST_SEEK_FLAG_FLUSH, 0)) {
-    /* after a seek we need to wait again for ASYNC_DONE */
-    message = gst_bus_timed_pop_filtered(mBus, 5 * GST_SECOND,
-       (GstMessageType)(GST_MESSAGE_ASYNC_DONE | GST_MESSAGE_ERROR));
-    if (message == NULL || GST_MESSAGE_TYPE(message) != GST_MESSAGE_ASYNC_DONE) {
-      LOG(PR_LOG_DEBUG, ("matroskademux seek hack failed: %p", message));
-      gst_element_set_state(mPlayBin, GST_STATE_NULL);
-      if (message) {
-        gst_message_unref(message);
-      }
-      return NS_ERROR_FAILURE;
-    }
-    LOG(PR_LOG_DEBUG, ("matroskademux seek hack completed"));
-  } else {
-    LOG(PR_LOG_DEBUG, ("matroskademux seek hack failed (non fatal)"));
-  }
-
   bool isMP3 = mDecoder->GetResource()->GetContentType().EqualsASCII(AUDIO_MP3);
   if (isMP3) {
     ParseMP3Headers();
   }
 
   /* report the duration */
   gint64 duration;
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -8802,28 +8802,24 @@ nsGlobalWindow::ShowModalDialog(const ns
   aError = dialog->GetReturnValue(getter_AddRefs(retVal));
   MOZ_ASSERT(!aError.Failed());
 
   return retVal.forget();
 }
 
 JS::Value
 nsGlobalWindow::ShowModalDialog(JSContext* aCx, const nsAString& aUrl,
-                                const Optional<JS::Handle<JS::Value> >& aArgument,
+                                JS::Handle<JS::Value> aArgument,
                                 const nsAString& aOptions,
                                 ErrorResult& aError)
 {
   nsCOMPtr<nsIVariant> args;
-  if (aArgument.WasPassed()) {
-    aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
-                                                      aArgument.Value(),
-                                                      getter_AddRefs(args));
-  } else {
-    args = CreateVoidVariant();
-  }
+  aError = nsContentUtils::XPConnect()->JSToVariant(aCx,
+                                                    aArgument,
+                                                    getter_AddRefs(args));
 
   nsCOMPtr<nsIVariant> retVal = ShowModalDialog(aUrl, args, aOptions, aError);
   if (aError.Failed()) {
     return JS::UndefinedValue();
   }
 
   JS::Rooted<JS::Value> result(aCx);
   if (retVal) {
@@ -11425,17 +11421,19 @@ nsGlobalWindow::SetTimeout(JSContext* aC
                            const Sequence<JS::Value>& aArguments,
                            ErrorResult& aError)
 {
   return SetTimeoutOrInterval(aFunction, aTimeout, aArguments, false, aError);
 }
 
 int32_t
 nsGlobalWindow::SetTimeout(JSContext* aCx, const nsAString& aHandler,
-                           int32_t aTimeout, ErrorResult& aError)
+                           int32_t aTimeout,
+                           const Sequence<JS::Value>& /* unused */,
+                           ErrorResult& aError)
 {
   return SetTimeoutOrInterval(aCx, aHandler, aTimeout, false, aError);
 }
 
 static bool
 IsInterval(const Optional<int32_t>& aTimeout, int32_t& aResultTimeout)
 {
   if (aTimeout.WasPassed()) {
@@ -11459,16 +11457,17 @@ nsGlobalWindow::SetInterval(JSContext* a
   bool isInterval = IsInterval(aTimeout, timeout);
   return SetTimeoutOrInterval(aFunction, timeout, aArguments, isInterval,
                               aError);
 }
 
 int32_t
 nsGlobalWindow::SetInterval(JSContext* aCx, const nsAString& aHandler,
                             const Optional<int32_t>& aTimeout,
+                            const Sequence<JS::Value>& /* unused */,
                             ErrorResult& aError)
 {
   int32_t timeout;
   bool isInterval = IsInterval(aTimeout, timeout);
   return SetTimeoutOrInterval(aCx, aHandler, timeout, isInterval, aError);
 }
 
 nsresult
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -819,34 +819,37 @@ protected:
                       mozilla::ErrorResult& aError);
 
 public:
   void Alert(const nsAString& aMessage, mozilla::ErrorResult& aError);
   bool Confirm(const nsAString& aMessage, mozilla::ErrorResult& aError);
   void Prompt(const nsAString& aMessage, const nsAString& aInitial,
               nsAString& aReturn, mozilla::ErrorResult& aError);
   void Print(mozilla::ErrorResult& aError);
-  JS::Value ShowModalDialog(JSContext* aCx, const nsAString& aUrl, const mozilla::dom::Optional<JS::Handle<JS::Value> >& aArgument, const nsAString& aOptions, mozilla::ErrorResult& aError);
+  JS::Value ShowModalDialog(JSContext* aCx, const nsAString& aUrl, JS::Handle<JS::Value> aArgument, const nsAString& aOptions, mozilla::ErrorResult& aError);
   void PostMessageMoz(JSContext* aCx, JS::Handle<JS::Value> aMessage,
                       const nsAString& aTargetOrigin,
                       const mozilla::dom::Optional<mozilla::dom::Sequence<JS::Value > >& aTransfer,
                       mozilla::ErrorResult& aError);
   int32_t SetTimeout(JSContext* aCx, mozilla::dom::Function& aFunction,
                      int32_t aTimeout,
                      const mozilla::dom::Sequence<JS::Value>& aArguments,
                      mozilla::ErrorResult& aError);
   int32_t SetTimeout(JSContext* aCx, const nsAString& aHandler,
-                     int32_t aTimeout, mozilla::ErrorResult& aError);
+                     int32_t aTimeout,
+                     const mozilla::dom::Sequence<JS::Value>& /* unused */,
+                     mozilla::ErrorResult& aError);
   void ClearTimeout(int32_t aHandle, mozilla::ErrorResult& aError);
   int32_t SetInterval(JSContext* aCx, mozilla::dom::Function& aFunction,
                       const mozilla::dom::Optional<int32_t>& aTimeout,
                       const mozilla::dom::Sequence<JS::Value>& aArguments,
                       mozilla::ErrorResult& aError);
   int32_t SetInterval(JSContext* aCx, const nsAString& aHandler,
                       const mozilla::dom::Optional<int32_t>& aTimeout,
+                      const mozilla::dom::Sequence<JS::Value>& /* unused */,
                       mozilla::ErrorResult& aError);
   void ClearInterval(int32_t aHandle, mozilla::ErrorResult& aError);
   void Atob(const nsAString& aAsciiBase64String, nsAString& aBinaryData,
             mozilla::ErrorResult& aError);
   void Btoa(const nsAString& aBinaryData, nsAString& aAsciiBase64String,
             mozilla::ErrorResult& aError);
   nsIDOMStorage* GetSessionStorage(mozilla::ErrorResult& aError);
   nsIDOMStorage* GetLocalStorage(mozilla::ErrorResult& aError);
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -31,16 +31,17 @@ support-files =
 [test_messagemanager_targetchain.html]
 [test_messageChannel_transferable.html]
 [test_messageChannel_unshipped.html]
 [test_named_frames.html]
 [test_nondomexception.html]
 [test_openDialogChromeOnly.html]
 [test_postMessage_solidus.html]
 [test_screen_orientation.html]
+[test_settimeout_extra_arguments.html]
 [test_settimeout_inner.html]
 [test_setting_opener.html]
 [test_url.html]
 [test_url_empty_port.html]
 [test_urlExceptions.html]
 [test_urlSearchParams.html]
 [test_urlutils_stringify.html]
 [test_window_constructor.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_settimeout_extra_arguments.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for setTimeout with a string argument and more than 2 arguments</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+  t1 = async_test("setTimeout with more than 2 arguments, first argument a string, should work");
+  t2 = async_test("setInterval with more than 2 arguments, first argument a string, should work");
+  setTimeout("t1.done()", 0, {});
+  var interval = setInterval("clearInterval(interval); t2.done()", 0, {});
+</script>
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -236,42 +236,24 @@ public:
 
   template <class T1>
   void Construct(const T1& t1)
   {
     Optional_base<JSObject*, JSObject*>::Construct(t1);
   }
 };
 
-// A specialization of Optional for JS::Value to make sure that when someone
-// calls Construct() on it we will pre-initialized the JS::Value to
-// JS::UndefinedValue() so it can be traced safely.
+// A specialization of Optional for JS::Value to make sure no one ever uses it.
 template<>
-class Optional<JS::Value> : public Optional_base<JS::Value, JS::Value>
+class Optional<JS::Value>
 {
-public:
-  Optional() :
-    Optional_base<JS::Value, JS::Value>()
-  {}
+private:
+  Optional() MOZ_DELETE;
 
-  explicit Optional(JS::Value aValue) :
-    Optional_base<JS::Value, JS::Value>(aValue)
-  {}
-
-  // Don't allow us to have an uninitialized JS::Value
-  void Construct()
-  {
-    Optional_base<JS::Value, JS::Value>::Construct(JS::UndefinedValue());
-  }
-
-  template <class T1>
-  void Construct(const T1& t1)
-  {
-    Optional_base<JS::Value, JS::Value>::Construct(t1);
-  }
+  explicit Optional(JS::Value aValue) MOZ_DELETE;
 };
 
 // A specialization of Optional for NonNull that lets us get a T& from Value()
 template<typename U> class NonNull;
 template<typename T>
 class Optional<NonNull<T> > : public Optional_base<T, NonNull<T> >
 {
 public:
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1518,17 +1518,16 @@ DOMInterfaces = {
 },
 
 'Window': {
     'nativeType': 'nsGlobalWindow',
     # When turning on Window, remember to drop the "'register': False"
     # from ChromeWindow.
     'hasXPConnectImpls': True,
     'register': False,
-    'implicitJSContext': [ 'setInterval', 'setTimeout' ],
     'binaryNames': {
         'postMessage': 'postMessageMoz',
     },
 },
 
 'WindowProxy': [
 {
     'nativeType': 'nsIDOMWindow',
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -6,17 +6,17 @@
 
 import operator
 import os
 import re
 import string
 import math
 import itertools
 
-from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute
+from WebIDL import BuiltinTypes, IDLBuiltinType, IDLNullValue, IDLSequenceType, IDLType, IDLAttribute, IDLUndefinedValue
 from Configuration import NoSuchDescriptorError, getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor
 
 AUTOGENERATED_WARNING_COMMENT = \
     "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
 ADDPROPERTY_HOOK_NAME = '_addProperty'
 FINALIZE_HOOK_NAME = '_finalize'
 CONSTRUCT_HOOK_NAME = '_constructor'
 LEGACYCALLER_HOOK_NAME = '_legacycaller'
@@ -3839,31 +3839,32 @@ for (uint32_t i = 0; i < length; ++i) {
 
         declArgs = None
         if (isMember == "Variadic" or isMember == "Sequence" or
             isMember == "Dictionary"):
             # Rooting is handled by the sequence and dictionary tracers.
             declType = "JS::Value"
         else:
             assert not isMember
-            if isOptional:
-                # We have a specialization of Optional that will use a
-                # Rooted for the storage here.
-                declType = "JS::Handle<JS::Value>"
+            declType = "JS::Rooted<JS::Value>"
+            declArgs = "cx"
+
+        assert not isOptional
+        templateBody = "${declName} = ${val};"
+        # We may not have a default value if we're being converted for
+        # a setter, say.
+        if defaultValue:
+            if isinstance(defaultValue, IDLNullValue):
+                defaultHandling = "${declName} = JS::NullValue()"
             else:
-                declType = "JS::Rooted<JS::Value>"
-            declArgs = "cx"
-
-        templateBody = "${declName} = ${val};"
-        nullHandling = "${declName} = JS::NullValue()"
-
-        templateBody = handleDefaultNull(templateBody, nullHandling)
+                assert isinstance(defaultValue, IDLUndefinedValue)
+                defaultHandling = "${declName} = JS::UndefinedValue()"
+            templateBody = handleDefault(templateBody, defaultHandling)
         return JSToNativeConversionInfo(templateBody,
                                         declType=CGGeneric(declType),
-                                        dealWithOptional=isOptional,
                                         declArgs=declArgs)
 
     if type.isObject():
         assert not isEnforceRange and not isClamp
         return handleJSObjectType(type, isMember, failureCode)
 
     if type.isDictionary():
         # There are no nullable dictionaries
@@ -4137,16 +4138,18 @@ def instantiateJSToNativeConversion(info
     # Add an empty CGGeneric to get an extra newline after the argument
     # conversion.
     result.append(CGGeneric(""))
     return result
 
 def convertConstIDLValueToJSVal(value):
     if isinstance(value, IDLNullValue):
         return "JS::NullValue()"
+    if isinstance(value, IDLUndefinedValue):
+        return "JS::UndefinedValue()"
     tag = value.type.tag()
     if tag in [IDLType.Tags.int8, IDLType.Tags.uint8, IDLType.Tags.int16,
                IDLType.Tags.uint16, IDLType.Tags.int32]:
         return "INT_TO_JSVAL(%s)" % (value.value)
     if tag == IDLType.Tags.uint32:
         return "UINT_TO_JSVAL(%sU)" % (value.value)
     if tag in [IDLType.Tags.int64, IDLType.Tags.uint64]:
         return "DOUBLE_TO_JSVAL(%s)" % numericValue(tag, value.value)
--- a/dom/bindings/parser/WebIDL.py
+++ b/dom/bindings/parser/WebIDL.py
@@ -2526,17 +2526,34 @@ class IDLNullValue(IDLObject):
                 if t.isDictionary():
                     nullValue.type = t
                     return nullValue
         nullValue.type = type
         return nullValue
 
     def _getDependentObjects(self):
         return set()
-  
+
+class IDLUndefinedValue(IDLObject):
+    def __init__(self, location):
+        IDLObject.__init__(self, location)
+        self.type = None
+        self.value = None
+
+    def coerceToType(self, type, location):
+        if not type.isAny():
+            raise WebIDLError("Cannot coerce undefined value to type %s." % type,
+                              [location])
+
+        undefinedValue = IDLUndefinedValue(self.location)
+        undefinedValue.type = type
+        return undefinedValue
+
+    def _getDependentObjects(self):
+        return set()
 
 class IDLInterfaceMember(IDLObjectWithIdentifier):
 
     Tags = enum(
         'Const',
         'Attr',
         'Method'
     )
@@ -2904,16 +2921,32 @@ class IDLArgument(IDLObjectWithIdentifie
             self.type = type
 
         if ((self.type.isDictionary() or
              self.type.isUnion() and self.type.unroll().hasDictionaryType) and
             self.optional and not self.defaultValue):
             # Default optional dictionaries to null, for simplicity,
             # so the codegen doesn't have to special-case this.
             self.defaultValue = IDLNullValue(self.location)
+        elif self.type.isAny():
+            assert (self.defaultValue is None or
+                    isinstance(self.defaultValue, IDLNullValue))
+            if (self.optional and not self.variadic and
+                not self.dictionaryMember and not self.defaultValue):
+                raise WebIDLError("Arguments of type 'any' are always optional "
+                                  "and shouldn't have the 'optional' keyword "
+                                  "unless they're being given a default value "
+                                  "of 'null'",
+                                  [self.location])
+            # 'any' values are always optional.
+            self.optional = True
+            if not self.defaultValue and not self.variadic:
+                # Set the default value to undefined, for simplicity, so the
+                # codegen doesn't have to special-case this.
+                self.defaultValue = IDLUndefinedValue(self.location)
 
         # Now do the coercing thing; this needs to happen after the
         # above creation of a default value.
         if self.defaultValue:
             self.defaultValue = self.defaultValue.coerceToType(self.type,
                                                                self.location)
             assert self.defaultValue
 
@@ -4283,16 +4316,20 @@ class Parser(Tokenizer):
         optional = p[2]
         variadic = p[4]
         defaultValue = p[6]
 
         if not optional and defaultValue:
             raise WebIDLError("Mandatory arguments can't have a default value.",
                               [self.getLocation(p, 6)])
 
+        # We can't test t.isAny() here and force optional to true, since at this
+        # point t is not a fully resolved type yet (e.g. it might be a typedef).
+        # We'll handle the 'any' case in IDLArgument.complete.
+
         if variadic:
             if optional:
                 raise WebIDLError("Variadic arguments should not be marked optional.",
                                   [self.getLocation(p, 2)])
             optional = variadic
 
         p[0] = IDLArgument(self.getLocation(p, 5), identifier, t, optional, defaultValue, variadic)
         p[0].addExtendedAttributes(p[1])
--- a/dom/bindings/parser/tests/test_method.py
+++ b/dom/bindings/parser/tests/test_method.py
@@ -107,17 +107,17 @@ def WebIDLTest(parser, harness):
                 "getObject", [("Object", [])])
     checkMethod(methods[10], "::TestMethods::setObject",
                 "setObject",
        [("Void",
         [("::TestMethods::setObject::arg1", "arg1", "Object", False, False)])])
     checkMethod(methods[11], "::TestMethods::setAny",
                 "setAny",
        [("Void",
-        [("::TestMethods::setAny::arg1", "arg1", "Any", False, False)])])
+        [("::TestMethods::setAny::arg1", "arg1", "Any", True, False)])])
     checkMethod(methods[12], "::TestMethods::doFloats",
                 "doFloats",
        [("Float",
         [("::TestMethods::doFloats::arg1", "arg1", "Float", False, False)])])
 
     parser = parser.reset()
     threw = False
     try:
--- a/dom/bindings/test/TestBindingHeader.h
+++ b/dom/bindings/test/TestBindingHeader.h
@@ -141,21 +141,21 @@ public:
   static
   already_AddRefed<TestInterface> Test(const GlobalObject&, const nsACString&,
                                        ErrorResult&);
 
   static
   already_AddRefed<TestInterface> Test2(const GlobalObject&,
                                         JSContext*,
                                         const DictForConstructor&,
-                                        JS::Value,
+                                        JS::Handle<JS::Value>,
                                         JS::Handle<JSObject*>,
                                         JS::Handle<JSObject*>,
                                         const Sequence<Dict>&,
-                                        const Optional<JS::Handle<JS::Value> >&,
+                                        JS::Handle<JS::Value>,
                                         const Optional<JS::Handle<JSObject*> >&,
                                         const Optional<JS::Handle<JSObject*> >&,
                                         ErrorResult&);
 
   // Integer types
   int8_t ReadonlyByte();
   int8_t WritableByte();
   void SetWritableByte(int8_t);
@@ -461,17 +461,16 @@ public:
   void SetTreatAsNullCallback(TestTreatAsNullCallback&);
   already_AddRefed<TestTreatAsNullCallback> TreatAsNullCallback();
   void SetNullableTreatAsNullCallback(TestTreatAsNullCallback*);
   already_AddRefed<TestTreatAsNullCallback> GetNullableTreatAsNullCallback();
 
   // Any types
   void PassAny(JSContext*, JS::Handle<JS::Value>);
   void PassVariadicAny(JSContext*, const Sequence<JS::Value>&);
-  void PassOptionalAny(JSContext*, const Optional<JS::Handle<JS::Value> >&);
   void PassAnyDefaultNull(JSContext*, JS::Handle<JS::Value>);
   void PassSequenceOfAny(JSContext*, const Sequence<JS::Value>&);
   void PassNullableSequenceOfAny(JSContext*, const Nullable<Sequence<JS::Value> >&);
   void PassOptionalSequenceOfAny(JSContext*, const Optional<Sequence<JS::Value> >&);
   void PassOptionalNullableSequenceOfAny(JSContext*, const Optional<Nullable<Sequence<JS::Value> > >&);
   void PassOptionalSequenceOfAnyWithDefaultValue(JSContext*, const Nullable<Sequence<JS::Value> >&);
   void PassSequenceOfSequenceOfAny(JSContext*, const Sequence<Sequence<JS::Value> >&);
   void PassSequenceOfNullableSequenceOfAny(JSContext*, const Sequence<Nullable<Sequence<JS::Value> > >&);
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -105,17 +105,18 @@ interface OnlyForUseInConstructor {
  Constructor(TestInterface? iface),
  Constructor(long arg1, IndirectlyImplementedInterface iface),
  Constructor(Date arg1),
  // Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3),
  AvailableIn=CertifiedApps,
  NamedConstructor=Test,
  NamedConstructor=Test(DOMString str),
  NamedConstructor=Test2(DictForConstructor dict, any any1, object obj1,
-                        object? obj2, sequence<Dict> seq, optional any any2,
+                        object? obj2, sequence<Dict> seq,
+                        optional any any2 = null,
                         optional object obj3, optional object? obj4)
  ]
 interface TestInterface {
   // Integer types
   // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
   void passByte(byte arg);
@@ -423,17 +424,16 @@ interface TestInterface {
   void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
   attribute TestTreatAsNullCallback treatAsNullCallback;
   attribute TestTreatAsNullCallback? nullableTreatAsNullCallback;
 
   // Any types
   void passAny(any arg);
   void passVariadicAny(any... arg);
-  void passOptionalAny(optional any arg);
   void passAnyDefaultNull(optional any arg = null);
   void passSequenceOfAny(sequence<any> arg);
   void passNullableSequenceOfAny(sequence<any>? arg);
   void passOptionalSequenceOfAny(optional sequence<any> arg);
   void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
   void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
   void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
   void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -7,17 +7,18 @@
  Constructor(DOMString str),
  Constructor(unsigned long num, boolean? boolArg),
  Constructor(TestInterface? iface),
  Constructor(long arg1, IndirectlyImplementedInterface iface),
  // Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3),
  NamedConstructor=Example,
  NamedConstructor=Example(DOMString str),
  NamedConstructor=Example2(DictForConstructor dict, any any1, object obj1,
-                           object? obj2, sequence<Dict> seq, optional any any2,
+                           object? obj2, sequence<Dict> seq,
+                           optional any any2 = null,
                            optional object obj3, optional object? obj4)
  ]
 interface TestExampleInterface {
   // Integer types
   // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
   void passByte(byte arg);
@@ -316,17 +317,16 @@ interface TestExampleInterface {
   TestCallback? receiveNullableCallback();
   void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
 
   // Any types
   void passAny(any arg);
   void passVariadicAny(any... arg);
-  void passOptionalAny(optional any arg);
   void passAnyDefaultNull(optional any arg = null);
   void passSequenceOfAny(sequence<any> arg);
   void passNullableSequenceOfAny(sequence<any>? arg);
   void passOptionalSequenceOfAny(optional sequence<any> arg);
   void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
   void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
   void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
   void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -18,17 +18,17 @@ enum MyTestEnum {
 };
 
 // We don't support multiple constructors (bug 869268) or named constructors
 // for JS-implemented WebIDL.
 [Constructor(DOMString str, unsigned long num, boolean? boolArg,
              TestInterface? iface, long arg1,
              DictForConstructor dict, any any1,
              object obj1,
-             object? obj2, sequence<Dict> seq, optional any any2,
+             object? obj2, sequence<Dict> seq, optional any any2 = null,
              optional object obj3,
              optional object? obj4),
  JSImplementation="@mozilla.org/test-js-impl-interface;1"]
 interface TestJSImplInterface {
   // Integer types
   // XXXbz add tests for throwing versions of all the integer stuff
   readonly attribute byte readonlyByte;
   attribute byte writableByte;
@@ -339,17 +339,16 @@ interface TestJSImplInterface {
   // Hmm. These two don't work, I think because I need a locally modified version of TestTreatAsNullCallback.
   //void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg);
   //void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
   void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
 
   // Any types
   void passAny(any arg);
   void passVariadicAny(any... arg);
-  void passOptionalAny(optional any arg);
   void passAnyDefaultNull(optional any arg = null);
   void passSequenceOfAny(sequence<any> arg);
   void passNullableSequenceOfAny(sequence<any>? arg);
   void passOptionalSequenceOfAny(optional sequence<any> arg);
   void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
   void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
   void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
   void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
--- a/dom/events/nsDOMMessageEvent.cpp
+++ b/dom/events/nsDOMMessageEvent.cpp
@@ -125,19 +125,17 @@ nsDOMMessageEvent::Constructor(const moz
   aRv = event->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   bool trusted = event->Init(t);
   event->SetTrusted(trusted);
 
-  if (aParam.mData.WasPassed()) {
-    event->mData = aParam.mData.Value();
-  }
+  event->mData = aParam.mData;
 
   mozilla::HoldJSObjects(event.get());
 
   if (aParam.mOrigin.WasPassed()) {
     event->mOrigin = aParam.mOrigin.Value();
   }
 
   if (aParam.mLastEventId.WasPassed()) {
--- a/dom/imptests/html/dom/test_interfaces.html
+++ b/dom/imptests/html/dom/test_interfaces.html
@@ -74,17 +74,17 @@ dictionary EventInit {
   boolean bubbles = false;
   boolean cancelable = false;
 };
 
 [Constructor(DOMString type, optional CustomEventInit eventInitDict)]
 interface CustomEvent : Event {
   readonly attribute any detail;
 
-  void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any details);
+  void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, optional any details);
 };
 
 dictionary CustomEventInit : EventInit {
   any detail = null;
 };
 
 interface EventTarget {
   void addEventListener(DOMString type, EventListener? callback, optional boolean capture);
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -692,26 +692,24 @@ IDBCursor::GetValue(JSContext* aCx, Erro
     mHaveCachedValue = true;
   }
 
   return mCachedValue;
 }
 
 void
 IDBCursor::Continue(JSContext* aCx,
-                    const Optional<JS::Handle<JS::Value> >& aKey,
+                    JS::Handle<JS::Value> aKey,
                     ErrorResult &aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   Key key;
-  if (aKey.WasPassed()) {
-    aRv = key.SetFromJSVal(aCx, aKey.Value());
-    ENSURE_SUCCESS_VOID(aRv);
-  }
+  aRv = key.SetFromJSVal(aCx, aKey);
+  ENSURE_SUCCESS_VOID(aRv);
 
   if (!key.IsUnset()) {
     switch (mDirection) {
       case IDBCursor::NEXT:
       case IDBCursor::NEXT_UNIQUE:
         if (key <= mKey) {
           aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
           return;
@@ -804,31 +802,27 @@ IDBCursor::Update(JSContext* aCx, JS::Ha
       return nullptr;
     }
 
     if (key != objectKey) {
       aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
       return nullptr;
     }
 
-    JS::Rooted<JS::Value> value(aCx, aValue);
-    Optional<JS::Handle<JS::Value> > keyValue(aCx);
-    request = mObjectStore->Put(aCx, value, keyValue, aRv);
+    request = mObjectStore->Put(aCx, aValue, JS::UndefinedHandleValue, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
   else {
     JS::Rooted<JS::Value> keyVal(aCx);
     aRv = objectKey.ToJSVal(aCx, &keyVal);
     ENSURE_SUCCESS(aRv, nullptr);
 
-    JS::Rooted<JS::Value> value(aCx, aValue);
-    Optional<JS::Handle<JS::Value> > keyValue(aCx, keyVal);
-    request = mObjectStore->Put(aCx, value, keyValue, aRv);
+    request = mObjectStore->Put(aCx, aValue, keyVal, aRv);
     if (aRv.Failed()) {
       return nullptr;
     }
   }
 
 #ifdef IDB_PROFILER_USE_MARKS
   {
     uint64_t requestSerial =
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -192,18 +192,17 @@ public:
 
   already_AddRefed<IDBRequest>
   Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   void
   Advance(uint32_t aCount, ErrorResult& aRv);
 
   void
-  Continue(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
-           ErrorResult& aRv);
+  Continue(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Delete(JSContext* aCx, ErrorResult& aRv);
 
   JS::Value
   GetValue(JSContext* aCx, ErrorResult& aRv);
 
 protected:
--- a/dom/indexedDB/IDBIndex.cpp
+++ b/dom/indexedDB/IDBIndex.cpp
@@ -891,86 +891,80 @@ IDBIndex::GetKey(JSContext* aCx, JS::Han
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR);
     return nullptr;
   }
 
   return GetKeyInternal(keyRange, aRv);
 }
 
 already_AddRefed<IDBRequest>
-IDBIndex::GetAll(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+IDBIndex::GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
                  const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   uint32_t limit = UINT32_MAX;
   if (aLimit.WasPassed() && aLimit.Value() > 0) {
     limit = aLimit.Value();
   }
 
   return GetAllInternal(keyRange, limit, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::GetAllKeys(JSContext* aCx,
-                     const Optional<JS::Handle<JS::Value> >& aKey,
+                     JS::Handle<JS::Value> aKey,
                      const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   uint32_t limit = UINT32_MAX;
   if (aLimit.WasPassed() && aLimit.Value() > 0) {
     limit = aLimit.Value();
   }
 
   return GetAllKeysInternal(keyRange, limit, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::OpenCursor(JSContext* aCx,
-                     const Optional<JS::Handle<JS::Value> >& aRange,
+                     JS::Handle<JS::Value> aRange,
                      IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aRange.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   if (!request) {
     IDB_WARNING("Failed to generate request!");
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
     return nullptr;
@@ -986,53 +980,49 @@ IDBIndex::OpenCursor(JSContext* aCx,
     return nullptr;
   }
 
   return request.forget();
 }
 
 already_AddRefed<IDBRequest>
 IDBIndex::OpenKeyCursor(JSContext* aCx,
-                        const Optional<JS::Handle<JS::Value> >& aRange,
+                        JS::Handle<JS::Value> aRange,
                         IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aRange.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
 
   return OpenKeyCursorInternal(keyRange, direction, aRv);
 }
 
 already_AddRefed<IDBRequest>
-IDBIndex::Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+IDBIndex::Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
                 ErrorResult& aRv)
 {
   IDBTransaction* transaction = mObjectStore->Transaction();
   if (!transaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   return CountInternal(keyRange, aRv);
 }
 
 void
 IndexHelper::ReleaseMainThreadObjects()
 {
   mIndex = nullptr;
--- a/dom/indexedDB/IDBIndex.h
+++ b/dom/indexedDB/IDBIndex.h
@@ -189,46 +189,46 @@ public:
   bool
   Unique() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return mUnique;
   }
 
   already_AddRefed<IDBRequest>
-  OpenCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
+  OpenCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
              IDBCursorDirection aDirection, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  OpenKeyCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
+  OpenKeyCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
                 IDBCursorDirection aDirection, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   GetKey(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
          ErrorResult& aRv);
 
   void
   GetStoreName(nsString& aStoreName) const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     mObjectStore->GetName(aStoreName);
   }
 
   already_AddRefed<IDBRequest>
-  GetAll(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
          const Optional<uint32_t>& aLimit, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  GetAllKeys(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  GetAllKeys(JSContext* aCx, JS::Handle<JS::Value> aKey,
              const Optional<uint32_t>& aLimit, ErrorResult& aRv);
 
 private:
   IDBIndex();
   ~IDBIndex();
 
   nsRefPtr<IDBObjectStore> mObjectStore;
 
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -1902,40 +1902,37 @@ IDBObjectStore::GetAddInfo(JSContext* aC
     rv = GetAddInfoCallback(aCx, &data);
   }
 
   return rv;
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::AddOrPut(JSContext* aCx, JS::Handle<JS::Value> aValue,
-                         const Optional<JS::Handle<JS::Value> >& aKey,
+                         JS::Handle<JS::Value> aKey,
                          bool aOverwrite, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   if (!IsWriteAllowed()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR);
     return nullptr;
   }
 
-  JS::Rooted<JS::Value> keyval(aCx, aKey.WasPassed() ? aKey.Value()
-                                                     : JSVAL_VOID);
-
   StructuredCloneWriteInfo cloneWriteInfo;
   Key key;
   nsTArray<IndexUpdateInfo> updateInfo;
 
   JS::Rooted<JS::Value> value(aCx, aValue);
-  aRv = GetAddInfo(aCx, value, keyval, cloneWriteInfo, key, updateInfo);
+  aRv = GetAddInfo(aCx, value, aKey, cloneWriteInfo, key, updateInfo);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   nsRefPtr<IDBRequest> request = GenerateRequest(this);
   if (!request) {
     IDB_WARNING("Failed to generate request!");
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
@@ -2695,31 +2692,29 @@ IDBObjectStore::Get(JSContext* aCx, JS::
     return nullptr;
   }
 
   return GetInternal(keyRange, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::GetAll(JSContext* aCx,
-                       const Optional<JS::Handle<JS::Value> >& aKey,
+                       JS::Handle<JS::Value> aKey,
                        const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   uint32_t limit = UINT32_MAX;
   if (aLimit.WasPassed() && aLimit.Value() != 0) {
     limit = aLimit.Value();
   }
 
   return GetAllInternal(keyRange, limit, aRv);
 }
@@ -2750,31 +2745,29 @@ IDBObjectStore::Delete(JSContext* aCx, J
     return nullptr;
   }
 
   return DeleteInternal(keyRange, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::OpenCursor(JSContext* aCx,
-                           const Optional<JS::Handle<JS::Value> >& aRange,
+                           JS::Handle<JS::Value> aRange,
                            IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aRange.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
   size_t argDirection = static_cast<size_t>(direction);
 
   return OpenCursorInternal(keyRange, argDirection, aRv);
 }
 
 already_AddRefed<IDBIndex>
@@ -2936,76 +2929,70 @@ IDBObjectStore::DeleteIndex(const nsAStr
                     IDB_PROFILER_STRING(Transaction()->Database()),
                     IDB_PROFILER_STRING(Transaction()),
                     IDB_PROFILER_STRING(this),
                     NS_ConvertUTF16toUTF8(aName).get());
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::Count(JSContext* aCx,
-                      const Optional<JS::Handle<JS::Value> >& aKey,
+                      JS::Handle<JS::Value> aKey,
                       ErrorResult& aRv)
 {
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   return CountInternal(keyRange, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::GetAllKeys(JSContext* aCx,
-                           const Optional<JS::Handle<JS::Value>>& aKey,
+                           JS::Handle<JS::Value> aKey,
                            const Optional<uint32_t>& aLimit, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aKey.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aKey.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   uint32_t limit = UINT32_MAX;
   if (aLimit.WasPassed() && aLimit.Value() != 0) {
     limit = aLimit.Value();
   }
 
   return GetAllKeysInternal(keyRange, limit, aRv);
 }
 
 already_AddRefed<IDBRequest>
 IDBObjectStore::OpenKeyCursor(JSContext* aCx,
-                              const Optional<JS::Handle<JS::Value>>& aRange,
+                              JS::Handle<JS::Value> aRange,
                               IDBCursorDirection aDirection, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mTransaction->IsOpen()) {
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR);
     return nullptr;
   }
 
   nsRefPtr<IDBKeyRange> keyRange;
-  if (aRange.WasPassed()) {
-    aRv = IDBKeyRange::FromJSVal(aCx, aRange.Value(), getter_AddRefs(keyRange));
-    ENSURE_SUCCESS(aRv, nullptr);
-  }
+  aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange));
+  ENSURE_SUCCESS(aRv, nullptr);
 
   IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection);
 
   return OpenKeyCursorInternal(keyRange, static_cast<size_t>(direction), aRv);
 }
 
 inline nsresult
 CopyData(nsIInputStream* aInputStream, nsIOutputStream* aOutputStream)
--- a/dom/indexedDB/IDBObjectStore.h
+++ b/dom/indexedDB/IDBObjectStore.h
@@ -299,41 +299,41 @@ public:
   AutoIncrement() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return mAutoIncrement;
   }
 
   already_AddRefed<IDBRequest>
   Put(JSContext* aCx, JS::Handle<JS::Value> aValue,
-      const Optional<JS::Handle<JS::Value> >& aKey, ErrorResult& aRv)
+      JS::Handle<JS::Value> aKey, ErrorResult& aRv)
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return AddOrPut(aCx, aValue, aKey, true, aRv);
   }
 
   already_AddRefed<IDBRequest>
   Add(JSContext* aCx, JS::Handle<JS::Value> aValue,
-      const Optional<JS::Handle<JS::Value> >& aKey, ErrorResult& aRv)
+      JS::Handle<JS::Value> aKey, ErrorResult& aRv)
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return AddOrPut(aCx, aValue, aKey, false, aRv);
   }
 
   already_AddRefed<IDBRequest>
   Delete(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Get(JSContext* aCx, JS::Handle<JS::Value> aKey, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
   Clear(ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  OpenCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aRange,
+  OpenCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
              IDBCursorDirection aDirection, ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName, const nsAString& aKeyPath,
               const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName,
@@ -342,45 +342,45 @@ public:
 
   already_AddRefed<IDBIndex>
   Index(const nsAString& aName, ErrorResult &aRv);
 
   void
   DeleteIndex(const nsAString& aIndexName, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  Count(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  Count(JSContext* aCx, JS::Handle<JS::Value> aKey,
         ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  GetAll(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aKey,
+  GetAll(JSContext* aCx, JS::Handle<JS::Value> aKey,
          const Optional<uint32_t>& aLimit, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  GetAllKeys(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aKey,
+  GetAllKeys(JSContext* aCx, JS::Handle<JS::Value> aKey,
              const Optional<uint32_t>& aLimit, ErrorResult& aRv);
 
   already_AddRefed<IDBRequest>
-  OpenKeyCursor(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aRange,
+  OpenKeyCursor(JSContext* aCx, JS::Handle<JS::Value> aRange,
                 IDBCursorDirection aDirection, ErrorResult& aRv);
 
 protected:
   IDBObjectStore();
   ~IDBObjectStore();
 
   nsresult GetAddInfo(JSContext* aCx,
                       JS::Handle<JS::Value> aValue,
                       JS::Handle<JS::Value> aKeyVal,
                       StructuredCloneWriteInfo& aCloneWriteInfo,
                       Key& aKey,
                       nsTArray<IndexUpdateInfo>& aUpdateInfoArray);
 
   already_AddRefed<IDBRequest>
   AddOrPut(JSContext* aCx, JS::Handle<JS::Value> aValue,
-           const Optional<JS::Handle<JS::Value> >& aKey, bool aOverwrite,
+           JS::Handle<JS::Value> aKey, bool aOverwrite,
            ErrorResult& aRv);
 
   already_AddRefed<IDBIndex>
   CreateIndex(JSContext* aCx, const nsAString& aName, KeyPath& aKeyPath,
               const IDBIndexParameters& aOptionalParameters, ErrorResult& aRv);
 
   static void
   ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer);
--- a/dom/ipc/TabContext.cpp
+++ b/dom/ipc/TabContext.cpp
@@ -167,17 +167,17 @@ TabContext::SetTabContextForAppFrame(moz
   if (aOwnApp) {
     nsresult rv = aOwnApp->GetLocalId(&ownAppId);
     NS_ENSURE_SUCCESS(rv, false);
     NS_ENSURE_TRUE(ownAppId != NO_APP_ID, false);
   }
 
   uint32_t containingAppId = NO_APP_ID;
   if (aAppFrameOwnerApp) {
-    nsresult rv = aOwnApp->GetLocalId(&containingAppId);
+    nsresult rv = aAppFrameOwnerApp->GetLocalId(&containingAppId);
     NS_ENSURE_SUCCESS(rv, false);
     NS_ENSURE_TRUE(containingAppId != NO_APP_ID, false);
   }
 
   mInitialized = true;
   mIsBrowser = false;
   mOwnAppId = ownAppId;
   mContainingAppId = containingAppId;
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -495,23 +495,21 @@ Promise::Constructor(const GlobalObject&
     promise->MaybeRejectInternal(cx, value);
   }
 
   return promise.forget();
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
-                 const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv)
+                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   // If a Promise was passed, just return it.
-  JS::Rooted<JS::Value> value(aCx, aValue.WasPassed() ? aValue.Value() :
-                                                        JS::UndefinedValue());
-  if (value.isObject()) {
-    JS::Rooted<JSObject*> valueObj(aCx, &value.toObject());
+  if (aValue.isObject()) {
+    JS::Rooted<JSObject*> valueObj(aCx, &aValue.toObject());
     Promise* nextPromise;
     nsresult rv = UNWRAP_OBJECT(Promise, valueObj, nextPromise);
 
     if (NS_SUCCEEDED(rv)) {
       nsRefPtr<Promise> addRefed = nextPromise;
       return addRefed.forget();
     }
   }
@@ -520,46 +518,44 @@ Promise::Resolve(const GlobalObject& aGl
   if (MOZ_LIKELY(NS_IsMainThread())) {
     window = do_QueryInterface(aGlobal.GetAsSupports());
     if (!window) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
   }
 
-  return Resolve(window, aCx, value, aRv);
+  return Resolve(window, aCx, aValue, aRv);
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Resolve(nsPIDOMWindow* aWindow, JSContext* aCx,
                  JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   // aWindow may be null.
   nsRefPtr<Promise> promise = new Promise(aWindow);
 
   promise->MaybeResolveInternal(aCx, aValue);
   return promise.forget();
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
-                const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv)
+                JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   nsCOMPtr<nsPIDOMWindow> window;
   if (MOZ_LIKELY(NS_IsMainThread())) {
     window = do_QueryInterface(aGlobal.GetAsSupports());
     if (!window) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
   }
 
-  return Reject(window, aCx,
-                aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue,
-                aRv);
+  return Reject(window, aCx, aValue, aRv);
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Reject(nsPIDOMWindow* aWindow, JSContext* aCx,
                 JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   // aWindow may be null.
   nsRefPtr<Promise> promise = new Promise(aWindow);
@@ -731,29 +727,29 @@ Promise::All(const GlobalObject& aGlobal
   }
 
   if (aIterable.Length() == 0) {
     JS::Rooted<JSObject*> empty(aCx, JS_NewArrayObject(aCx, 0));
     if (!empty) {
       aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
       return nullptr;
     }
-    Optional<JS::Handle<JS::Value>> optValue(aCx, JS::ObjectValue(*empty));
-    return Promise::Resolve(aGlobal, aCx, optValue, aRv);
+    JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*empty));
+    return Promise::Resolve(aGlobal, aCx, value, aRv);
   }
 
   nsRefPtr<Promise> promise = new Promise(window);
   nsRefPtr<CountdownHolder> holder =
     new CountdownHolder(aGlobal, promise, aIterable.Length());
 
   nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise);
 
   for (uint32_t i = 0; i < aIterable.Length(); ++i) {
-    Optional<JS::Handle<JS::Value>> optValue(aCx, aIterable.ElementAt(i));
-    nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, optValue, aRv);
+    JS::Rooted<JS::Value> value(aCx, aIterable.ElementAt(i));
+    nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, value, aRv);
 
     MOZ_ASSERT(!aRv.Failed());
 
     nsRefPtr<PromiseNativeHandler> resolveHandler =
       new AllResolveHandler(holder, i);
 
     nsRefPtr<PromiseCallback> resolveCb =
       new NativePromiseCallback(resolveHandler, Resolved);
@@ -778,18 +774,18 @@ Promise::Race(const GlobalObject& aGloba
     }
   }
 
   nsRefPtr<Promise> promise = new Promise(window);
   nsRefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(promise);
   nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(promise);
 
   for (uint32_t i = 0; i < aIterable.Length(); ++i) {
-    Optional<JS::Handle<JS::Value>> optValue(aCx, aIterable.ElementAt(i));
-    nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, optValue, aRv);
+    JS::Rooted<JS::Value> value(aCx, aIterable.ElementAt(i));
+    nsRefPtr<Promise> nextPromise = Promise::Resolve(aGlobal, aCx, value, aRv);
     // According to spec, Resolve can throw, but our implementation never does.
     // Well it does when window isn't passed on the main thread, but that is an
     // implementation detail which should never be reached since we are checking
     // for window above. Remove this when subclassing is supported.
     MOZ_ASSERT(!aRv.Failed());
     nextPromise->AppendCallbacks(resolveCb, rejectCb);
   }
 
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -61,25 +61,25 @@ public:
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   static already_AddRefed<Promise>
   Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
               ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Resolve(const GlobalObject& aGlobal, JSContext* aCx,
-          const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
+          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Resolve(nsPIDOMWindow* aWindow, JSContext* aCx,
           JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Reject(const GlobalObject& aGlobal, JSContext* aCx,
-         const Optional<JS::Handle<JS::Value>>& aValue, ErrorResult& aRv);
+         JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Reject(nsPIDOMWindow* aWindow, JSContext* aCx,
          JS::Handle<JS::Value> aValue, ErrorResult& aRv);
 
   already_AddRefed<Promise>
   Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
 
--- a/dom/webidl/HTMLCanvasElement.webidl
+++ b/dom/webidl/HTMLCanvasElement.webidl
@@ -21,21 +21,21 @@ interface HTMLCanvasElement : HTMLElemen
   [Pure, SetterThrows]
            attribute unsigned long height;
 
   [Throws]
   nsISupports? getContext(DOMString contextId, optional any contextOptions = null);
 
   [Throws]
   DOMString toDataURL(optional DOMString type = "",
-                      optional any encoderOptions);
+                      any encoderOptions);
   [Throws]
   void toBlob(FileCallback _callback,
               optional DOMString type = "",
-              optional any encoderOptions);
+              any encoderOptions);
 };
 
 // Mozilla specific bits
 partial interface HTMLCanvasElement {
   [Pure, SetterThrows]
            attribute boolean mozOpaque;
   [Throws]
   File mozGetAsFile(DOMString name, optional DOMString? type = null);
--- a/dom/webidl/IDBCursor.webidl
+++ b/dom/webidl/IDBCursor.webidl
@@ -27,17 +27,17 @@ interface IDBCursor {
 
     [Throws]
     IDBRequest update (any value);
 
     [Throws]
     void       advance ([EnforceRange] unsigned long count);
 
     [Throws]
-    void       continue (optional any key);
+    void       continue (any key);
 
     [Throws]
     IDBRequest delete ();
 };
 
 interface IDBCursorWithValue : IDBCursor {
     [Throws]
     readonly    attribute any value;
--- a/dom/webidl/IDBIndex.webidl
+++ b/dom/webidl/IDBIndex.webidl
@@ -18,32 +18,32 @@ interface IDBIndex {
 
     [Throws]
     readonly    attribute any            keyPath;
 
     readonly    attribute boolean        multiEntry;
     readonly    attribute boolean        unique;
 
     [Throws]
-    IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openCursor (any range, optional IDBCursorDirection direction = "next");
 
     [Throws]
-    IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openKeyCursor (any range, optional IDBCursorDirection direction = "next");
 
     [Throws]
     IDBRequest get (any key);
 
     [Throws]
     IDBRequest getKey (any key);
 
     [Throws]
-    IDBRequest count (optional any key);
+    IDBRequest count (any key);
 };
 
 partial interface IDBIndex {
     readonly attribute DOMString storeName;
 
     [Throws]
-    IDBRequest mozGetAll (optional any key, optional unsigned long limit);
+    IDBRequest mozGetAll (any key, optional unsigned long limit);
 
     [Throws]
-    IDBRequest mozGetAllKeys (optional any key, optional unsigned long limit);
+    IDBRequest mozGetAllKeys (any key, optional unsigned long limit);
 };
--- a/dom/webidl/IDBObjectStore.webidl
+++ b/dom/webidl/IDBObjectStore.webidl
@@ -20,32 +20,32 @@ interface IDBObjectStore {
     readonly    attribute any            keyPath;
 
     [Throws]
     readonly    attribute DOMStringList  indexNames;
     readonly    attribute IDBTransaction transaction;
     readonly    attribute boolean        autoIncrement;
 
     [Throws]
-    IDBRequest put (any value, optional any key);
+    IDBRequest put (any value, any key);
 
     [Throws]
-    IDBRequest add (any value, optional any key);
+    IDBRequest add (any value, any key);
 
     [Throws]
     IDBRequest delete (any key);
 
     [Throws]
     IDBRequest get (any key);
 
     [Throws]
     IDBRequest clear ();
 
     [Throws]
-    IDBRequest openCursor (optional any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openCursor (any range, optional IDBCursorDirection direction = "next");
 
     // Bug 899972
     // IDBIndex   createIndex (DOMString name, (DOMString or sequence<DOMString>) keyPath, optional IDBIndexParameters optionalParameters);
 
     [Throws]
     IDBIndex   createIndex (DOMString name, DOMString keyPath, optional IDBIndexParameters optionalParameters);
 
     [Throws]
@@ -53,25 +53,25 @@ interface IDBObjectStore {
 
     [Throws]
     IDBIndex   index (DOMString name);
 
     [Throws]
     void       deleteIndex (DOMString indexName);
 
     [Throws]
-    IDBRequest count (optional any key);
+    IDBRequest count (any key);
 };
 
 partial interface IDBObjectStore {
     // Success fires IDBTransactionEvent, result == array of values for given keys
     [Throws]
-    IDBRequest mozGetAll (optional any key, optional unsigned long limit);
+    IDBRequest mozGetAll (any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest getAll (optional any key, optional unsigned long limit);
+    IDBRequest getAll (any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest getAllKeys (optional any key, optional unsigned long limit);
+    IDBRequest getAllKeys (any key, optional unsigned long limit);
 
     [Pref="dom.indexedDB.experimental", Throws]
-    IDBRequest openKeyCursor (optional any range, optional IDBCursorDirection direction = "next");
+    IDBRequest openKeyCursor (any range, optional IDBCursorDirection direction = "next");
 };
--- a/dom/webidl/Promise.webidl
+++ b/dom/webidl/Promise.webidl
@@ -21,19 +21,19 @@ interface Promise {
   // TODO bug 875289 - static Promise fulfill(any value);
 
   // Disable the static methods when the interface object is supposed to be
   // disabled, just in case some code decides to walk over to .constructor from
   // the proto of a promise object or someone screws up and manages to create a
   // Promise object in this scope without having resolved the interface object
   // first.
   [NewObject, Throws]
-  static Promise resolve(optional any value);
+  static Promise resolve(any value);
   [NewObject, Throws]
-  static Promise reject(optional any value);
+  static Promise reject(any value);
 
   // The [TreatNonCallableAsNull] annotation is required since then() should do
   // nothing instead of throwing errors when non-callable arguments are passed.
   [NewObject]
   Promise then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
                [TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
 
   [NewObject]
--- a/dom/webidl/RTCStatsReport.webidl
+++ b/dom/webidl/RTCStatsReport.webidl
@@ -141,12 +141,12 @@ dictionary RTCStatsReportInternal {
 
 [Pref="media.peerconnection.enabled",
 // TODO: Use MapClass here once it's available (Bug 928114)
 // MapClass(DOMString, object)
  JSImplementation="@mozilla.org/dom/rtcstatsreport;1"]
 interface RTCStatsReport {
   [ChromeOnly]
   readonly attribute DOMString mozPcid;
-  void forEach(RTCStatsReportCallback callbackFn, optional any thisArg);
+  void forEach(RTCStatsReportCallback callbackFn, any thisArg);
   object get(DOMString key);
   boolean has(DOMString key);
 };
--- a/dom/webidl/TestInterfaceJS.webidl
+++ b/dom/webidl/TestInterfaceJS.webidl
@@ -1,17 +1,17 @@
 /* -*- Mode: IDL; tab-width: 2; 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/.
  */
 
 [JSImplementation="@mozilla.org/dom/test-interface-js;1",
  Pref="dom.expose_test_interfaces",
- Constructor(optional any anyArg, optional object objectArg)]
+ Constructor(any anyArg, optional object objectArg)]
 interface TestInterfaceJS {
   readonly attribute any anyArg;
   readonly attribute object objectArg;
   attribute any anyAttr;
   attribute object objectAttr;
   any pingPongAny(any arg);
   object pingPongObject(any obj);
 
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -69,33 +69,33 @@ typedef any Transferable;
   [Throws] readonly attribute ApplicationCache applicationCache;
 
   // user prompts
   [Throws] void alert(optional DOMString message = "");
   [Throws] boolean confirm(optional DOMString message = "");
   [Throws] DOMString? prompt(optional DOMString message = "", optional DOMString default = "");
   [Throws] void print();
   //[Throws] any showModalDialog(DOMString url, optional any argument);
-  [Throws] any showModalDialog(DOMString url, optional any argument, optional DOMString options = "");
+  [Throws] any showModalDialog(DOMString url, any argument, optional DOMString options = "");
 
   [Throws, CrossOriginCallable] void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
 
   // also has obsolete members
 };
 Window implements GlobalEventHandlers;
 Window implements WindowEventHandlers;
 
 // http://www.whatwg.org/specs/web-apps/current-work/
 [NoInterfaceObject]
 interface WindowTimers {
   [Throws] long setTimeout(Function handler, optional long timeout = 0, any... arguments);
-  [Throws] long setTimeout(DOMString handler, optional long timeout = 0);
+  [Throws] long setTimeout(DOMString handler, optional long timeout = 0, any... unused);
   [Throws] void clearTimeout(long handle);
   [Throws] long setInterval(Function handler, optional long timeout, any... arguments);
-  [Throws] long setInterval(DOMString handler, optional long timeout);
+  [Throws] long setInterval(DOMString handler, optional long timeout, any... unused);
   [Throws] void clearInterval(long handle);
 };
 Window implements WindowTimers;
 
 // http://www.whatwg.org/specs/web-apps/current-work/
 [NoInterfaceObject]
 interface WindowBase64 {
   [Throws] DOMString btoa(DOMString btoa);
--- a/dom/webidl/WorkerConsole.webidl
+++ b/dom/webidl/WorkerConsole.webidl
@@ -7,22 +7,22 @@
 interface WorkerConsole {
   void log(any... data);
   void info(any... data);
   void warn(any... data);
   void error(any... data);
   void _exception(any... data);
   void debug(any... data);
   void trace();
-  void dir(optional any data);
+  void dir(any data);
   void group(any... data);
   void groupCollapsed(any... data);
   void groupEnd(any... data);
-  void time(optional any time);
-  void timeEnd(optional any time);
+  void time(any time);
+  void timeEnd(any time);
   void profile(any... data);
   void profileEnd(any... data);
   void assert(boolean condition, any... data);
   void ___noSuchMethod__();
 };
 
 // This dictionary is used internally to send the stack trace from the worker to
 // the main thread Console API implementation.
--- a/dom/workers/Console.cpp
+++ b/dom/workers/Console.cpp
@@ -336,20 +336,20 @@ private:
 
   const char* mMethod;
   JSAutoStructuredCloneBuffer mArguments;
   nsTArray<ConsoleStackData> mStackData;
 
   nsTArray<nsString> mStrings;
 };
 
-class TeardownRunnable : public nsRunnable
+class TeardownConsoleRunnable : public nsRunnable
 {
 public:
-  TeardownRunnable(ConsoleProxy* aProxy)
+  TeardownConsoleRunnable(ConsoleProxy* aProxy)
     : mProxy(aProxy)
   {
   }
 
   NS_IMETHOD Run()
   {
     AssertIsOnMainThread();
 
@@ -387,17 +387,18 @@ WorkerConsole::WorkerConsole()
   SetIsDOMBinding();
 }
 
 WorkerConsole::~WorkerConsole()
 {
   MOZ_COUNT_DTOR(WorkerConsole);
 
   if (mProxy) {
-    nsRefPtr<TeardownRunnable> runnable = new TeardownRunnable(mProxy);
+    nsRefPtr<TeardownConsoleRunnable> runnable =
+      new TeardownConsoleRunnable(mProxy);
     mProxy = nullptr;
 
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       NS_ERROR("Failed to dispatch teardown runnable!");
     }
   }
 }
 
@@ -486,56 +487,54 @@ void
 WorkerConsole::Trace(JSContext* aCx)
 {
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
   Method(aCx, "trace", data, DEFAULT_MAX_STACKTRACE_DEPTH);
 }
 
 void
-WorkerConsole::Dir(JSContext* aCx,
-                   const Optional<JS::Handle<JS::Value>>& aValue)
+WorkerConsole::Dir(JSContext* aCx, JS::Handle<JS::Value> aValue)
 {
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
-  if (aValue.WasPassed()) {
-    data.AppendElement(aValue.Value());
+  if (!aValue.isUndefined()) {
+    data.AppendElement(aValue);
   }
 
   Method(aCx, "dir", data, 1);
 }
 
 METHOD(Group, "group")
 METHOD(GroupCollapsed, "groupCollapsed")
 METHOD(GroupEnd, "groupEnd")
 
 void
-WorkerConsole::Time(JSContext* aCx,
-                    const Optional<JS::Handle<JS::Value>>& aTimer)
+WorkerConsole::Time(JSContext* aCx, JS::Handle<JS::Value> aTimer)
 {
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
-  if (aTimer.WasPassed()) {
-    data.AppendElement(aTimer.Value());
+  if (!aTimer.isUndefined()) {
+    data.AppendElement(aTimer);
   }
 
   Method(aCx, "time", data, 1);
 }
 
 void
 WorkerConsole::TimeEnd(JSContext* aCx,
-                       const Optional<JS::Handle<JS::Value>>& aTimer)
+                       JS::Handle<JS::Value> aTimer)
 {
   Sequence<JS::Value> data;
   SequenceRooter<JS::Value> rooter(aCx, &data);
 
-  if (aTimer.WasPassed()) {
-    data.AppendElement(aTimer.Value());
+  if (!aTimer.isUndefined()) {
+    data.AppendElement(aTimer);
   }
 
   Method(aCx, "timeEnd", data, 1);
 }
 
 METHOD(Profile, "profile")
 METHOD(ProfileEnd, "profileEnd")
 
--- a/dom/workers/Console.h
+++ b/dom/workers/Console.h
@@ -65,32 +65,32 @@ public:
 
   void
   Debug(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
   Trace(JSContext* aCx);
 
   void
-  Dir(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aValue);
+  Dir(JSContext* aCx, JS::Handle<JS::Value> aValue);
 
   void
   Group(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
   GroupCollapsed(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
   GroupEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
-  Time(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aTimer);
+  Time(JSContext* aCx, JS::Handle<JS::Value> aTimer);
 
   void
-  TimeEnd(JSContext* aCx, const Optional<JS::Handle<JS::Value>>& aTimer);
+  TimeEnd(JSContext* aCx, JS::Handle<JS::Value> aTimer);
 
   void
   Profile(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
   ProfileEnd(JSContext* aCx, const Sequence<JS::Value>& aData);
 
   void
--- a/dom/workers/RuntimeService.cpp
+++ b/dom/workers/RuntimeService.cpp
@@ -838,21 +838,23 @@ CreateJSContextForWorker(WorkerPrivate* 
   return workerCx;
 }
 
 class WorkerJSRuntime : public mozilla::CycleCollectedJSRuntime
 {
 public:
   // The heap size passed here doesn't matter, we will change it later in the
   // call to JS_SetGCParameter inside CreateJSContextForWorker.
-  WorkerJSRuntime(WorkerPrivate* aWorkerPrivate)
-  : CycleCollectedJSRuntime(WORKER_DEFAULT_RUNTIME_HEAPSIZE,
-                            JS_NO_HELPER_THREADS),
+  WorkerJSRuntime(JSRuntime* aParentRuntime, WorkerPrivate* aWorkerPrivate)
+    : CycleCollectedJSRuntime(aParentRuntime,
+                              WORKER_DEFAULT_RUNTIME_HEAPSIZE,
+                              JS_NO_HELPER_THREADS),
     mWorkerPrivate(aWorkerPrivate)
-  { }
+  {
+  }
 
   ~WorkerJSRuntime()
   {
     auto rtPrivate = static_cast<WorkerThreadRuntimePrivate*>(JS_GetRuntimePrivate(Runtime()));
     delete rtPrivate;
     JS_SetRuntimePrivate(Runtime(), nullptr);
 
     // The worker global should be unrooted and the shutdown cycle collection
@@ -907,16 +909,17 @@ public:
 private:
   WorkerPrivate* mWorkerPrivate;
 };
 
 class WorkerThreadPrimaryRunnable MOZ_FINAL : public nsRunnable
 {
   WorkerPrivate* mWorkerPrivate;
   nsRefPtr<RuntimeService::WorkerThread> mThread;
+  JSRuntime* mParentRuntime;
 
   class FinishedRunnable MOZ_FINAL : public nsRunnable
   {
     nsRefPtr<RuntimeService::WorkerThread> mThread;
 
   public:
     FinishedRunnable(already_AddRefed<RuntimeService::WorkerThread> aThread)
     : mThread(aThread)
@@ -930,18 +933,19 @@ class WorkerThreadPrimaryRunnable MOZ_FI
     ~FinishedRunnable()
     { }
 
     NS_DECL_NSIRUNNABLE
   };
 
 public:
   WorkerThreadPrimaryRunnable(WorkerPrivate* aWorkerPrivate,
-                              RuntimeService::WorkerThread* aThread)
-  : mWorkerPrivate(aWorkerPrivate), mThread(aThread)
+                              RuntimeService::WorkerThread* aThread,
+                              JSRuntime* aParentRuntime)
+  : mWorkerPrivate(aWorkerPrivate), mThread(aThread), mParentRuntime(aParentRuntime)
   {
     MOZ_ASSERT(aWorkerPrivate);
     MOZ_ASSERT(aThread);
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
 private:
@@ -1524,17 +1528,17 @@ RuntimeService::ScheduleWorker(JSContext
                      nsISupportsPriority::PRIORITY_NORMAL :
                      nsISupportsPriority::PRIORITY_LOW;
 
   if (NS_FAILED(thread->SetPriority(priority))) {
     NS_WARNING("Could not set the thread's priority!");
   }
 
   nsCOMPtr<nsIRunnable> runnable =
-    new WorkerThreadPrimaryRunnable(aWorkerPrivate, thread);
+    new WorkerThreadPrimaryRunnable(aWorkerPrivate, thread, JS_GetParentRuntime(aCx));
   if (NS_FAILED(thread->Dispatch(runnable, NS_DISPATCH_NORMAL))) {
     UnregisterWorker(aCx, aWorkerPrivate);
     JS_ReportError(aCx, "Could not dispatch to thread!");
     return false;
   }
 
 #ifdef DEBUG
   thread->SetAcceptingNonWorkerRunnables(false);
@@ -2530,17 +2534,17 @@ WorkerThreadPrimaryRunnable::Run()
 
   mThread->SetWorker(mWorkerPrivate);
 
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   {
     nsCycleCollector_startup();
 
-    WorkerJSRuntime runtime(mWorkerPrivate);
+    WorkerJSRuntime runtime(mParentRuntime, mWorkerPrivate);
     JSRuntime* rt = runtime.Runtime();
 
     JSContext* cx = CreateJSContextForWorker(mWorkerPrivate, rt);
     if (!cx) {
       // XXX need to fire an error at parent.
       NS_ERROR("Failed to create runtime and context!");
       return NS_ERROR_FAILURE;
     }
--- a/dom/workers/URL.cpp
+++ b/dom/workers/URL.cpp
@@ -307,20 +307,20 @@ public:
 
   URLProxy*
   GetURLProxy()
   {
     return mRetval;
   }
 };
 
-class TeardownRunnable : public nsRunnable
+class TeardownURLRunnable : public nsRunnable
 {
 public:
-  TeardownRunnable(URLProxy* aURLProxy)
+  TeardownURLRunnable(URLProxy* aURLProxy)
     : mURLProxy(aURLProxy)
   {
   }
 
   NS_IMETHOD Run()
   {
     AssertIsOnMainThread();
 
@@ -571,17 +571,18 @@ URL::URL(WorkerPrivate* aWorkerPrivate, 
   MOZ_COUNT_CTOR(workers::URL);
 }
 
 URL::~URL()
 {
   MOZ_COUNT_DTOR(workers::URL);
 
   if (mURLProxy) {
-    nsRefPtr<TeardownRunnable> runnable = new TeardownRunnable(mURLProxy);
+    nsRefPtr<TeardownURLRunnable> runnable =
+      new TeardownURLRunnable(mURLProxy);
     mURLProxy = nullptr;
 
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       NS_ERROR("Failed to dispatch teardown runnable!");
     }
   }
 }
 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -175,18 +175,20 @@ WorkerGlobalScope::SetTimeout(JSContext*
                               ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
   return mWorkerPrivate->SetTimeout(aCx, &aHandler, EmptyString(), aTimeout,
                                     aArguments, false, aRv);
 }
 
 int32_t
-WorkerGlobalScope::SetTimeout(const nsAString& aHandler,
+WorkerGlobalScope::SetTimeout(JSContext* /* unused */,
+                              const nsAString& aHandler,
                               const int32_t aTimeout,
+                              const Sequence<JS::Value>& /* unused */,
                               ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
   Sequence<JS::Value> dummy;
   return mWorkerPrivate->SetTimeout(GetCurrentThreadJSContext(), nullptr,
                                     aHandler, aTimeout, dummy, false, aRv);
 }
 
@@ -208,18 +210,20 @@ WorkerGlobalScope::SetInterval(JSContext
 
   int32_t timeout = aTimeout.WasPassed() ? aTimeout.Value() : 0;
 
   return mWorkerPrivate->SetTimeout(aCx, &aHandler, EmptyString(), timeout,
                                     aArguments, !!timeout, aRv);
 }
 
 int32_t
-WorkerGlobalScope::SetInterval(const nsAString& aHandler,
+WorkerGlobalScope::SetInterval(JSContext* /* unused */,
+                               const nsAString& aHandler,
                                const Optional<int32_t>& aTimeout,
+                               const Sequence<JS::Value>& /* unused */,
                                ErrorResult& aRv)
 {
   mWorkerPrivate->AssertIsOnWorkerThread();
 
   Sequence<JS::Value> dummy;
 
   int32_t timeout = aTimeout.WasPassed() ? aTimeout.Value() : 0;
 
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -83,27 +83,29 @@ public:
   void
   ImportScripts(JSContext* aCx, const Sequence<nsString>& aScriptURLs,
                 ErrorResult& aRv);
 
   int32_t
   SetTimeout(JSContext* aCx, Function& aHandler, const int32_t aTimeout,
              const Sequence<JS::Value>& aArguments, ErrorResult& aRv);
   int32_t
-  SetTimeout(const nsAString& aHandler, const int32_t aTimeout,
+  SetTimeout(JSContext* /* unused */, const nsAString& aHandler,
+             const int32_t aTimeout, const Sequence<JS::Value>& /* unused */,
              ErrorResult& aRv);
   void
   ClearTimeout(int32_t aHandle, ErrorResult& aRv);
   int32_t
   SetInterval(JSContext* aCx, Function& aHandler,
               const Optional<int32_t>& aTimeout,
               const Sequence<JS::Value>& aArguments, ErrorResult& aRv);
   int32_t
-  SetInterval(const nsAString& aHandler, const Optional<int32_t>& aTimeout,
-              ErrorResult& aRv);
+  SetInterval(JSContext* /* unused */, const nsAString& aHandler,
+              const Optional<int32_t>& aTimeout,
+              const Sequence<JS::Value>& /* unused */, ErrorResult& aRv);
   void
   ClearInterval(int32_t aHandle, ErrorResult& aRv);
 
   void
   Atob(const nsAString& aAtob, nsAString& aOutput, ErrorResult& aRv) const;
   void
   Btoa(const nsAString& aBtoa, nsAString& aOutput, ErrorResult& aRv) const;
 
--- a/embedding/tests/winEmbed/Makefile.in
+++ b/embedding/tests/winEmbed/Makefile.in
@@ -23,17 +23,17 @@
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 # DEALINGS IN THE SOFTWARE.
 #
 # Contributor(s):
 #
 # ***** END LICENSE BLOCK *****
 
 LIBS = \
-	$(DEPTH)/profile/dirserviceprovider/standalone/$(LIB_PREFIX)profdirserviceprovidersa_s.$(LIB_SUFFIX) \
+	$(DEPTH)/profile/dirserviceprovider/src/$(LIB_PREFIX)profdirserviceprovidersa_s.$(LIB_SUFFIX) \
 	$(XPCOM_STANDALONE_GLUE_LDOPTS) \
 	$(NULL)
 
 STL_FLAGS=
 
 OS_LIBS		+= $(call EXPAND_LIBNAME,ole32 comdlg32 shell32 version)
 
 include $(topsrcdir)/config/rules.mk
--- a/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
+++ b/extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
@@ -9476,146 +9476,149 @@ 38891a44715,44716
 38951c44776
 < proprietorship/M
 ---
 > proprietorship/MS
 39039a44865
 > provender/M
 39564a45391
 > quinoa
-40036a45864
+39873a45701,45702
+> rasterization/M
+> rasterize/SGDR
+40036a45866
 > recency
-40140a45969
+40140a45971
 > recurse/DGSV
-40141a45971
+40141a45973
 > recuse/DGS
-40208a46039
+40208a46041
 > refactor/SMDG
-40244d46074
+40244d46076
 < reflexion/SM
-40659d46488
+40659d46490
 < resizing
-40829c46658
+40829c46660
 < reverie/M
 ---
 > reverie/MS
-41415a47245
+41415a47247
 > sabre/MS
-41914c47744
+41914c47746
 < schnaps's
 ---
 > schnaps/M
-41949c47779
+41949c47781
 < schrod's
 ---
 > schrod/SM
-41998a47829
+41998a47831
 > scot-free
-42883,42885c48714
+42883,42885c48716
 < shit's
 < shit/S!
 < shite/S!
 ---
 > shit/MS!
-42887,42888c48716,48717
+42887,42888c48718,48719
 < shithead/S!
 < shitload/!
 ---
 > shithead/MS!
 > shitload/MS!
-42891c48720
+42891c48722
 < shitty/RT!
 ---
 > shitty/TR!
-42976a48806
+42976a48808
 > should've
-43008c48838
+43008c48840
 < showtime
 ---
 > showtime/MS
-43328c49158
+43328c49160
 < size/MGBDRS
 ---
 > size/AMGBDRS
-43724,43726c49554
+43724,43726c49556
 < smoulder's
 < smouldered
 < smoulders
 ---
 > smoulder/GSMD
-44062c49890
+44062c49892
 < sonofabitch
 ---
 > sonofabitch/!
-44346a50175
+44346a50177
 > spelled
-44348a50178
+44348a50180
 > spelt
-44371a50202
+44371a50204
 > spick/S!
-44383c50214
+44383c50216
 < spik/S
 ---
 > spik/S!
-46106a51938
+46106a51940
 > syllabi
-46160c51992
+46160c51994
 < synch/GMD
 ---
 > synch/GMDS
-46167d51998
+46167d52000
 < synchs
-46203,46204c52034,52035
+46203,46204c52036,52037
 < sysadmin/S
 < sysop/S
 ---
 > sysadmin/MS
 > sysop/MS
-46752a52584
+46752a52586
 > terabit/MS
-46753a52586,52587
+46753a52588,52589
 > terahertz/M
 > terapixel/MS
-46817a52652
+46817a52654
 > testcase/MS
-46831a52667
+46831a52669
 > testsuite/MS
-46925a52762
+46925a52764
 > theremin/MS
-47455c53292
+47455c53294
 < toolbar
 ---
 > toolbar/MS
-47755a53593
+47755a53595
 > transfect/DSMG
-47774a53613,53614
+47774a53615,53616
 > transgenderism
 > transgene/MS
-47951c53791
+47951c53793
 < triage/M
 ---
 > triage/MG
-48869a54710
+48869a54712
 > unlikeable
-49211c55052
+49211c55054
 < vagina/M
 ---
 > vagina/MS
-49368,49369c55209
+49368,49369c55211
 < velour's
 < velours's
 ---
 > velour/MS
-49478a55319
+49478a55321
 > vertices
-50148a55990
+50148a55992
 > weaponize/DSG
-50260,50261d56101
+50260,50261d56103
 < werwolf/M
 < werwolves
-50728c56568
+50728c56570
 < women
 ---
 > women/M
-50794c56634
+50794c56636
 < wop/S!
 ---
 > wop/MS!
--- a/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
+++ b/extensions/spellcheck/locales/en-US/hunspell/en-US.dic
@@ -1,9 +1,9 @@
-57456
+57458
 0/nm
 0th/pt
 1/n1
 1st/p
 1th/tc
 2/nm
 2nd/p
 2th/tc
@@ -46019,16 +46019,18 @@ rarity/SM
 rascal/SMY
 rash/ZTMRSYP
 rasher/M
 rashness/M
 rasp/GMDRS
 raspberry/SM
 raspy/RT
 raster
+rasterization/M
+rasterize/SGDR
 rat/SM
 ratatouille/M
 ratbag/S
 ratchet/GMDS
 rate/BJXMZGNDRS
 rateable
 rated/U
 ratepayer/S
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -333,16 +333,17 @@ Factory::CreateDrawTargetForData(Backend
   switch (aBackend) {
 #ifdef USE_SKIA
   case BackendType::SKIA:
     {
       RefPtr<DrawTargetSkia> newTarget;
       newTarget = new DrawTargetSkia();
       newTarget->Init(aData, aSize, aStride, aFormat);
       retVal = newTarget;
+      break;
     }
 #endif
 #ifdef XP_MACOSX
   case BackendType::COREGRAPHICS:
     {
       RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
       if (newTarget->Init(aBackend, aData, aSize, aStride, aFormat))
         return newTarget;
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -71,30 +71,34 @@ CanvasClient2D::Update(gfx::IntSize aSiz
 
     bufferCreated = true;
   }
 
   if (!mBuffer->Lock(OPEN_WRITE_ONLY)) {
     return;
   }
 
-  RefPtr<DrawTarget> drawTarget =
-    mBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget();
-  if (drawTarget) {
-    aLayer->UpdateTarget(drawTarget);
+  bool updated = false;
+  {
+    // Restrict drawTarget to a scope so that terminates before Unlock.
+    RefPtr<DrawTarget> drawTarget =
+      mBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget();
+    if (drawTarget) {
+      aLayer->UpdateTarget(drawTarget);
+      updated = true;
+    }
   }
-
   mBuffer->Unlock();
 
   if (bufferCreated && !AddTextureClient(mBuffer)) {
     mBuffer = nullptr;
     return;
   }
 
-  if (drawTarget) {
+  if (updated) {
     GetForwarder()->UpdatedTexture(this, mBuffer, nullptr);
     GetForwarder()->UseTexture(this, mBuffer);
   }
 }
 
 TemporaryRef<BufferTextureClient>
 CanvasClient2D::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
 {
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -545,41 +545,43 @@ CompositorD3D11::DrawQuad(const gfx::Rec
   scissor.bottom = aClipRect.YMost();
   mContext->RSSetScissorRects(1, &scissor);
   mContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
   mContext->VSSetShader(mAttachments->mVSQuadShader[maskType], nullptr, 0);
 
 
   switch (aEffectChain.mPrimaryEffect->mType) {
   case EFFECT_SOLID_COLOR: {
+      SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, SurfaceFormat::UNKNOWN);
+
       Color color =
         static_cast<EffectSolidColor*>(aEffectChain.mPrimaryEffect.get())->mColor;
       mPSConstants.layerColor[0] = color.r * color.a * aOpacity;
       mPSConstants.layerColor[1] = color.g * color.a * aOpacity;
       mPSConstants.layerColor[2] = color.b * color.a * aOpacity;
       mPSConstants.layerColor[3] = color.a * aOpacity;
     }
     break;
   case EFFECT_RGB:
   case EFFECT_RENDER_TARGET:
     {
       TexturedEffect* texturedEffect =
         static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
 
-      SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, texturedEffect->mTexture->GetFormat());
-
       mVSConstants.textureCoords = texturedEffect->mTextureCoords;
 
       TextureSourceD3D11* source = texturedEffect->mTexture->AsSourceD3D11();
 
       if (!source) {
         NS_WARNING("Missing texture source!");
         return;
       }
 
+      SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, texturedEffect->mTexture->GetFormat());
+
       RefPtr<ID3D11ShaderResourceView> view;
       mDevice->CreateShaderResourceView(source->GetD3D11Texture(), nullptr, byRef(view));
 
       ID3D11ShaderResourceView* srView = view;
       mContext->PSSetShaderResources(0, 1, &srView);
 
       if (!texturedEffect->mPremultiplied) {
         mContext->OMSetBlendState(mAttachments->mNonPremulBlendState, sBlendFactor, 0xFFFFFFFF);
@@ -588,29 +590,30 @@ CompositorD3D11::DrawQuad(const gfx::Rec
 
       SetSamplerForFilter(texturedEffect->mFilter);
     }
     break;
   case EFFECT_YCBCR: {
       EffectYCbCr* ycbcrEffect =
         static_cast<EffectYCbCr*>(aEffectChain.mPrimaryEffect.get());
 
-      SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, ycbcrEffect->mTexture->GetFormat());
       SetSamplerForFilter(Filter::LINEAR);
 
       mVSConstants.textureCoords = ycbcrEffect->mTextureCoords;
 
       const int Y = 0, Cb = 1, Cr = 2;
       TextureSource* source = ycbcrEffect->mTexture;
 
       if (!source) {
         NS_WARNING("No texture to composite");
         return;
       }
 
+      SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, ycbcrEffect->mTexture->GetFormat());
+
       if (!source->GetSubSource(Y) || !source->GetSubSource(Cb) || !source->GetSubSource(Cr)) {
         // This can happen if we failed to upload the textures, most likely
         // because of unsupported dimensions (we don't tile YCbCr textures).
         return;
       }
 
       TextureSourceD3D11* sourceY  = source->GetSubSource(Y)->AsSourceD3D11();
       TextureSourceD3D11* sourceCb = source->GetSubSource(Cb)->AsSourceD3D11();
@@ -630,25 +633,26 @@ CompositorD3D11::DrawQuad(const gfx::Rec
     break;
   case EFFECT_COMPONENT_ALPHA:
     {
       MOZ_ASSERT(gfxPlatform::ComponentAlphaEnabled());
       MOZ_ASSERT(mAttachments->mComponentBlendState);
       EffectComponentAlpha* effectComponentAlpha =
         static_cast<EffectComponentAlpha*>(aEffectChain.mPrimaryEffect.get());
 
-      SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, effectComponentAlpha->mTexture->GetFormat());
       TextureSourceD3D11* sourceOnWhite = effectComponentAlpha->mOnWhite->AsSourceD3D11();
       TextureSourceD3D11* sourceOnBlack = effectComponentAlpha->mOnBlack->AsSourceD3D11();
 
       if (!sourceOnWhite || !sourceOnBlack) {
         NS_WARNING("Missing texture source(s)!");
         return;
       }
 
+      SetPSForEffect(aEffectChain.mPrimaryEffect, maskType, effectComponentAlpha->mOnWhite->GetFormat());
+
       SetSamplerForFilter(effectComponentAlpha->mFilter);
 
       mVSConstants.textureCoords = effectComponentAlpha->mTextureCoords;
       RefPtr<ID3D11ShaderResourceView> views[2];
       mDevice->CreateShaderResourceView(sourceOnBlack->GetD3D11Texture(), nullptr, byRef(views[0]));
       mDevice->CreateShaderResourceView(sourceOnWhite->GetD3D11Texture(), nullptr, byRef(views[1]));
 
       ID3D11ShaderResourceView* srViews[2] = { views[0], views[1] };
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -286,16 +286,26 @@ GrallocBufferActor::Create(const gfx::In
   uint32_t format = aFormat;
   uint32_t usage = aUsage;
 
   if (format == 0 || usage == 0) {
     printf_stderr("GrallocBufferActor::Create -- format and usage must be non-zero");
     return actor;
   }
 
+  // If the requested size is too big (i.e. exceeds the commonly used max GL texture size)
+  // then we risk OOMing the parent process. It's better to just deny the allocation and
+  // kill the child process, which is what the following code does.
+  // TODO: actually use GL_MAX_TEXTURE_SIZE instead of hardcoding 4096
+  if (aSize.width > 4096 || aSize.height > 4096) {
+    printf_stderr("GrallocBufferActor::Create -- requested gralloc buffer is too big. Killing child instead.");
+    delete actor;
+    return nullptr;
+  }
+
   sp<GraphicBuffer> buffer(new GraphicBuffer(aSize.width, aSize.height, format, usage));
   if (buffer->initCheck() != OK)
     return actor;
 
   size_t bpp = BytesPerPixelForPixelFormat(format);
   actor->mAllocBytes = aSize.width * aSize.height * bpp;
   GrallocReporter::sAmount += actor->mAllocBytes;
 
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
@@ -104,22 +104,25 @@ SharedPlanarYCbCrImage::SetData(const Pl
     Data data = aData;
     if (!Allocate(data)) {
       NS_WARNING("SharedPlanarYCbCrImage::SetData failed to allocate");
       return;
     }
   }
 
   MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr());
-
+  if (!mTextureClient->Lock(OPEN_WRITE_ONLY)) {
+    MOZ_ASSERT(false, "Failed to lock the texture.");
+    return;
+  }
+  TextureClientAutoUnlock unlock(mTextureClient);
   if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) {
     MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
     return;
   }
-
   // do not set mBuffer like in PlanarYCbCrImage because the later
   // will try to manage this memory without knowing it belongs to a
   // shmem.
   mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize,
                                                                mData.mCbCrSize);
   mSize = mData.mPicSize;
 
   YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer());
--- a/gfx/tests/gtest/TestTextures.cpp
+++ b/gfx/tests/gtest/TestTextures.cpp
@@ -103,23 +103,23 @@ void AssertYCbCrSurfacesEqual(PlanarYCbC
 void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) {
 
   // client allocation
   ASSERT_TRUE(texture->AsTextureClientSurface() != nullptr);
   TextureClientSurface* client = texture->AsTextureClientSurface();
   client->AllocateForSurface(ToIntSize(surface->GetSize()));
   ASSERT_TRUE(texture->IsAllocated());
 
+  ASSERT_TRUE(texture->Lock(OPEN_READ_WRITE));
   // client painting
   client->UpdateSurface(surface);
 
   nsRefPtr<gfxASurface> aSurface = client->GetAsSurface();
   nsRefPtr<gfxImageSurface> clientSurface = aSurface->GetAsImageSurface();
 
-  ASSERT_TRUE(texture->Lock(OPEN_READ_ONLY));
   AssertSurfacesEqual(surface, clientSurface);
   texture->Unlock();
 
   // client serialization
   SurfaceDescriptor descriptor;
   ASSERT_TRUE(texture->ToSurfaceDescriptor(descriptor));
 
   ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
@@ -150,20 +150,19 @@ void TestTextureClientYCbCr(TextureClien
   // client allocation
   ASSERT_TRUE(client->AsTextureClientYCbCr() != nullptr);
   TextureClientYCbCr* texture = client->AsTextureClientYCbCr();
   texture->AllocateForYCbCr(ycbcrData.mYSize,
                             ycbcrData.mCbCrSize,
                             ycbcrData.mStereoMode);
   ASSERT_TRUE(client->IsAllocated());
 
+  ASSERT_TRUE(client->Lock(OPEN_READ_WRITE));
   // client painting
   texture->UpdateYCbCr(ycbcrData);
-
-  ASSERT_TRUE(client->Lock(OPEN_READ_ONLY));
   client->Unlock();
 
   // client serialization
   SurfaceDescriptor descriptor;
   ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));
 
   ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
 
@@ -171,23 +170,21 @@ void TestTextureClientYCbCr(TextureClien
   RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr,
                                                                         client->GetFlags());
 
   RefPtr<BufferTextureHost> host = static_cast<BufferTextureHost*>(textureHost.get());
 
   ASSERT_TRUE(host.get() != nullptr);
   ASSERT_EQ(host->GetFlags(), client->GetFlags());
 
-  // This will work iff the compositor is not BasicCompositor
-  ASSERT_EQ(host->GetFormat(), mozilla::gfx::SurfaceFormat::YUV);
-
   // host read
   ASSERT_TRUE(host->Lock());
 
-  ASSERT_TRUE(host->GetFormat() == mozilla::gfx::SurfaceFormat::YUV);
+  // This will work iff the compositor is not BasicCompositor
+  ASSERT_EQ(host->GetFormat(), mozilla::gfx::SurfaceFormat::YUV);
 
   YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer());
   ASSERT_TRUE(yuvDeserializer.IsValid());
   PlanarYCbCrData data;
   data.mYChannel = yuvDeserializer.GetYData();
   data.mCbChannel = yuvDeserializer.GetCbData();
   data.mCrChannel = yuvDeserializer.GetCrData();
   data.mYStride = yuvDeserializer.GetYStride();
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -14,103 +14,82 @@
 #include "jsobjinlines.h"
 
 using namespace js;
 using namespace js::types;
 
 using mozilla::ArrayLength;
 
 bool
-js::CreateRegExpMatchResult(JSContext *cx, HandleString input_, const jschar *chars, size_t length,
-                            MatchPairs &matches, MutableHandleValue rval)
+js::CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs &matches,
+                            MutableHandleValue rval)
 {
-    RootedString input(cx, input_);
+    JS_ASSERT(input);
 
     /*
      * Create the (slow) result array for a match.
      *
      * Array contents:
      *  0:              matched string
      *  1..pairCount-1: paren matches
      *  input:          input string
      *  index:          start index for the match
      */
-    if (!input) {
-        input = js_NewStringCopyN<CanGC>(cx, chars, length);
-        if (!input)
-            return false;
-    }
-
-    size_t numPairs = matches.length();
-    JS_ASSERT(numPairs > 0);
-
-    AutoValueVector elements(cx);
-    if (!elements.reserve(numPairs))
-        return false;
-
-    /* Accumulate a Value for each pair, in a rooted vector. */
-    for (size_t i = 0; i < numPairs; ++i) {
-        const MatchPair &pair = matches[i];
-
-        if (pair.isUndefined()) {
-            JS_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
-            elements.infallibleAppend(UndefinedHandleValue);
-        } else {
-            JSLinearString *str = js_NewDependentString(cx, input, pair.start, pair.length());
-            if (!str)
-                return false;
-            elements.infallibleAppend(StringValue(str));
-        }
-    }
 
     /* Get the templateObject that defines the shape and type of the output object */
     JSObject *templateObject = cx->compartment()->regExps.getOrCreateMatchResultTemplateObject(cx);
     if (!templateObject)
         return false;
 
-    /* Copy the rooted vector into the array object. */
-    RootedObject arr(cx, NewDenseCopiedArrayWithTemplate(cx, elements.length(), elements.begin(),
-                                                         templateObject));
+    size_t numPairs = matches.length();
+    JS_ASSERT(numPairs > 0);
+
+    RootedObject arr(cx, NewDenseAllocatedArrayWithTemplate(cx, numPairs, templateObject));
     if (!arr)
         return false;
 
+    /* Store a Value for each pair. */
+    for (size_t i = 0; i < numPairs; i++) {
+        const MatchPair &pair = matches[i];
+
+        if (pair.isUndefined()) {
+            JS_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
+            arr->setDenseInitializedLength(i + 1);
+            arr->initDenseElement(i, UndefinedValue());
+        } else {
+            JSLinearString *str = js_NewDependentString(cx, input, pair.start, pair.length());
+            if (!str)
+                return false;
+            arr->setDenseInitializedLength(i + 1);
+            arr->initDenseElement(i, StringValue(str));
+        }
+    }
+
     /* Set the |index| property. (TemplateObject positions it in slot 0) */
-    RootedValue index(cx, Int32Value(matches[0].start));
-    arr->nativeSetSlot(0, index);
+    arr->nativeSetSlot(0, Int32Value(matches[0].start));
 
     /* Set the |input| property. (TemplateObject positions it in slot 1) */
-    RootedValue inputVal(cx, StringValue(input));
-    arr->nativeSetSlot(1, inputVal);
+    arr->nativeSetSlot(1, StringValue(input));
 
 #ifdef DEBUG
     RootedValue test(cx);
     RootedId id(cx, NameToId(cx->names().index));
     if (!baseops::GetProperty(cx, arr, id, &test))
         return false;
-    JS_ASSERT(test == index);
+    JS_ASSERT(test == arr->nativeGetSlot(0));
     id = NameToId(cx->names().input);
     if (!baseops::GetProperty(cx, arr, id, &test))
         return false;
-    JS_ASSERT(test == inputVal);
+    JS_ASSERT(test == arr->nativeGetSlot(1));
 #endif
 
     rval.setObject(*arr);
     return true;
 }
 
-bool
-js::CreateRegExpMatchResult(JSContext *cx, HandleString string, MatchPairs &matches,
-                            MutableHandleValue rval)
-{
-    Rooted<JSLinearString*> input(cx, string->ensureLinear(cx));
-    if (!input)
-        return false;
-    return CreateRegExpMatchResult(cx, input, input->chars(), input->length(), matches, rval);
-}
-
 static RegExpRunStatus
 ExecuteRegExpImpl(JSContext *cx, RegExpStatics *res, RegExpShared &re,
                   Handle<JSLinearString*> input, const jschar *chars, size_t length,
                   size_t *lastIndex, MatchConduit &matches)
 {
     RegExpRunStatus status;
 
     /* Switch between MatchOnly and IncludeSubpatterns modes. */
@@ -128,45 +107,52 @@ ExecuteRegExpImpl(JSContext *cx, RegExpS
     }
 
     return status;
 }
 
 /* Legacy ExecuteRegExp behavior is baked into the JSAPI. */
 bool
 js::ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
-                        Handle<JSLinearString*> input, const jschar *chars, size_t length,
+                        Handle<JSLinearString*> input_, const jschar *chars, size_t length,
                         size_t *lastIndex, bool test, MutableHandleValue rval)
 {
     RegExpGuard shared(cx);
     if (!reobj.getShared(cx, &shared))
         return false;
 
     ScopedMatchPairs matches(&cx->tempLifoAlloc());
     MatchConduit conduit(&matches);
 
     RegExpRunStatus status =
-        ExecuteRegExpImpl(cx, res, *shared, input, chars, length, lastIndex, conduit);
+        ExecuteRegExpImpl(cx, res, *shared, input_, chars, length, lastIndex, conduit);
 
     if (status == RegExpRunStatus_Error)
         return false;
 
     if (status == RegExpRunStatus_Success_NotFound) {
         /* ExecuteRegExp() previously returned an array or null. */
         rval.setNull();
         return true;
     }
 
     if (test) {
         /* Forbid an array, as an optimization. */
         rval.setBoolean(true);
         return true;
     }
 
-    return CreateRegExpMatchResult(cx, input, chars, length, matches, rval);
+    RootedString input(cx, input_);
+    if (!input) {
+        input = js_NewStringCopyN<CanGC>(cx, chars, length);
+        if (!input)
+            return false;
+    }
+
+    return CreateRegExpMatchResult(cx, input, matches, rval);
 }
 
 /* Note: returns the original if no escaping need be performed. */
 static JSAtom *
 EscapeNakedForwardSlashes(JSContext *cx, HandleAtom unescaped)
 {
     size_t oldLen = unescaped->length();
     const jschar *oldChars = unescaped->chars();
--- a/js/src/builtin/RegExp.h
+++ b/js/src/builtin/RegExp.h
@@ -36,23 +36,19 @@ ExecuteRegExp(JSContext *cx, HandleObjec
  */
 bool
 ExecuteRegExpLegacy(JSContext *cx, RegExpStatics *res, RegExpObject &reobj,
                     Handle<JSLinearString*> input, const jschar *chars, size_t length,
                     size_t *lastIndex, bool test, MutableHandleValue rval);
 
 /* Translation from MatchPairs to a JS array in regexp_exec()'s output format. */
 bool
-CreateRegExpMatchResult(JSContext *cx, HandleString string, MatchPairs &matches,
+CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs &matches,
                         MutableHandleValue rval);
 
-bool
-CreateRegExpMatchResult(JSContext *cx, HandleString input, const jschar *chars, size_t length,
-                        MatchPairs &matches, MutableHandleValue rval);
-
 extern bool
 regexp_exec_raw(JSContext *cx, HandleObject regexp, HandleString input, Value *vp);
 
 extern bool
 regexp_exec(JSContext *cx, unsigned argc, Value *vp);
 
 bool
 regexp_test_raw(JSContext *cx, HandleObject regexp, HandleString input, bool *result);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2064,19 +2064,19 @@ Parser<SyntaxParseHandler>::finishFuncti
 
     if (funbox->inWith)
         return abortIfSyntaxParser();
 
     size_t numFreeVariables = pc->lexdeps->count();
     size_t numInnerFunctions = pc->innerFunctions.length();
 
     RootedFunction fun(context, funbox->function());
-    LazyScript *lazy = LazyScript::Create(context, fun, numFreeVariables, numInnerFunctions, versionNumber(),
-                                          funbox->bufStart, funbox->bufEnd,
-                                          funbox->startLine, funbox->startColumn);
+    LazyScript *lazy = LazyScript::CreateRaw(context, fun, numFreeVariables, numInnerFunctions,
+                                             versionNumber(), funbox->bufStart, funbox->bufEnd,
+                                             funbox->startLine, funbox->startColumn);
     if (!lazy)
         return false;
 
     HeapPtrAtom *freeVariables = lazy->freeVariables();
     size_t i = 0;
     for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront())
         freeVariables[i++].init(r.front().key());
     JS_ASSERT(i == numFreeVariables);
--- a/js/src/gc/Barrier.cpp
+++ b/js/src/gc/Barrier.cpp
@@ -52,9 +52,15 @@ HeapSlot::preconditionForWriteBarrierPos
 
 bool
 RuntimeFromMainThreadIsHeapMajorCollecting(JS::shadow::Zone *shadowZone)
 {
     return shadowZone->runtimeFromMainThread()->isHeapMajorCollecting();
 }
 #endif // DEBUG
 
+bool
+StringIsPermanentAtom(JSString *str)
+{
+    return str->isPermanentAtom();
+}
+
 } // namespace js
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -600,16 +600,19 @@ struct EncapsulatedPtrHasher
     static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
     static bool match(const Key &k, Lookup l) { return k.get() == l; }
     static void rekey(Key &k, const Key& newKey) { k.unsafeSet(newKey); }
 };
 
 template <class T>
 struct DefaultHasher< EncapsulatedPtr<T> > : EncapsulatedPtrHasher<T> { };
 
+bool
+StringIsPermanentAtom(JSString *str);
+
 /*
  * Base class for barriered value types.
  */
 class BarrieredValue : public ValueOperations<BarrieredValue>
 {
   protected:
     Value value;
 
@@ -652,16 +655,18 @@ class BarrieredValue : public ValueOpera
 #ifdef JSGC_INCREMENTAL
         if (v.isMarkable() && shadowRuntimeFromAnyThread(v)->needsBarrier())
             writeBarrierPre(ZoneOfValueFromAnyThread(v), v);
 #endif
     }
 
     static void writeBarrierPre(Zone *zone, const Value &v) {
 #ifdef JSGC_INCREMENTAL
+        if (v.isString() && StringIsPermanentAtom(v.toString()))
+            return;
         JS::shadow::Zone *shadowZone = JS::shadow::Zone::asShadowZone(zone);
         if (shadowZone->needsBarrier()) {
             JS_ASSERT_IF(v.isMarkable(), shadowRuntimeFromMainThread(v)->needsBarrier());
             Value tmp(v);
             js::gc::MarkValueUnbarriered(shadowZone->barrierTracer(), &tmp, "write barrier");
             JS_ASSERT(tmp == v);
         }
 #endif
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -113,28 +113,42 @@ IsThingPoisoned(T *thing)
 
 static GCMarker *
 AsGCMarker(JSTracer *trc)
 {
     JS_ASSERT(IS_GC_MARKING_TRACER(trc));
     return static_cast<GCMarker *>(trc);
 }
 
+template <typename T> bool ThingIsPermanentAtom(T *thing) { return false; }
+template <> bool ThingIsPermanentAtom<JSString>(JSString *str) { return str->isPermanentAtom(); }
+template <> bool ThingIsPermanentAtom<JSFlatString>(JSFlatString *str) { return str->isPermanentAtom(); }
+template <> bool ThingIsPermanentAtom<JSLinearString>(JSLinearString *str) { return str->isPermanentAtom(); }
+template <> bool ThingIsPermanentAtom<JSAtom>(JSAtom *atom) { return atom->isPermanent(); }
+template <> bool ThingIsPermanentAtom<PropertyName>(PropertyName *name) { return name->isPermanent(); }
+
 template<typename T>
 static inline void
 CheckMarkedThing(JSTracer *trc, T *thing)
 {
 #ifdef DEBUG
     JS_ASSERT(trc);
     JS_ASSERT(thing);
 
     /* This function uses data that's not available in the nursery. */
     if (IsInsideNursery(trc->runtime, thing))
         return;
 
+    /*
+     * Permanent atoms are not associated with this runtime, but will be ignored
+     * during marking.
+     */
+    if (ThingIsPermanentAtom(thing))
+        return;
+
     JS_ASSERT(thing->zone());
     JS_ASSERT(thing->zone()->runtimeFromMainThread() == trc->runtime);
     JS_ASSERT(trc->debugPrinter || trc->debugPrintArg);
 
     DebugOnly<JSRuntime *> rt = trc->runtime;
 
     JS_ASSERT_IF(IS_GC_MARKING_TRACER(trc) && rt->gcManipulatingDeadZones,
                  !thing->zone()->scheduledForDestruction);
@@ -183,16 +197,24 @@ MarkInternal(JSTracer *trc, T **thingp)
          * MinorCollectionTracer because of a pre-barrier. The pre-barrier is
          * not needed in this case because we perform a minor collection before
          * each incremental slice.
          */
         if (IsInsideNursery(trc->runtime, thing))
             return;
 
         /*
+         * Don't mark permanent atoms, as they may be associated with another
+         * runtime. Note that PushMarkStack() also checks this, but the tests
+         * and maybeAlive write below should only be done on the main thread.
+         */
+        if (ThingIsPermanentAtom(thing))
+            return;
+
+        /*
          * Don't mark things outside a compartment if we are in a
          * per-compartment GC.
          */
         if (!thing->zone()->isGCMarking())
             return;
 
         PushMarkStack(AsGCMarker(trc), thing);
         thing->zone()->maybeAlive = true;
@@ -224,16 +246,40 @@ MarkUnbarriered(JSTracer *trc, T **thing
 template <typename T>
 static void
 Mark(JSTracer *trc, BarrieredPtr<T> *thing, const char *name)
 {
     JS_SET_TRACING_NAME(trc, name);
     MarkInternal(trc, thing->unsafeGet());
 }
 
+void
+MarkPermanentAtom(JSTracer *trc, JSAtom *atom, const char *name)
+{
+    JS_SET_TRACING_NAME(trc, name);
+
+    JS_ASSERT(atom->isPermanent());
+
+    CheckMarkedThing(trc, atom);
+
+    if (!trc->callback) {
+        // Atoms do not refer to other GC things so don't need to go on the mark stack.
+        // Additionally, PushMarkStack will ignore permanent atoms.
+        atom->markIfUnmarked();
+    } else {
+        void *thing = atom;
+        trc->callback(trc, &thing, JSTRACE_STRING);
+        JS_ASSERT(thing == atom);
+        JS_UNSET_TRACING_LOCATION(trc);
+    }
+
+    trc->debugPrinter = nullptr;
+    trc->debugPrintArg = nullptr;
+}
+
 } /* namespace gc */
 } /* namespace js */
 
 template <typename T>
 static void
 MarkRoot(JSTracer *trc, T **thingp, const char *name)
 {
     JS_ROOT_MARKING_ASSERT(trc);
@@ -288,16 +334,23 @@ IsMarked(T **thingp)
 
 template <typename T>
 static bool
 IsAboutToBeFinalized(T **thingp)
 {
     JS_ASSERT(thingp);
     JS_ASSERT(*thingp);
 
+    /* Permanent atoms are never finalized by non-owning runtimes. */
+    if (ThingIsPermanentAtom(*thingp) &&
+        !TlsPerThreadData.get()->associatedWith((*thingp)->runtimeFromAnyThread()))
+    {
+        return false;
+    }
+
 #ifdef JSGC_GENERATIONAL
     Nursery &nursery = (*thingp)->runtimeFromMainThread()->gcNursery;
     if (nursery.isInside(*thingp))
         return !nursery.getForwardedPointer(thingp);
 #endif
     if (!(*thingp)->tenuredZone()->isGCSweeping())
         return false;
 
@@ -935,16 +988,18 @@ ScanLinearString(GCMarker *gcmarker, JSL
     /*
      * Add extra asserts to confirm the static type to detect incorrect string
      * mutations.
      */
     JS_ASSERT(str->JSString::isLinear());
     while (str->hasBase()) {
         str = str->base();
         JS_ASSERT(str->JSString::isLinear());
+        if (str->isPermanentAtom())
+            break;
         JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, str);
         if (!str->markIfUnmarked())
             break;
     }
 }
 
 /*
  * The function tries to scan the whole rope tree using the marking stack as
@@ -963,25 +1018,25 @@ ScanRope(GCMarker *gcmarker, JSRope *rop
     for (;;) {
         JS_DIAGNOSTICS_ASSERT(GetGCThingTraceKind(rope) == JSTRACE_STRING);
         JS_DIAGNOSTICS_ASSERT(rope->JSString::isRope());
         JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, rope);
         JS_ASSERT(rope->isMarked());
         JSRope *next = nullptr;
 
         JSString *right = rope->rightChild();
-        if (right->markIfUnmarked()) {
+        if (!right->isPermanentAtom() && right->markIfUnmarked()) {
             if (right->isLinear())
                 ScanLinearString(gcmarker, &right->asLinear());
             else
                 next = &right->asRope();
         }
 
         JSString *left = rope->leftChild();
-        if (left->markIfUnmarked()) {
+        if (!left->isPermanentAtom() && left->markIfUnmarked()) {
             if (left->isLinear()) {
                 ScanLinearString(gcmarker, &left->asLinear());
             } else {
                 /*
                  * When both children are ropes, set aside the right one to
                  * scan it later.
                  */
                 if (next && !gcmarker->stack.push(reinterpret_cast<uintptr_t>(next)))
@@ -1008,16 +1063,20 @@ ScanString(GCMarker *gcmarker, JSString 
         ScanLinearString(gcmarker, &str->asLinear());
     else
         ScanRope(gcmarker, &str->asRope());
 }
 
 static inline void
 PushMarkStack(GCMarker *gcmarker, JSString *str)
 {
+    // Permanent atoms might not be associated with this runtime.
+    if (str->isPermanentAtom())
+        return;
+
     JS_COMPARTMENT_ASSERT_STR(gcmarker->runtime, str);
 
     /*
      * As string can only refer to other strings we fully scan its GC graph
      * using the explicit stack when navigating the rope tree to avoid
      * dealing with strings on the stack in drainMarkStack.
      */
     if (str->markIfUnmarked())
@@ -1393,20 +1452,22 @@ GCMarker::processMarkStackTop(SliceBudge
     return;
 
   scan_value_array:
     JS_ASSERT(vp <= end);
     while (vp != end) {
         const Value &v = *vp++;
         if (v.isString()) {
             JSString *str = v.toString();
-            JS_COMPARTMENT_ASSERT_STR(runtime, str);
-            JS_ASSERT(runtime->isAtomsZone(str->zone()) || str->zone() == obj->zone());
-            if (str->markIfUnmarked())
-                ScanString(this, str);
+            if (!str->isPermanentAtom()) {
+                JS_COMPARTMENT_ASSERT_STR(runtime, str);
+                JS_ASSERT(runtime->isAtomsZone(str->zone()) || str->zone() == obj->zone());
+                if (str->markIfUnmarked())
+                    ScanString(this, str);
+            }
         } else if (v.isObject()) {
             JSObject *obj2 = &v.toObject();
             JS_COMPARTMENT_ASSERT(runtime, obj2);
             JS_ASSERT(obj->compartment() == obj2->compartment());
             if (obj2->markIfUnmarked(getMarkColor())) {
                 pushValueArray(obj, vp, end);
                 obj = obj2;
                 goto scan_obj;
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -109,16 +109,19 @@ DeclMarker(String, JSAtom)
 DeclMarker(String, JSString)
 DeclMarker(String, JSFlatString)
 DeclMarker(String, JSLinearString)
 DeclMarker(String, PropertyName)
 DeclMarker(TypeObject, types::TypeObject)
 
 #undef DeclMarker
 
+void
+MarkPermanentAtom(JSTracer *trc, JSAtom *atom, const char *name);
+
 /* Return true if the pointer is nullptr, or if it is a tagged pointer to
  * nullptr.
  */
 MOZ_ALWAYS_INLINE bool
 IsNullTaggedPointer(void *p)
 {
     return uintptr_t(p) < 32;
 }
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -731,18 +731,18 @@ js::gc::MarkRuntime(JSTracer *trc, bool 
     if (rt->scriptAndCountsVector) {
         ScriptAndCountsVector &vec = *rt->scriptAndCountsVector;
         for (size_t i = 0; i < vec.length(); i++)
             MarkScriptRoot(trc, &vec[i].script, "scriptAndCountsVector");
     }
 
     if (!rt->isBeingDestroyed() && !trc->runtime->isHeapMinorCollecting()) {
         if (!IS_GC_MARKING_TRACER(trc) || rt->atomsCompartment()->zone()->isCollecting()) {
+            MarkPermanentAtoms(trc);
             MarkAtoms(trc);
-            rt->staticStrings.trace(trc);
 #ifdef JS_ION
             jit::JitRuntime::Mark(trc);
 #endif
         }
     }
 
     for (ContextIter acx(rt); !acx.done(); acx.next())
         acx->mark(trc);
--- a/js/src/gc/Verifier.cpp
+++ b/js/src/gc/Verifier.cpp
@@ -577,16 +577,20 @@ CheckEdge(JSTracer *jstrc, void **thingp
 }
 
 static void
 AssertMarkedOrAllocated(const EdgeValue &edge)
 {
     if (!edge.thing || IsMarkedOrAllocated(static_cast<Cell *>(edge.thing)))
         return;
 
+    // Permanent atoms aren't marked during graph traversal.
+    if (edge.kind == JSTRACE_STRING && static_cast<JSString *>(edge.thing)->isPermanentAtom())
+        return;
+
     char msgbuf[1024];
     const char *label = edge.label ? edge.label : "<unknown>";
 
     JS_snprintf(msgbuf, sizeof(msgbuf), "[barrier verifier] Unmarked edge: %s", label);
     MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
     MOZ_CRASH();
 }
 
--- a/js/src/jit-test/tests/basic/cross-context-stack-1.js
+++ b/js/src/jit-test/tests/basic/cross-context-stack-1.js
@@ -2,16 +2,16 @@
 function g() {
     evaluate("function h() {\nstack = Error().stack;\n };\n h();", {newContext: true});
 }
 function f() {
     g();
 }
 f();
 assertEq(stack,
-    "h@@evaluate:2\n" +
-    "@@evaluate:4\n");
+    "h@@evaluate:2:1\n" +
+    "@@evaluate:4:2\n");
 
 function k() {
     evaluate("stack = Error().stack", {newContext: true});
 }
 k();
-assertEq(stack, "@@evaluate:1\n");
+assertEq(stack, "@@evaluate:1:1\n");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/evaluate-worker.js
@@ -0,0 +1,19 @@
+// |jit-test| slow
+
+gcslice(10);
+evalInWorker("print('helo world');");
+for (i = 0; i < 100000; i++) {}
+
+evalInWorker("\
+  for (var i = 0; i < 10; i++) { \
+    var o = {}; \
+    for (var j = 0; j < 100; j++) \
+      o['a' + j] = j; \
+    JSON.stringify(o); \
+    o = null; \
+    gc(); \
+}");
+for (var i = 0; i < 10; i++) {
+    gc();
+    for (var j = 0; j < 100000; j++) {}
+}
--- a/js/src/jit-test/tests/basic/offThreadCompileScript-02.js
+++ b/js/src/jit-test/tests/basic/offThreadCompileScript-02.js
@@ -1,16 +1,16 @@
 // Test offThreadCompileScript option handling.
 
 offThreadCompileScript('Error()');
-assertEq(!!runOffThreadScript().stack.match(/^@<string>:1\n/), true);
+assertEq(!!runOffThreadScript().stack.match(/^@<string>:1:1\n/), true);
 
 offThreadCompileScript('Error()',
                        { fileName: "candelabra", lineNumber: 6502 });
-assertEq(!!runOffThreadScript().stack.match(/^@candelabra:6502\n/), true);
+assertEq(!!runOffThreadScript().stack.match(/^@candelabra:6502:1\n/), true);
 
 var element = {};
 offThreadCompileScript('Error()', { element: element }); // shouldn't crash
 runOffThreadScript();
 
 var elementAttributeName = "molybdenum";
 elementAttributeName += elementAttributeName + elementAttributeName + elementAttributeName;
 offThreadCompileScript('Error()', { elementAttributeName: elementAttributeName }); // shouldn't crash
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -5679,16 +5679,18 @@ CheckFunctionsParallel(ModuleCompiler &m
     // pref, etc) or another thread is currently compiling asm.js in parallel,
     // fall back to sequential compilation. (We could lift the latter
     // constraint by hoisting asmJS* state out of WorkerThreadState so multiple
     // concurrent asm.js parallel compilations don't race.)
     ParallelCompilationGuard g;
     if (!ParallelCompilationEnabled(m.cx()) || !g.claim())
         return CheckFunctionsSequential(m);
 
+    IonSpew(IonSpew_Logs, "Can't log asm.js script. (Compiled on background thread.)");
+
     // Saturate all worker threads plus the main thread.
     size_t numParallelJobs = WorkerThreadState().threadCount + 1;
 
     // Allocate scoped AsmJSParallelTask objects. Each contains a unique
     // LifoAlloc that provides all necessary memory for compilation.
     js::Vector<AsmJSParallelTask, 0> tasks(m.cx());
     if (!tasks.initCapacity(numParallelJobs))
         return false;
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -4435,17 +4435,17 @@ ICGetElem_String::Compiler::generateStub
     masm.loadPtr(charsAddr, scratchReg);
     masm.load16ZeroExtend(BaseIndex(scratchReg, key, TimesTwo, 0), scratchReg);
 
     // Check if char code >= UNIT_STATIC_LIMIT.
     masm.branch32(Assembler::AboveOrEqual, scratchReg, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
                   &failure);
 
     // Load static string.
-    masm.movePtr(ImmPtr(&cx->runtime()->staticStrings.unitStaticTable), str);
+    masm.movePtr(ImmPtr(&cx->staticStrings().unitStaticTable), str);
     masm.loadPtr(BaseIndex(str, scratchReg, ScalePointer), str);
 
     // Return.
     masm.tagValue(JSVAL_TYPE_STRING, str, R0);
     EmitReturnFromIC(masm);
 
     // Failure case - jump to next stub
     masm.bind(&failure);
@@ -9382,17 +9382,17 @@ ICInstanceOf_Fallback::Compiler::generat
 //
 
 static bool
 DoTypeOfFallback(JSContext *cx, BaselineFrame *frame, ICTypeOf_Fallback *stub, HandleValue val,
                  MutableHandleValue res)
 {
     FallbackICSpew(cx, stub, "TypeOf");
     JSType type = js::TypeOfValue(val);
-    RootedString string(cx, TypeName(type, cx->runtime()->atomState));
+    RootedString string(cx, TypeName(type, cx->names()));
 
     res.setString(string);
 
     JS_ASSERT(type != JSTYPE_NULL);
     if (type != JSTYPE_OBJECT && type != JSTYPE_FUNCTION) {
         // Create a new TypeOf stub.
         IonSpew(IonSpew_BaselineIC, "  Generating TypeOf stub for JSType (%d)", (int) type);
         ICTypeOf_Typed::Compiler compiler(cx, type, string);
--- a/js/src/jit/CompileWrappers.cpp
+++ b/js/src/jit/CompileWrappers.cpp
@@ -107,23 +107,23 @@ bool
 CompileRuntime::hadOutOfMemory()
 {
     return runtime()->hadOutOfMemory;
 }
 
 const JSAtomState &
 CompileRuntime::names()
 {
-    return runtime()->atomState;
+    return *runtime()->commonNames;
 }
 
 const StaticStrings &
 CompileRuntime::staticStrings()
 {
-    return runtime()->staticStrings;
+    return *runtime()->staticStrings;
 }
 
 const Value &
 CompileRuntime::NaNValue()
 {
     return runtime()->NaNValue;
 }
 
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -454,17 +454,17 @@ CharCodeAt(JSContext *cx, HandleString s
 }
 
 JSFlatString *
 StringFromCharCode(JSContext *cx, int32_t code)
 {
     jschar c = jschar(code);
 
     if (StaticStrings::hasUnit(c))
-        return cx->runtime()->staticStrings.getUnit(c);
+        return cx->staticStrings().getUnit(c);
 
     return js_NewStringCopyN<CanGC>(cx, &c, 1);
 }
 
 bool
 SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value,
             bool strict, jsbytecode *pc)
 {
@@ -1035,16 +1035,22 @@ AssertValidObjectPtr(JSContext *cx, JSOb
         JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
         JS_ASSERT(obj->tenuredZone() == cx->zone());
     }
 }
 
 void
 AssertValidStringPtr(JSContext *cx, JSString *str)
 {
+    // We can't closely inspect strings from another runtime.
+    if (str->runtimeFromAnyThread() != cx->runtime()) {
+        JS_ASSERT(str->isPermanentAtom());
+        return;
+    }
+
     if (str->isAtom())
         JS_ASSERT(cx->runtime()->isAtomsZone(str->tenuredZone()));
     else
         JS_ASSERT(str->tenuredZone() == cx->zone());
 
     JS_ASSERT(str->runtimeFromMainThread() == cx->runtime());
     JS_ASSERT(str->isAligned());
     JS_ASSERT(str->length() <= JSString::MAX_LENGTH);
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -783,37 +783,44 @@ CodeGeneratorX86Shared::visitReturnZero(
     masm.mov(ImmWord(0), ool->reg());
     masm.jmp(ool->rejoin());
     return true;
 }
 
 bool
 CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod *ins)
 {
-    JS_ASSERT(ToRegister(ins->lhs()) == eax);
+    Register lhs = ToRegister(ins->lhs());
     Register rhs = ToRegister(ins->rhs());
     Register output = ToRegister(ins->output());
 
+    JS_ASSERT_IF(lhs != rhs, rhs != eax);
+    JS_ASSERT(rhs != edx);
     JS_ASSERT_IF(output == eax, ToRegister(ins->remainder()) == edx);
 
     ReturnZero *ool = nullptr;
 
+    // Put the lhs in eax.
+    if (lhs != eax)
+        masm.mov(lhs, eax);
+
     // Prevent divide by zero.
     if (ins->canBeDivideByZero()) {
         masm.testl(rhs, rhs);
         if (ins->mir()->isTruncated()) {
             if (!ool)
                 ool = new(alloc()) ReturnZero(output);
             masm.j(Assembler::Zero, ool->entry());
         } else {
             if (!bailoutIf(Assembler::Zero, ins->snapshot()))
                 return false;
         }
     }
 
+    // Zero extend the lhs into edx to make (edx:eax), since udiv is 64-bit.
     masm.mov(ImmWord(0), edx);
     masm.udiv(rhs);
 
     // Unsigned div or mod can return a value that's not a signed int32.
     // If our users aren't expecting that, bail.
     if (!ins->mir()->isTruncated()) {
         masm.testl(output, output);
         if (!bailoutIf(Assembler::Signed, ins->snapshot()))
@@ -888,54 +895,38 @@ CodeGeneratorX86Shared::visitDivPowTwoI(
         // Do the shift.
         masm.sarl(Imm32(shift), lhs);
     }
 
     return true;
 }
 
 bool
-CodeGeneratorX86Shared::visitDivSelfI(LDivSelfI *ins)
-{
-    Register op = ToRegister(ins->op());
-    Register output = ToRegister(ins->output());
-    MDiv *mir = ins->mir();
-
-    // If we can't divide by zero, lowering should have just used a constant one.
-    JS_ASSERT(mir->canBeDivideByZero());
-
-    masm.testl(op, op);
-    if (mir->isTruncated()) {
-        masm.emitSet(Assembler::NonZero, output);
-    } else {
-       if (!bailoutIf(Assembler::Zero, ins->snapshot()))
-           return false;
-        masm.mov(ImmWord(1), output);
-    }
-
-    return true;
-}
-
-bool
 CodeGeneratorX86Shared::visitDivI(LDivI *ins)
 {
     Register remainder = ToRegister(ins->remainder());
     Register lhs = ToRegister(ins->lhs());
     Register rhs = ToRegister(ins->rhs());
     Register output = ToRegister(ins->output());
 
     MDiv *mir = ins->mir();
 
+    JS_ASSERT_IF(lhs != rhs, rhs != eax);
+    JS_ASSERT(rhs != edx);
     JS_ASSERT(remainder == edx);
-    JS_ASSERT(lhs == eax);
     JS_ASSERT(output == eax);
 
     Label done;
     ReturnZero *ool = nullptr;
 
+    // Put the lhs in eax, for either the negative overflow case or the regular
+    // divide case.
+    if (lhs != eax)
+        masm.mov(lhs, eax);
+
     // Handle divide by zero.
     if (mir->canBeDivideByZero()) {
         masm.testl(rhs, rhs);
         if (mir->isTruncated()) {
             // Truncated division by zero is zero (Infinity|0 == 0)
             if (!ool)
                 ool = new(alloc()) ReturnZero(output);
             masm.j(Assembler::Zero, ool->entry());
@@ -970,17 +961,19 @@ CodeGeneratorX86Shared::visitDivI(LDivI 
         masm.testl(lhs, lhs);
         masm.j(Assembler::NonZero, &nonzero);
         masm.cmpl(rhs, Imm32(0));
         if (!bailoutIf(Assembler::LessThan, ins->snapshot()))
             return false;
         masm.bind(&nonzero);
     }
 
-    // Sign extend eax into edx to make (edx:eax), since idiv is 64-bit.
+    // Sign extend the lhs into edx to make (edx:eax), since idiv is 64-bit.
+    if (lhs != eax)
+        masm.mov(lhs, eax);
     masm.cdq();
     masm.idiv(rhs);
 
     if (!mir->isTruncated()) {
         // If the remainder is > 0, bailout since this must be a double.
         masm.testl(remainder, remainder);
         if (!bailoutIf(Assembler::NonZero, ins->snapshot()))
             return false;
@@ -993,49 +986,16 @@ CodeGeneratorX86Shared::visitDivI(LDivI 
             return false;
         masm.bind(ool->rejoin());
     }
 
     return true;
 }
 
 bool
-CodeGeneratorX86Shared::visitModSelfI(LModSelfI *ins)
-{
-    Register op = ToRegister(ins->op());
-    Register output = ToRegister(ins->output());
-    MMod *mir = ins->mir();
-
-    // If we're not fallible, lowering should have just used a constant zero.
-    JS_ASSERT(mir->fallible());
-    JS_ASSERT(mir->canBeDivideByZero() || (!mir->isUnsigned() && mir->canBeNegativeDividend()));
-
-    masm.testl(op, op);
-
-    // For a negative operand, we need to return negative zero. We can't
-    // represent that as an int32, so bail if that happens.
-    if (!mir->isUnsigned() && mir->canBeNegativeDividend()) {
-        if (!bailoutIf(Assembler::Signed, ins->snapshot()))
-             return false;
-    }
-
-    // For a zero operand, we need to return NaN. We can't
-    // represent that as an int32, so bail if that happens.
-    if (mir->canBeDivideByZero()) {
-        if (!bailoutIf(Assembler::Zero, ins->snapshot()))
-            return false;
-    }
-
-    // For any other value, return 0.
-    masm.mov(ImmWord(0), output);
-
-    return true;
-}
-
-bool
 CodeGeneratorX86Shared::visitModPowTwoI(LModPowTwoI *ins)
 {
     Register lhs = ToRegister(ins->getOperand(0));
     int32_t shift = ins->shift();
 
     Label negative;
 
     if (ins->mir()->canBeNegativeDividend()) {
@@ -1109,24 +1069,29 @@ CodeGeneratorX86Shared::visitModOverflow
 bool
 CodeGeneratorX86Shared::visitModI(LModI *ins)
 {
     Register remainder = ToRegister(ins->remainder());
     Register lhs = ToRegister(ins->lhs());
     Register rhs = ToRegister(ins->rhs());
 
     // Required to use idiv.
-    JS_ASSERT(lhs == eax);
+    JS_ASSERT_IF(lhs != rhs, rhs != eax);
+    JS_ASSERT(rhs != edx);
     JS_ASSERT(remainder == edx);
     JS_ASSERT(ToRegister(ins->getTemp(0)) == eax);
 
     Label done;
     ReturnZero *ool = nullptr;
     ModOverflowCheck *overflow = nullptr;
 
+    // Set up eax in preparation for doing a div.
+    if (lhs != eax)
+        masm.mov(lhs, eax);
+
     // Prevent divide by zero.
     if (ins->mir()->canBeDivideByZero()) {
         masm.testl(rhs, rhs);
         if (ins->mir()->isTruncated()) {
             if (!ool)
                 ool = new(alloc()) ReturnZero(edx);
             masm.j(Assembler::Zero, ool->entry());
         } else {
--- a/js/src/jit/shared/CodeGenerator-x86-shared.h
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.h
@@ -86,20 +86,18 @@ class CodeGeneratorX86Shared : public Co
     virtual bool visitSqrtD(LSqrtD *ins);
     virtual bool visitSqrtF(LSqrtF *ins);
     virtual bool visitPowHalfD(LPowHalfD *ins);
     virtual bool visitAddI(LAddI *ins);
     virtual bool visitSubI(LSubI *ins);
     virtual bool visitMulI(LMulI *ins);
     virtual bool visitDivI(LDivI *ins);
     virtual bool visitDivPowTwoI(LDivPowTwoI *ins);
-    virtual bool visitDivSelfI(LDivSelfI *ins);
     virtual bool visitModI(LModI *ins);
     virtual bool visitModPowTwoI(LModPowTwoI *ins);
-    virtual bool visitModSelfI(LModSelfI *ins);
     virtual bool visitBitNotI(LBitNotI *ins);
     virtual bool visitBitOpI(LBitOpI *ins);
     virtual bool visitShiftI(LShiftI *ins);
     virtual bool visitUrshD(LUrshD *ins);
     virtual bool visitTestIAndBranch(LTestIAndBranch *test);
     virtual bool visitTestDAndBranch(LTestDAndBranch *test);
     virtual bool visitTestFAndBranch(LTestFAndBranch *test);
     virtual bool visitCompare(LCompare *comp);
--- a/js/src/jit/shared/LIR-x86-shared.h
+++ b/js/src/jit/shared/LIR-x86-shared.h
@@ -67,35 +67,16 @@ class LDivPowTwoI : public LBinaryMath<0
     int32_t shift() const {
         return shift_;
     }
     MDiv *mir() const {
         return mir_->toDiv();
     }
 };
 
-// Division of a number by itself. Returns 1 unless the number is zero.
-class LDivSelfI : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(DivSelfI)
-
-    LDivSelfI(const LAllocation &op) {
-        setOperand(0, op);
-    }
-
-    const LAllocation *op() {
-        return getOperand(0);
-    }
-
-    MDiv *mir() const {
-        return mir_->toDiv();
-    }
-};
-
 class LModI : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(ModI)
 
     LModI(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
         setOperand(0, lhs);
         setOperand(1, rhs);
@@ -109,35 +90,16 @@ class LModI : public LBinaryMath<1>
     const LDefinition *remainder() {
         return getDef(0);
     }
     MMod *mir() const {
         return mir_->toMod();
     }
 };
 
-// Modulo of a number by itself. Returns 0 unless the number is zero.
-class LModSelfI : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(ModSelfI)
-
-    LModSelfI(const LAllocation &op) {
-        setOperand(0, op);
-    }
-
-    const LAllocation *op() {
-        return getOperand(0);
-    }
-
-    MMod *mir() const {
-        return mir_->toMod();
-    }
-};
-
 // This class performs a simple x86 'div', yielding either a quotient or remainder depending on
 // whether this instruction is defined to output eax (quotient) or edx (remainder).
 class LUDivOrMod : public LBinaryMath<1>
 {
   public:
     LIR_HEADER(UDivOrMod);
 
     LUDivOrMod(const LAllocation &lhs, const LAllocation &rhs, const LDefinition &temp) {
--- a/js/src/jit/shared/Lowering-x86-shared.cpp
+++ b/js/src/jit/shared/Lowering-x86-shared.cpp
@@ -155,34 +155,18 @@ LIRGeneratorX86Shared::lowerDivI(MDiv *d
                 lir = new(alloc()) LDivPowTwoI(lhs, useRegister(div->lhs()), shift);
             }
             if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
                 return false;
             return defineReuseInput(lir, div, 0);
         }
     }
 
-    // Optimize x/x. This is quaint, but it also protects the LDivI code below.
-    // Since LDivI requires lhs to be in %eax, and since the register allocator
-    // can't put a virtual register in two physical registers at the same time,
-    // this puts rhs in %eax too, and since rhs isn't marked usedAtStart, it
-    // would conflict with the %eax output register. (rhs could be marked
-    // usedAtStart but for the fact that LDivI clobbers %edx early and rhs could
-    // happen to be in %edx).
-    if (div->lhs() == div->rhs()) {
-        if (!div->canBeDivideByZero())
-            return define(new(alloc()) LInteger(1), div);
-
-        LDivSelfI *lir = new(alloc()) LDivSelfI(useRegisterAtStart(div->lhs()));
-        if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
-            return false;
-        return define(lir, div);
-    }
-
-    LDivI *lir = new(alloc()) LDivI(useFixed(div->lhs(), eax), useRegister(div->rhs()), tempFixed(edx));
+    LDivI *lir = new(alloc()) LDivI(useRegister(div->lhs()), useRegister(div->rhs()),
+                                    tempFixed(edx));
     if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
         return false;
     return defineFixed(lir, div, LAllocation(AnyRegister(eax)));
 }
 
 bool
 LIRGeneratorX86Shared::lowerModI(MMod *mod)
 {
@@ -195,30 +179,17 @@ LIRGeneratorX86Shared::lowerModI(MMod *m
         if (rhs > 0 && 1 << shift == rhs) {
             LModPowTwoI *lir = new(alloc()) LModPowTwoI(useRegisterAtStart(mod->lhs()), shift);
             if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
                 return false;
             return defineReuseInput(lir, mod, 0);
         }
     }
 
-    // Optimize x%x. The comments in lowerDivI apply here as well, except
-    // that we return 0 for all cases except when x is 0 and we're not
-    // truncated.
-    if (mod->rhs() == mod->lhs()) {
-        if (mod->isTruncated())
-            return define(new(alloc()) LInteger(0), mod);
-
-        LModSelfI *lir = new(alloc()) LModSelfI(useRegisterAtStart(mod->lhs()));
-        if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
-            return false;
-        return define(lir, mod);
-    }
-
-    LModI *lir = new(alloc()) LModI(useFixedAtStart(mod->lhs(), eax),
+    LModI *lir = new(alloc()) LModI(useRegister(mod->lhs()),
                                     useRegister(mod->rhs()),
                                     tempFixed(eax));
     if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
         return false;
     return defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
 }
 
 bool
@@ -232,50 +203,28 @@ LIRGeneratorX86Shared::visitAsmJSNeg(MAs
 
     JS_ASSERT(ins->type() == MIRType_Double);
     return defineReuseInput(new(alloc()) LNegD(useRegisterAtStart(ins->input())), ins, 0);
 }
 
 bool
 LIRGeneratorX86Shared::lowerUDiv(MDiv *div)
 {
-    // Optimize x/x. The comments in lowerDivI apply here as well.
-    if (div->lhs() == div->rhs()) {
-        if (!div->canBeDivideByZero())
-            return define(new(alloc()) LInteger(1), div);
-
-        LDivSelfI *lir = new(alloc()) LDivSelfI(useRegisterAtStart(div->lhs()));
-        if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
-            return false;
-        return define(lir, div);
-    }
-
-    LUDivOrMod *lir = new(alloc()) LUDivOrMod(useFixedAtStart(div->lhs(), eax),
+    LUDivOrMod *lir = new(alloc()) LUDivOrMod(useRegister(div->lhs()),
                                               useRegister(div->rhs()),
                                               tempFixed(edx));
     if (div->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
         return false;
     return defineFixed(lir, div, LAllocation(AnyRegister(eax)));
 }
 
 bool
 LIRGeneratorX86Shared::lowerUMod(MMod *mod)
 {
-    // Optimize x%x. The comments in lowerModI apply here as well.
-    if (mod->lhs() == mod->rhs()) {
-        if (mod->isTruncated() || (mod->isUnsigned() && !mod->canBeDivideByZero()))
-            return define(new(alloc()) LInteger(0), mod);
-
-        LModSelfI *lir = new(alloc()) LModSelfI(useRegisterAtStart(mod->lhs()));
-        if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
-            return false;
-        return define(lir, mod);
-    }
-
-    LUDivOrMod *lir = new(alloc()) LUDivOrMod(useFixedAtStart(mod->lhs(), eax),
+    LUDivOrMod *lir = new(alloc()) LUDivOrMod(useRegister(mod->lhs()),
                                               useRegister(mod->rhs()),
                                               tempFixed(eax));
     if (mod->fallible() && !assignSnapshot(lir, Bailout_BaselineInfo))
         return false;
     return defineFixed(lir, mod, LAllocation(AnyRegister(edx)));
 }
 
 bool
--- a/js/src/jit/x64/LOpcodes-x64.h
+++ b/js/src/jit/x64/LOpcodes-x64.h
@@ -8,19 +8,17 @@
 #define jit_x64_LOpcodes_x64_h
 
 #define LIR_CPU_OPCODE_LIST(_)      \
     _(Box)                          \
     _(Unbox)                        \
     _(UnboxFloatingPoint)           \
     _(DivI)                         \
     _(DivPowTwoI)                   \
-    _(DivSelfI)                     \
     _(ModI)                         \
     _(ModPowTwoI)                   \
-    _(ModSelfI)                     \
     _(PowHalfD)                     \
     _(AsmJSUInt32ToDouble)          \
     _(AsmJSUInt32ToFloat32)         \
     _(AsmJSLoadFuncPtr)             \
     _(UDivOrMod)
 
 #endif /* jit_x64_LOpcodes_x64_h */
--- a/js/src/jit/x86/LOpcodes-x86.h
+++ b/js/src/jit/x86/LOpcodes-x86.h
@@ -9,19 +9,17 @@
 
 #define LIR_CPU_OPCODE_LIST(_)  \
     _(Unbox)                    \
     _(UnboxFloatingPoint)       \
     _(Box)                      \
     _(BoxFloatingPoint)         \
     _(DivI)                     \
     _(DivPowTwoI)               \
-    _(DivSelfI)                 \
     _(ModI)                     \
     _(ModPowTwoI)               \
-    _(ModSelfI)                 \
     _(PowHalfD)                 \
     _(AsmJSUInt32ToDouble)      \
     _(AsmJSUInt32ToFloat32)     \
     _(AsmJSLoadFuncPtr)         \
     _(UDivOrMod)
 
 #endif /* jit_x86_LOpcodes_x86_h */
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -631,22 +631,28 @@ JS::isGCEnabled()
 {
     return !TlsPerThreadData.get()->suppressGC;
 }
 #else
 JS_FRIEND_API(bool) JS::isGCEnabled() { return true; }
 #endif
 
 JS_PUBLIC_API(JSRuntime *)
-JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads)
+JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads, JSRuntime *parentRuntime)
 {
     MOZ_ASSERT(jsInitState == Running,
                "must call JS_Init prior to creating any JSRuntimes");
 
-    JSRuntime *rt = js_new<JSRuntime>(useHelperThreads);
+    // Any parent runtime should be the topmost parent. This assert
+    // isn't required for correctness, but ensuring that the parent
+    // runtime is not destroyed before this one is more easily done
+    // for the main runtime in the process.
+    JS_ASSERT_IF(parentRuntime, !parentRuntime->parentRuntime);
+
+    JSRuntime *rt = js_new<JSRuntime>(parentRuntime, useHelperThreads);
     if (!rt)
         return nullptr;
 
     if (!rt->init(maxbytes)) {
         JS_DestroyRuntime(rt);
         return nullptr;
     }
 
@@ -802,16 +808,23 @@ JS_SetSecondContextPrivate(JSContext *cx
 }
 
 JS_PUBLIC_API(JSRuntime *)
 JS_GetRuntime(JSContext *cx)
 {
     return cx->runtime();
 }
 
+JS_PUBLIC_API(JSRuntime *)
+JS_GetParentRuntime(JSContext *cx)
+{
+    JSRuntime *rt = cx->runtime();
+    return rt->parentRuntime ? rt->parentRuntime : nullptr;
+}
+
 JS_PUBLIC_API(JSContext *)
 JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
 {
     JSContext *cx = *iterp;
     cx = cx ? cx->getNext() : rt->contextList.getFirst();
     *iterp = cx;
     return cx;
 }
@@ -1155,17 +1168,17 @@ typedef struct JSStdName {
 
 static const JSStdName*
 LookupStdName(JSRuntime *rt, HandleString name, const JSStdName *table)
 {
     MOZ_ASSERT(name->isAtom());
     for (unsigned i = 0; !table[i].isSentinel(); i++) {
         if (table[i].isDummy())
             continue;
-        JSAtom *atom = AtomStateOffsetToName(rt->atomState, table[i].atomOffset);
+        JSAtom *atom = AtomStateOffsetToName(*rt->commonNames, table[i].atomOffset);
         MOZ_ASSERT(atom);
         if (name == atom)
             return &table[i];
     }
 
     return nullptr;
 }
 
@@ -1260,17 +1273,17 @@ JS_ResolveStandardClass(JSContext *cx, H
 
     rt = cx->runtime();
     if (!rt->hasContexts() || !JSID_IS_ATOM(id))
         return true;
 
     RootedString idstr(cx, JSID_TO_STRING(id));
 
     /* Check whether we're resolving 'undefined', and define it if so. */
-    JSAtom *undefinedAtom = rt->atomState.undefined;
+    JSAtom *undefinedAtom = cx->names().undefined;
     if (idstr == undefinedAtom) {
         *resolved = true;
         return JSObject::defineProperty(cx, obj, undefinedAtom->asPropertyName(),
                                         UndefinedHandleValue,
                                         JS_PropertyStub, JS_StrictPropertyStub,
                                         JSPROP_PERMANENT | JSPROP_READONLY);
     }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1284,17 +1284,18 @@ JS_Init(void);
  * It is currently not possible to initialize SpiderMonkey multiple times (that
  * is, calling JS_Init/JSAPI methods/JS_ShutDown in that order, then doing so
  * again).  This restriction may eventually be lifted.
  */
 extern JS_PUBLIC_API(void)
 JS_ShutDown(void);
 
 extern JS_PUBLIC_API(JSRuntime *)
-JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads);
+JS_NewRuntime(uint32_t maxbytes, JSUseHelperThreads useHelperThreads,
+              JSRuntime *parentRuntime = nullptr);
 
 extern JS_PUBLIC_API(void)
 JS_DestroyRuntime(JSRuntime *rt);
 
 // These are equivalent to ICU's |UMemAllocFn|, |UMemReallocFn|, and
 // |UMemFreeFn| types.  The first argument (called |context| in the ICU docs)
 // will always be nullptr, and should be ignored.
 typedef void *(*JS_ICUAllocFn)(const void *, size_t size);
@@ -1307,16 +1308,19 @@ extern JS_PUBLIC_API(bool)
 JS_SetICUMemoryFunctions(JS_ICUAllocFn allocFn, JS_ICUReallocFn reallocFn, JS_ICUFreeFn freeFn);
 
 JS_PUBLIC_API(void *)
 JS_GetRuntimePrivate(JSRuntime *rt);
 
 extern JS_PUBLIC_API(JSRuntime *)
 JS_GetRuntime(JSContext *cx);
 
+extern JS_PUBLIC_API(JSRuntime *)
+JS_GetParentRuntime(JSContext *cx);
+
 JS_PUBLIC_API(void)
 JS_SetRuntimePrivate(JSRuntime *rt, void *data);
 
 extern JS_PUBLIC_API(void)
 JS_BeginRequest(JSContext *cx);
 
 extern JS_PUBLIC_API(void)
 JS_EndRequest(JSContext *cx);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3272,18 +3272,17 @@ js::NewDenseCopiedArray(JSContext *cx, u
 
     if (values)
         arr->initDenseElements(0, values, length);
 
     return arr;
 }
 
 ArrayObject *
-js::NewDenseCopiedArrayWithTemplate(JSContext *cx, uint32_t length, const Value *values,
-                                    JSObject *templateObject)
+js::NewDenseAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject)
 {
     gc::AllocKind allocKind = GuessArrayGCKind(length);
     JS_ASSERT(CanBeFinalizedInBackground(allocKind, &ArrayObject::class_));
     allocKind = GetBackgroundAllocKind(allocKind);
 
     RootedTypeObject type(cx, templateObject->type());
     if (!type)
         return nullptr;
@@ -3295,19 +3294,16 @@ js::NewDenseCopiedArrayWithTemplate(JSCo
     gc::InitialHeap heap = GetInitialHeap(GenericObject, &ArrayObject::class_);
     Rooted<ArrayObject *> arr(cx, JSObject::createArray(cx, allocKind, heap, shape, type, length));
     if (!arr)
         return nullptr;
 
     if (!EnsureNewArrayElements(cx, arr, length))
         return nullptr;
 
-    arr->setDenseInitializedLength(length);
-    arr->initDenseElements(0, values, length);
-
     probes::CreateObject(cx, arr);
 
     return arr;
 }
 
 #ifdef DEBUG
 bool
 js_ArrayInfo(JSContext *cx, unsigned argc, Value *vp)
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -65,23 +65,20 @@ NewDenseUnallocatedArray(ExclusiveContex
 extern ArrayObject *
 NewDenseCopiedArray(JSContext *cx, uint32_t length, HandleObject src, uint32_t elementOffset, JSObject *proto = nullptr);
 
 /* Create a dense array from the given array values, which must be rooted */
 extern ArrayObject *
 NewDenseCopiedArray(JSContext *cx, uint32_t length, const Value *values, JSObject *proto = nullptr,
                     NewObjectKind newKind = GenericObject);
 
-/*
- * Create a dense array based on templateObject from the given array values,
- * which must be rooted.
- */
+/* Create a dense array based on templateObject with the given length. */
 extern ArrayObject *
-NewDenseCopiedArrayWithTemplate(JSContext *cx, uint32_t length, const Value *values,
-                                JSObject *templateObject);
+NewDenseAllocatedArrayWithTemplate(JSContext *cx, uint32_t length, JSObject *templateObject);
+
 /*
  * Determines whether a write to the given element on |obj| should fail because
  * |obj| is an Array with a non-writable length, and writing that element would
  * increase the length of the array.
  */
 extern bool
 WouldDefinePastNonwritableLength(ThreadSafeContext *cx,
                                  HandleObject obj, uint32_t index, bool strict,
--- a/js/src/jsatom.cpp
+++ b/js/src/jsatom.cpp
@@ -99,86 +99,97 @@ const char js_super_str[]           = "s
 const char js_switch_str[]          = "switch";
 const char js_this_str[]            = "this";
 const char js_try_str[]             = "try";
 const char js_typeof_str[]          = "typeof";
 const char js_void_str[]            = "void";
 const char js_while_str[]           = "while";
 const char js_with_str[]            = "with";
 
-/*
- * For a browser build from 2007-08-09 after the browser starts up there are
- * just 55 double atoms, but over 15000 string atoms. Not to penalize more
- * economical embeddings allocating too much memory initially we initialize
- * atomized strings with just 1K entries.
- */
-#define JS_STRING_HASH_COUNT   1024
-
-bool
-js::InitAtoms(JSRuntime *rt)
-{
-    AutoLockForExclusiveAccess lock(rt);
-    return rt->atoms().init(JS_STRING_HASH_COUNT);
-}
-
-void
-js::FinishAtoms(JSRuntime *rt)
-{
-    AtomSet &atoms = rt->atoms();
-    if (!atoms.initialized()) {
-        /*
-         * We are called with uninitialized state when JS_NewRuntime fails and
-         * calls JS_DestroyRuntime on a partially initialized runtime.
-         */
-        return;
-    }
-
-    FreeOp fop(rt, false);
-    for (AtomSet::Range r = atoms.all(); !r.empty(); r.popFront())
-        r.front().asPtr()->finalize(&fop);
-}
+// Use a low initial capacity for atom hash tables to avoid penalizing runtimes
+// which create a small number of atoms.
+static const uint32_t JS_STRING_HASH_COUNT = 64;
 
 struct CommonNameInfo
 {
     const char *str;
     size_t length;
 };
 
 bool
-js::InitCommonNames(JSContext *cx)
+JSRuntime::initializeAtoms(JSContext *cx)
 {
+    atoms_ = cx->new_<AtomSet>();
+    if (!atoms_ || !atoms_->init(JS_STRING_HASH_COUNT))
+        return false;
+
+    if (parentRuntime) {
+        staticStrings = parentRuntime->staticStrings;
+        commonNames = parentRuntime->commonNames;
+        emptyString = parentRuntime->emptyString;
+        permanentAtoms = parentRuntime->permanentAtoms;
+        return true;
+    }
+
+    permanentAtoms = cx->new_<AtomSet>();
+    if (!permanentAtoms || !permanentAtoms->init(JS_STRING_HASH_COUNT))
+        return false;
+
+    staticStrings = cx->new_<StaticStrings>();
+    if (!staticStrings || !staticStrings->init(cx))
+        return false;
+
     static const CommonNameInfo cachedNames[] = {
 #define COMMON_NAME_INFO(idpart, id, text) { js_##idpart##_str, sizeof(text) - 1 },
         FOR_EACH_COMMON_PROPERTYNAME(COMMON_NAME_INFO)
 #undef COMMON_NAME_INFO
 #define COMMON_NAME_INFO(name, code, init, clasp) { js_##name##_str, sizeof(#name) - 1 },
         JS_FOR_EACH_PROTOTYPE(COMMON_NAME_INFO)
 #undef COMMON_NAME_INFO
     };
 
-    FixedHeapPtr<PropertyName> *names = &cx->runtime()->firstCachedName;
+    commonNames = cx->new_<JSAtomState>();
+    if (!commonNames)
+        return false;
+
+    FixedHeapPtr<PropertyName> *names = reinterpret_cast<FixedHeapPtr<PropertyName> *>(commonNames);
     for (size_t i = 0; i < ArrayLength(cachedNames); i++, names++) {
         JSAtom *atom = Atomize(cx, cachedNames[i].str, cachedNames[i].length, InternAtom);
         if (!atom)
             return false;
         names->init(atom->asPropertyName());
     }
-    JS_ASSERT(uintptr_t(names) == uintptr_t(&cx->runtime()->atomState + 1));
+    JS_ASSERT(uintptr_t(names) == uintptr_t(commonNames + 1));
 
-    cx->runtime()->emptyString = cx->names().empty;
+    emptyString = commonNames->empty;
     return true;
 }
 
 void
-js::FinishCommonNames(JSRuntime *rt)
+JSRuntime::finishAtoms()
 {
-    rt->emptyString = nullptr;
-#ifdef DEBUG
-    memset(&rt->atomState, JS_FREE_PATTERN, sizeof(JSAtomState));
-#endif
+    if (atoms_)
+        js_delete(atoms_);
+
+    if (!parentRuntime) {
+        if (staticStrings)
+            js_delete(staticStrings);
+
+        if (commonNames)
+            js_delete(commonNames);
+
+        if (permanentAtoms)
+            js_delete(permanentAtoms);
+    }
+
+    atoms_ = nullptr;
+    staticStrings = nullptr;
+    commonNames = nullptr;
+    permanentAtoms = nullptr;
+    emptyString = nullptr;
 }
 
 void
 js::MarkAtoms(JSTracer *trc)
 {
     JSRuntime *rt = trc->runtime;
     for (AtomSet::Enum e(rt->atoms()); !e.empty(); e.popFront()) {
         const AtomStateEntry &entry = e.front();
@@ -189,41 +200,97 @@ js::MarkAtoms(JSTracer *trc)
         bool tagged = entry.isTagged();
         MarkStringRoot(trc, &atom, "interned_atom");
         if (entry.asPtr() != atom)
             e.rekeyFront(AtomHasher::Lookup(atom), AtomStateEntry(atom, tagged));
     }
 }
 
 void
-js::SweepAtoms(JSRuntime *rt)
+js::MarkPermanentAtoms(JSTracer *trc)
 {
-    for (AtomSet::Enum e(rt->atoms()); !e.empty(); e.popFront()) {
+    JSRuntime *rt = trc->runtime;
+
+    // Permanent atoms only need to be marked in the runtime which owns them.
+    if (rt->parentRuntime)
+        return;
+
+    // Static strings are not included in the permanent atoms table.
+    if (rt->staticStrings)
+        rt->staticStrings->trace(trc);
+
+    if (rt->permanentAtoms) {
+        for (AtomSet::Enum e(*rt->permanentAtoms); !e.empty(); e.popFront()) {
+            const AtomStateEntry &entry = e.front();
+
+            JSAtom *atom = entry.asPtr();
+            MarkPermanentAtom(trc, atom, "permanent_table");
+        }
+    }
+}
+
+void
+JSRuntime::sweepAtoms()
+{
+    if (!atoms_)
+        return;
+
+    for (AtomSet::Enum e(*atoms_); !e.empty(); e.popFront()) {
         AtomStateEntry entry = e.front();
         JSAtom *atom = entry.asPtr();
         bool isDying = IsStringAboutToBeFinalized(&atom);
 
         /* Pinned or interned key cannot be finalized. */
-        JS_ASSERT_IF(rt->hasContexts() && entry.isTagged(), !isDying);
+        JS_ASSERT_IF(hasContexts() && entry.isTagged(), !isDying);
 
         if (isDying)
             e.removeFront();
     }
 }
 
 bool
+JSRuntime::transformToPermanentAtoms()
+{
+    JS_ASSERT(!parentRuntime);
+
+    // All static strings were created as permanent atoms, now move the contents
+    // of the atoms table into permanentAtoms and mark each as permanent.
+
+    JS_ASSERT(permanentAtoms && permanentAtoms->empty());
+
+    AtomSet *temp = atoms_;
+    atoms_ = permanentAtoms;
+    permanentAtoms = temp;
+
+    for (AtomSet::Enum e(*permanentAtoms); !e.empty(); e.popFront()) {
+        AtomStateEntry entry = e.front();
+        JSAtom *atom = entry.asPtr();
+        atom->morphIntoPermanentAtom();
+    }
+
+    return true;
+}
+
+bool
 AtomIsInterned(JSContext *cx, JSAtom *atom)
 {
     /* We treat static strings as interned because they're never collected. */
     if (StaticStrings::isStatic(atom))
         return true;
 
+    AtomHasher::Lookup lookup(atom);
+
+    /* Likewise, permanent strings are considered to be interned. */
+    AtomSet::Ptr p = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
+    if (p)
+        return true;
+
     AutoLockForExclusiveAccess lock(cx);
 
-    AtomSet::Ptr p = cx->runtime()->atoms().lookup(atom);
+    p = cx->runtime()->atoms().lookup(lookup);
     if (!p)
         return false;
 
     return p->isTagged();
 }
 
 /*
  * When the jschars reside in a freshly allocated buffer the memory can be used
@@ -236,26 +303,34 @@ AtomizeAndTakeOwnership(ExclusiveContext
 {
     JS_ASSERT(tbchars[length] == 0);
 
     if (JSAtom *s = cx->staticStrings().lookup(tbchars, length)) {
         js_free(tbchars);
         return s;
     }
 
+    AtomHasher::Lookup lookup(tbchars, length);
+
+    AtomSet::Ptr pp = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
+    if (pp) {
+        js_free(tbchars);
+        return pp->asPtr();
+    }
+
     AutoLockForExclusiveAccess lock(cx);
 
     /*
      * If a GC occurs at js_NewStringCopy then |p| will still have the correct
      * hash, allowing us to avoid rehashing it. Even though the hash is
      * unchanged, we need to re-lookup the table position because a last-ditch
      * GC will potentially free some table entries.
      */
     AtomSet& atoms = cx->atoms();
-    AtomSet::AddPtr p = atoms.lookupForAdd(AtomHasher::Lookup(tbchars, length));
+    AtomSet::AddPtr p = atoms.lookupForAdd(lookup);
     SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
     if (p) {
         JSAtom *atom = p->asPtr();
         p->setTagged(bool(ib));
         js_free(tbchars);
         return atom;
     }
 
@@ -265,44 +340,49 @@ AtomizeAndTakeOwnership(ExclusiveContext
     if (!flat) {
         js_free(tbchars);
         js_ReportOutOfMemory(cx);
         return nullptr;
     }
 
     JSAtom *atom = flat->morphAtomizedStringIntoAtom();
 
-    if (!atoms.relookupOrAdd(p, AtomHasher::Lookup(tbchars, length),
-                             AtomStateEntry(atom, bool(ib)))) {
+    if (!atoms.relookupOrAdd(p, lookup, AtomStateEntry(atom, bool(ib)))) {
         js_ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
         return nullptr;
     }
 
     return atom;
 }
 
 /* |tbchars| must not point into an inline or short string. */
 MOZ_ALWAYS_INLINE
 static JSAtom *
 AtomizeAndCopyChars(ExclusiveContext *cx, const jschar *tbchars, size_t length, InternBehavior ib)
 {
     if (JSAtom *s = cx->staticStrings().lookup(tbchars, length))
          return s;
 
+    AtomHasher::Lookup lookup(tbchars, length);
+
+    AtomSet::Ptr pp = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
+    if (pp)
+        return pp->asPtr();
+
     /*
      * If a GC occurs at js_NewStringCopy then |p| will still have the correct
      * hash, allowing us to avoid rehashing it. Even though the hash is
      * unchanged, we need to re-lookup the table position because a last-ditch
      * GC will potentially free some table entries.
      */
 
     AutoLockForExclusiveAccess lock(cx);
 
     AtomSet& atoms = cx->atoms();
-    AtomSet::AddPtr p = atoms.lookupForAdd(AtomHasher::Lookup(tbchars, length));
+    AtomSet::AddPtr p = atoms.lookupForAdd(lookup);
     SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
     if (p) {
         JSAtom *atom = p->asPtr();
         p->setTagged(bool(ib));
         return atom;
     }
 
     AutoCompartment ac(cx, cx->atomsCompartment());
@@ -310,18 +390,17 @@ AtomizeAndCopyChars(ExclusiveContext *cx
     JSFlatString *flat = js_NewStringCopyN<NoGC>(cx, tbchars, length);
     if (!flat) {
         js_ReportOutOfMemory(cx);
         return nullptr;
     }
 
     JSAtom *atom = flat->morphAtomizedStringIntoAtom();
 
-    if (!atoms.relookupOrAdd(p, AtomHasher::Lookup(tbchars, length),
-                             AtomStateEntry(atom, bool(ib)))) {
+    if (!atoms.relookupOrAdd(p, lookup, AtomStateEntry(atom, bool(ib)))) {
         js_ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
         return nullptr;
     }
 
     return atom;
 }
 
 JSAtom *
@@ -329,19 +408,26 @@ js::AtomizeString(ExclusiveContext *cx, 
                   js::InternBehavior ib /* = js::DoNotInternAtom */)
 {
     if (str->isAtom()) {
         JSAtom &atom = str->asAtom();
         /* N.B. static atoms are effectively always interned. */
         if (ib != InternAtom || js::StaticStrings::isStatic(&atom))
             return &atom;
 
+        AtomHasher::Lookup lookup(&atom);
+
+        /* Likewise, permanent atoms are always interned. */
+        AtomSet::Ptr p = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
+        if (p)
+            return &atom;
+
         AutoLockForExclusiveAccess lock(cx);
 
-        AtomSet::Ptr p = cx->atoms().lookup(AtomHasher::Lookup(&atom));
+        p = cx->atoms().lookup(lookup);
         JS_ASSERT(p); /* Non-static atom must exist in atom state set. */
         JS_ASSERT(p->asPtr() == &atom);
         JS_ASSERT(ib == InternAtom);
         p->setTagged(bool(ib));
         return &atom;
     }
 
     const jschar *chars = str->getChars(cx);
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -84,21 +84,27 @@ class AtomStateEntry
 struct AtomHasher
 {
     struct Lookup
     {
         const jschar    *chars;
         size_t          length;
         const JSAtom    *atom; /* Optional. */
 
-        Lookup(const jschar *chars, size_t length) : chars(chars), length(length), atom(nullptr) {}
+        HashNumber hash;
+
+        Lookup(const jschar *chars, size_t length)
+          : chars(chars), length(length), atom(nullptr)
+        {
+            hash = mozilla::HashString(chars, length);
+        }
         inline Lookup(const JSAtom *atom);
     };
 
-    static HashNumber hash(const Lookup &l) { return mozilla::HashString(l.chars, l.length); }
+    static HashNumber hash(const Lookup &l) { return l.hash; }
     static inline bool match(const AtomStateEntry &entry, const Lookup &lookup);
     static void rekey(AtomStateEntry &k, const AtomStateEntry& newKey) { k = newKey; }
 };
 
 typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;
 
 class PropertyName;
 
@@ -158,44 +164,23 @@ extern const char js_void_str[];
 extern const char js_while_str[];
 extern const char js_with_str[];
 
 namespace js {
 
 extern const char * const TypeStrings[];
 
 /*
- * Initialize atom state. Return true on success, false on failure to allocate
- * memory. The caller must zero rt->atomState before calling this function and
- * only call it after js_InitGC successfully returns.
- */
-extern bool
-InitAtoms(JSRuntime *rt);
-
-/*
- * Free and clear atom state including any interned string atoms. This
- * function must be called before js_FinishGC.
- */
-extern void
-FinishAtoms(JSRuntime *rt);
-
-/*
  * Atom tracing and garbage collection hooks.
  */
 extern void
 MarkAtoms(JSTracer *trc);
 
 extern void
-SweepAtoms(JSRuntime *rt);
-
-extern bool
-InitCommonNames(JSContext *cx);
-
-extern void
-FinishCommonNames(JSRuntime *rt);
+MarkPermanentAtoms(JSTracer *trc);
 
 /* N.B. must correspond to boolean tagging behavior. */
 enum InternBehavior
 {
     DoNotInternAtom = false,
     InternAtom = true
 };
 
--- a/js/src/jsatominlines.h
+++ b/js/src/jsatominlines.h
@@ -133,17 +133,19 @@ IdToString(JSContext *cx, jsid id)
         return nullptr;
 
     return str->ensureFlat(cx);
 }
 
 inline
 AtomHasher::Lookup::Lookup(const JSAtom *atom)
   : chars(atom->chars()), length(atom->length()), atom(atom)
-{}
+{
+    hash = mozilla::HashString(chars, length);
+}
 
 inline bool
 AtomHasher::match(const AtomStateEntry &entry, const Lookup &lookup)
 {
     JSAtom *key = entry.asPtr();
     if (lookup.atom)
         return lookup.atom == key;
     if (key->length() != lookup.length)
@@ -171,17 +173,17 @@ ClassName(JSProtoKey key, JSAtomState &a
                      sizeof(JSAtomState));
     JS_STATIC_ASSERT(JSProto_Null == 0);
     return (&atomState.Null)[key];
 }
 
 inline Handle<PropertyName*>
 ClassName(JSProtoKey key, JSRuntime *rt)
 {
-    return ClassName(key, rt->atomState);
+    return ClassName(key, *rt->commonNames);
 }
 
 inline Handle<PropertyName*>
 ClassName(JSProtoKey key, ExclusiveContext *cx)
 {
     return ClassName(key, cx->names());
 }
 
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -189,29 +189,31 @@ js::NewContext(JSRuntime *rt, size_t sta
      * steps should fail, the runtime will be left in a partially initialized
      * state, with zeroes and nulls stored in the default-initialized remainder
      * of the struct.
      */
     if (!rt->haveCreatedContext) {
 #ifdef JS_THREADSAFE
         JS_BeginRequest(cx);
 #endif
-        bool ok = rt->staticStrings.init(cx);
-        if (ok)
-            ok = InitCommonNames(cx);
+        bool ok = rt->initializeAtoms(cx);
         if (ok)
             ok = rt->initSelfHosting(cx);
 
+        if (ok && !rt->parentRuntime)
+            ok = rt->transformToPermanentAtoms();
+
 #ifdef JS_THREADSAFE
         JS_EndRequest(cx);
 #endif
         if (!ok) {
             DestroyContext(cx, DCM_NEW_FAILED);
             return nullptr;
         }
+
         rt->haveCreatedContext = true;
     }
 
     JSContextCallback cxCallback = rt->cxCallback;
     if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW, rt->cxCallbackData)) {
         DestroyContext(cx, DCM_NEW_FAILED);
         return nullptr;
     }
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -271,18 +271,19 @@ struct ThreadSafeContext : ContextFriend
         runtime_->updateMallocCounter(zone_, nbytes);
     }
 
     void reportAllocationOverflow() {
         js_ReportAllocationOverflow(this);
     }
 
     // Accessors for immutable runtime data.
-    JSAtomState &names() { return runtime_->atomState; }
-    StaticStrings &staticStrings() { return runtime_->staticStrings; }
+    JSAtomState &names() { return *runtime_->commonNames; }
+    StaticStrings &staticStrings() { return *runtime_->staticStrings; }
+    AtomSet &permanentAtoms() { return *runtime_->permanentAtoms; }
     const JS::AsmJSCacheOps &asmJSCacheOps() { return runtime_->asmJSCacheOps; }
     PropertyName *emptyString() { return runtime_->emptyString; }
     FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); }
     bool useHelperThreads() { return runtime_->useHelperThreads(); }
     void *runtimeAddressForJit() { return runtime_; }
     void *stackLimitAddress(StackKind kind) { return &runtime_->mainThread.nativeStackLimit[kind]; }
     void *stackLimitAddressForJitCode(StackKind kind);
     size_t gcSystemPageSize() { return runtime_->gcSystemPageSize; }
--- a/js/src/jscrashreport.cpp
+++ b/js/src/jscrashreport.cpp
@@ -211,41 +211,49 @@ Ring::copyBytes(void *data, size_t size)
         js_memcpy(&buffer[offset], data, size);
         offset += size;
     }
 }
 
 } /* namespace crash */
 } /* namespace js */
 
+#ifdef JS_CRASH_DIAGNOSTICS
 static bool gInitialized;
 
 static Stack gGCStack(JS_CRASH_STACK_GC);
 static Stack gErrorStack(JS_CRASH_STACK_ERROR);
 static Ring gRingBuffer(JS_CRASH_RING);
+#endif
 
 void
 js::crash::SnapshotGCStack()
 {
+#ifdef JS_CRASH_DIAGNOSTICS
     if (gInitialized)
         gGCStack.snapshot();
+#endif
 }
 
 void
 js::crash::SnapshotErrorStack()
 {
+#ifdef JS_CRASH_DIAGNOSTICS
     if (gInitialized)
         gErrorStack.snapshot();
+#endif
 }
 
 void
 js::crash::SaveCrashData(uint64_t tag, void *ptr, size_t size)
 {
+#ifdef JS_CRASH_DIAGNOSTICS
     if (gInitialized)
         gRingBuffer.push(tag, ptr, size);
+#endif
 }
 
 JS_PUBLIC_API(void)
 JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback)
 {
 #ifdef JS_CRASH_DIAGNOSTICS
     if (!gInitialized) {
         gInitialized = true;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -232,19 +232,25 @@ ComputeStackString(JSContext *cx)
             /* Now the filename. */
             RootedScript script(cx, i.script());
             const char *cfilename = script->filename();
             if (!cfilename)
                 cfilename = "";
             if (!sb.appendInflated(cfilename, strlen(cfilename)))
                 return nullptr;
 
-            /* Finally, : followed by the line number and a newline. */
-            uint32_t line = PCToLineNumber(script, i.pc());
-            if (!sb.append(':') || !NumberValueToStringBuffer(cx, NumberValue(line), sb) ||
+            uint32_t column = 0;
+            uint32_t line = PCToLineNumber(script, i.pc(), &column);
+            // Now the line number
+            if (!sb.append(':') || !NumberValueToStringBuffer(cx, NumberValue(line), sb))
+                return nullptr;
+
+            // Finally, : followed by the column number (1-based, as in other browsers)
+            // and a newline.
+            if (!sb.append(':') || !NumberValueToStringBuffer(cx, NumberValue(column + 1), sb) ||
                 !sb.append('\n'))
             {
                 return nullptr;
             }
 
             /*
              * Cut off the stack if it gets too deep (most commonly for
              * infinite recursion errors).
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -65,17 +65,17 @@ JS_SetGrayGCRootsTracer(JSRuntime *rt, J
     rt->gcGrayRootTracer.op = traceOp;
     rt->gcGrayRootTracer.data = data;
 }
 
 JS_FRIEND_API(JSString *)
 JS_GetAnonymousString(JSRuntime *rt)
 {
     JS_ASSERT(rt->hasContexts());
-    return rt->atomState.anonymous;
+    return rt->commonNames->anonymous;
 }
 
 JS_FRIEND_API(void)
 JS_SetIsWorkerRuntime(JSRuntime *rt)
 {
     rt->setIsWorkerRuntime();
 }
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -175,17 +175,17 @@ fun_enumerate(JSContext *cx, HandleObjec
         return false;
 
     id = NameToId(cx->names().name);
     if (!JSObject::hasProperty(cx, obj, id, &found, 0))
         return false;
 
     for (unsigned i = 0; i < ArrayLength(poisonPillProps); i++) {
         const uint16_t offset = poisonPillProps[i];
-        id = NameToId(AtomStateOffsetToName(cx->runtime()->atomState, offset));
+        id = NameToId(AtomStateOffsetToName(cx->names(), offset));
         if (!JSObject::hasProperty(cx, obj, id, &found, 0))
             return false;
     }
 
     return true;
 }
 
 static JSObject *
@@ -315,17 +315,17 @@ js::fun_resolve(JSContext *cx, HandleObj
         }
         objp.set(fun);
         return true;
     }
 
     for (unsigned i = 0; i < ArrayLength(poisonPillProps); i++) {
         const uint16_t offset = poisonPillProps[i];
 
-        if (JSID_IS_ATOM(id, AtomStateOffsetToName(cx->runtime()->atomState, offset))) {
+        if (JSID_IS_ATOM(id, AtomStateOffsetToName(cx->names(), offset))) {
             JS_ASSERT(!IsInternalFunctionObject(fun));
 
             PropertyOp getter;
             StrictPropertyOp setter;
             unsigned attrs = JSPROP_PERMANENT | JSPROP_SHARED;
             if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
                 return false;
             if (fun->isInterpreted() ? fun->strict() : fun->isBoundFunction()) {
@@ -352,45 +352,66 @@ js::fun_resolve(JSContext *cx, HandleObj
 }
 
 template<XDRMode mode>
 bool
 js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
                            MutableHandleObject objp)
 {
     enum FirstWordFlag {
-        HasAtom = 0x1,
-        IsStarGenerator = 0x2
+        HasAtom             = 0x1,
+        IsStarGenerator     = 0x2,
+        IsLazy              = 0x4,
+        HasSingletonType    = 0x8
     };
 
     /* NB: Keep this in sync with CloneFunctionAndScript. */
     RootedAtom atom(xdr->cx());
     uint32_t firstword = 0;        /* bitmask of FirstWordFlag */
     uint32_t flagsword = 0;        /* word for argument count and fun->flags */
 
     JSContext *cx = xdr->cx();
     RootedFunction fun(cx);
     RootedScript script(cx);
+    Rooted<LazyScript *> lazy(cx);
+
     if (mode == XDR_ENCODE) {
         fun = &objp->as<JSFunction>();
         if (!fun->isInterpreted()) {
             JSAutoByteString funNameBytes;
             if (const char *name = GetFunctionNameBytes(cx, fun, &funNameBytes)) {
                 JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                                      JSMSG_NOT_SCRIPTED_FUNCTION, name);
             }
             return false;
         }
+
         if (fun->atom() || fun->hasGuessedAtom())
             firstword |= HasAtom;
+
         if (fun->isStarGenerator())
             firstword |= IsStarGenerator;
-        script = fun->getOrCreateScript(cx);
-        if (!script)
-            return false;
+
+        if (fun->isInterpretedLazy()) {
+            // This can only happen for re-lazified cloned functions, so this
+            // does not apply to any JSFunction produced by the parser, only to
+            // JSFunction created by the runtime.
+            JS_ASSERT(!fun->lazyScript()->maybeScript());
+
+            // Encode a lazy script.
+            firstword |= IsLazy;
+            lazy = fun->lazyScript();
+        } else {
+            // Encode the script.
+            script = fun->nonLazyScript();
+        }
+
+        if (fun->hasSingletonType())
+            firstword |= HasSingletonType;
+
         atom = fun->displayAtom();
         flagsword = (fun->nargs() << 16) | fun->flags();
     }
 
     if (!xdr->codeUint32(&firstword))
         return false;
 
     if (mode == XDR_DECODE) {
@@ -409,28 +430,39 @@ js::XDRInterpretedFunction(XDRState<mode
         script = nullptr;
     }
 
     if ((firstword & HasAtom) && !XDRAtom(xdr, &atom))
         return false;
     if (!xdr->codeUint32(&flagsword))
         return false;
 
-    if (!XDRScript(xdr, enclosingScope, enclosingScript, fun, &script))
-        return false;
+    if (firstword & IsLazy) {
+        if (!XDRLazyScript(xdr, enclosingScope, enclosingScript, fun, &lazy))
+            return false;
+    } else {
+        if (!XDRScript(xdr, enclosingScope, enclosingScript, fun, &script))
+            return false;
+    }
 
     if (mode == XDR_DECODE) {
         fun->setArgCount(flagsword >> 16);
         fun->setFlags(uint16_t(flagsword));
         fun->initAtom(atom);
-        fun->initScript(script);
-        script->setFunction(fun);
-        if (!JSFunction::setTypeForScriptedFunction(cx, fun))
+        if (firstword & IsLazy) {
+            fun->initLazyScript(lazy);
+        } else {
+            fun->initScript(script);
+            script->setFunction(fun);
+            JS_ASSERT(fun->nargs() == script->bindings.numArgs());
+        }
+
+        bool singleton = firstword & HasSingletonType;
+        if (!JSFunction::setTypeForScriptedFunction(cx, fun, singleton))
             return false;
-        JS_ASSERT(fun->nargs() == fun->nonLazyScript()->bindings.numArgs());
         objp.set(fun);
     }
 
     return true;
 }
 
 template bool
 js::XDRInterpretedFunction(XDRState<XDR_ENCODE> *, HandleObject, HandleScript, MutableHandleObject);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2433,22 +2433,21 @@ GCHelperThread::init()
     backgroundAllocation = (GetCPUCount() >= 2);
 #endif /* JS_THREADSAFE */
     return true;
 }
 
 void
 GCHelperThread::finish()
 {
-    if (!rt->useHelperThreads()) {
+    if (!rt->useHelperThreads() || !rt->gcLock) {
         JS_ASSERT(state == IDLE);
         return;
     }
 
-
 #ifdef JS_THREADSAFE
     PRThread *join = nullptr;
     {
         AutoLockGC lock(rt);
         if (thread && state != SHUTDOWN) {
             /*
              * We cannot be in the ALLOCATING or CANCEL_ALLOCATION states as
              * the allocations should have been stopped during the last GC.
@@ -3135,17 +3134,17 @@ BeginMarkPhase(JSRuntime *rt)
     }
 
     /*
      * For black roots, code in gc/Marking.cpp will already have set maybeAlive
      * during MarkRuntime.
      */
 
     for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
-        if (!zone->maybeAlive)
+        if (!zone->maybeAlive && !rt->isAtomsZone(zone))
             zone->scheduledForDestruction = true;
     }
     rt->gcFoundBlackGrayEdges = false;
 
     return true;
 }
 
 template <class CompartmentIterT>
@@ -3915,17 +3914,17 @@ BeginSweepingZoneGroup(JSRuntime *rt)
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_START);
         if (rt->gcFinalizeCallback)
             rt->gcFinalizeCallback(&fop, JSFINALIZE_GROUP_START, !rt->gcIsFull /* unused */);
     }
 
     if (sweepingAtoms) {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_ATOMS);
-        SweepAtoms(rt);
+        rt->sweepAtoms();
     }
 
     /* Prune out dead views from ArrayBuffer's view lists. */
     for (GCCompartmentGroupIter c(rt); !c.done(); c.next())
         ArrayBufferObject::sweep(c);
 
     /* Collect watch points associated with unreachable objects. */
     WatchpointMap::sweepAll(rt);
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -92,17 +92,17 @@ ShouldNurseryAllocate(const Nursery &nur
 #endif
 
 inline JSGCTraceKind
 GetGCThingTraceKind(const void *thing)
 {
     JS_ASSERT(thing);
     const Cell *cell = static_cast<const Cell *>(thing);
 #ifdef JSGC_GENERATIONAL
-    if (IsInsideNursery(cell->runtimeFromMainThread(), cell))
+    if (IsInsideNursery(cell->runtimeFromAnyThread(), cell))
         return JSTRACE_OBJECT;
 #endif
     return MapAllocToTraceKind(cell->tenuredGetAllocKind());
 }
 
 static inline void
 GCPoke(JSRuntime *rt)
 {
--- a/js/src/jsproxy.cpp
+++ b/js/src/jsproxy.cpp
@@ -1192,17 +1192,17 @@ NormalizePropertyDescriptor(JSContext *c
     AutoIdVector props(cx);
     if (!GetPropertyNames(cx, attributes, 0, &props))
         return false;
     size_t n = props.length();
     for (size_t i = 0; i < n; ++i) {
         RootedId id(cx, props[i]);
         if (JSID_IS_ATOM(id)) {
             JSAtom *atom = JSID_TO_ATOM(id);
-            const JSAtomState &atomState = cx->runtime()->atomState;
+            const JSAtomState &atomState = cx->names();
             if (atom == atomState.value || atom == atomState.writable ||
                 atom == atomState.get || atom == atomState.set ||
                 atom == atomState.enumerable || atom == atomState.configurable)
             {
                 continue;
             }
         }
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -409,16 +409,85 @@ js::XDRScriptConst(XDRState<mode> *xdr, 
 }
 
 template bool
 js::XDRScriptConst(XDRState<XDR_ENCODE> *, MutableHandleValue);
 
 template bool
 js::XDRScriptConst(XDRState<XDR_DECODE> *, MutableHandleValue);
 
+// Code LazyScript's free variables.
+template<XDRMode mode>
+static bool
+XDRLazyFreeVariables(XDRState<mode> *xdr, MutableHandle<LazyScript *> lazy)
+{
+    JSContext *cx = xdr->cx();
+    RootedAtom atom(cx);
+    HeapPtrAtom *freeVariables = lazy->freeVariables();
+    size_t numFreeVariables = lazy->numFreeVariables();
+    for (size_t i = 0; i < numFreeVariables; i++) {
+        if (mode == XDR_ENCODE)
+            atom = freeVariables[i];
+
+        if (!XDRAtom(xdr, &atom))
+            return false;
+
+        if (mode == XDR_DECODE)
+            freeVariables[i] = atom;
+    }
+
+    return true;
+}
+
+// Code the missing part needed to re-create a LazyScript from a JSScript.
+template<XDRMode mode>
+static bool
+XDRRelazificationInfo(XDRState<mode> *xdr, HandleFunction fun, HandleScript script,
+                      MutableHandle<LazyScript *> lazy)
+{
+    MOZ_ASSERT_IF(mode == XDR_ENCODE, script->isRelazifiable() && script->maybeLazyScript());
+    MOZ_ASSERT_IF(mode == XDR_ENCODE, !lazy->numInnerFunctions());
+
+    JSContext *cx = xdr->cx();
+
+    uint64_t packedFields;
+    {
+        uint32_t begin = script->sourceStart();
+        uint32_t end = script->sourceEnd();
+        uint32_t lineno = script->lineno();
+        uint32_t column = script->column();
+
+        if (mode == XDR_ENCODE) {
+            packedFields = lazy->packedFields();
+            MOZ_ASSERT(begin == lazy->begin());
+            MOZ_ASSERT(end == lazy->end());
+            MOZ_ASSERT(lineno == lazy->lineno());
+            MOZ_ASSERT(column == lazy->column());
+        }
+
+        if (!xdr->codeUint64(&packedFields))
+            return false;
+
+        if (mode == XDR_DECODE) {
+            lazy.set(LazyScript::Create(cx, fun, packedFields, begin, end, lineno, column));
+
+            // As opposed to XDRLazyScript, we need to restore the runtime bits
+            // of the script, as we are trying to match the fact this function
+            // has already been parsed and that it would need to be re-lazified.
+            lazy->initRuntimeFields(packedFields);
+        }
+    }
+
+    // Code free variables.
+    if (!XDRLazyFreeVariables(xdr, lazy))
+        return false;
+
+    return true;
+}
+
 static inline uint32_t
 FindScopeObjectIndex(JSScript *script, NestedScopeObject &scope)
 {
     ObjectArray *objects = script->objects();
     HeapPtrObject *vector = objects->vector;
     unsigned length = objects->length;
     for (unsigned i = 0; i < length; ++i) {
         if (vector[i] == &scope)
@@ -458,17 +527,18 @@ js::XDRScript(XDRState<mode> *xdr, Handl
         IsGeneratorExp,
         IsLegacyGenerator,
         IsStarGenerator,
         OwnSource,
         ExplicitUseStrict,
         SelfHosted,
         IsCompileAndGo,
         HasSingleton,
-        TreatAsRunOnce
+        TreatAsRunOnce,
+        HasLazyScript
     };
 
     uint32_t length, lineno, column, nslots;
     uint32_t natoms, nsrcnotes, i;
     uint32_t nconsts, nobjects, nregexps, ntrynotes, nblockscopes;
     uint32_t prologLength, version;
     uint32_t funLength = 0;
     uint32_t nTypeSets = 0;
@@ -556,16 +626,18 @@ js::XDRScript(XDRState<mode> *xdr, Handl
         if (script->isStarGenerator())
             scriptBits |= (1 << IsStarGenerator);
         if (script->compileAndGo())
             scriptBits |= (1 << IsCompileAndGo);
         if (script->hasSingletons())
             scriptBits |= (1 << HasSingleton);
         if (script->treatAsRunOnce())
             scriptBits |= (1 << TreatAsRunOnce);
+        if (script->isRelazifiable())
+            scriptBits |= (1 << HasLazyScript);
     }
 
     if (!xdr->codeUint32(&prologLength))
         return false;
     if (!xdr->codeUint32(&version))
         return false;
 
     // To fuse allocations, we need lengths of all embedded arrays early.
@@ -816,42 +888,48 @@ js::XDRScript(XDRState<mode> *xdr, Handl
                 *objp = tmp;
             }
             break;
           }
 
           case CK_JSFunction: {
             /* Code the nested function's enclosing scope. */
             uint32_t funEnclosingScopeIndex = 0;
+            RootedObject funEnclosingScope(cx);
             if (mode == XDR_ENCODE) {
-                JSScript *innerScript = (*objp)->as<JSFunction>().getOrCreateScript(cx);
-                if (!innerScript)
-                    return false;
-                RootedObject staticScope(cx, innerScript->enclosingStaticScope());
-                StaticScopeIter<NoGC> ssi(staticScope);
+                RootedFunction function(cx, &(*objp)->as<JSFunction>());
+
+                if (function->isInterpretedLazy())
+                    funEnclosingScope = function->lazyScript()->enclosingScope();
+                else
+                    funEnclosingScope = function->nonLazyScript()->enclosingStaticScope();
+
+                StaticScopeIter<NoGC> ssi(funEnclosingScope);
                 if (ssi.done() || ssi.type() == StaticScopeIter<NoGC>::FUNCTION) {
                     JS_ASSERT(ssi.done() == !fun);
                     funEnclosingScopeIndex = UINT32_MAX;
                 } else {
                     funEnclosingScopeIndex = FindScopeObjectIndex(script, ssi.block());
                     JS_ASSERT(funEnclosingScopeIndex < i);
                 }
             }
+
             if (!xdr->codeUint32(&funEnclosingScopeIndex))
                 return false;
-            Rooted<JSObject*> funEnclosingScope(cx);
+
             if (mode == XDR_DECODE) {
                 if (funEnclosingScopeIndex == UINT32_MAX) {
                     funEnclosingScope = fun;
                 } else {
                     JS_ASSERT(funEnclosingScopeIndex < i);
                     funEnclosingScope = script->objects()->vector[funEnclosingScopeIndex];
                 }
             }
 
+            // Code nested function and script.
             RootedObject tmp(cx, *objp);
             if (!XDRInterpretedFunction(xdr, funEnclosingScope, script, &tmp))
                 return false;
             *objp = tmp;
             break;
           }
 
           case CK_JSObject: {
@@ -896,16 +974,28 @@ js::XDRScript(XDRState<mode> *xdr, Handl
             !xdr->codeUint32(&note->start) ||
             !xdr->codeUint32(&note->length) ||
             !xdr->codeUint32(&note->parent))
         {
             return false;
         }
     }
 
+    if (scriptBits & (1 << HasLazyScript)) {
+        Rooted<LazyScript *> lazy(cx);
+        if (mode == XDR_ENCODE)
+            lazy = script->maybeLazyScript();
+
+        if (!XDRRelazificationInfo(xdr, fun, script, &lazy))
+            return false;
+
+        if (mode == XDR_DECODE)
+            script->setLazyScript(lazy);
+    }
+
     if (mode == XDR_DECODE) {
         scriptp.set(script);
 
         /* see BytecodeEmitter::tellDebuggerAboutCompiledScript */
         CallNewScriptHook(cx, script, fun);
         if (!fun) {
             RootedGlobalObject global(cx, script->compileAndGo() ? &script->global() : nullptr);
             Debugger::onNewScript(cx, script, global);
@@ -918,26 +1008,108 @@ js::XDRScript(XDRState<mode> *xdr, Handl
 template bool
 js::XDRScript(XDRState<XDR_ENCODE> *, HandleObject, HandleScript, HandleFunction,
               MutableHandleScript);
 
 template bool
 js::XDRScript(XDRState<XDR_DECODE> *, HandleObject, HandleScript, HandleFunction,
               MutableHandleScript);
 
+template<XDRMode mode>
+bool
+js::XDRLazyScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
+                  HandleFunction fun, MutableHandle<LazyScript *> lazy)
+{
+    JSContext *cx = xdr->cx();
+
+    {
+        uint32_t begin;
+        uint32_t end;
+        uint32_t lineno;
+        uint32_t column;
+        uint64_t packedFields;
+
+        if (mode == XDR_ENCODE) {
+            MOZ_ASSERT(!lazy->maybeScript());
+            MOZ_ASSERT(fun == lazy->functionNonDelazifying());
+
+            begin = lazy->begin();
+            end = lazy->end();
+            lineno = lazy->lineno();
+            column = lazy->column();
+            packedFields = lazy->packedFields();
+        }
+
+        if (!xdr->codeUint32(&begin) || !xdr->codeUint32(&end) ||
+            !xdr->codeUint32(&lineno) || !xdr->codeUint32(&column) ||
+            !xdr->codeUint64(&packedFields))
+        {
+            return false;
+        }
+
+        if (mode == XDR_DECODE)
+            lazy.set(LazyScript::Create(cx, fun, packedFields, begin, end, lineno, column));
+    }
+
+    // Code free variables.
+    if (!XDRLazyFreeVariables(xdr, lazy))
+        return false;
+
+    // Code inner functions.
+    {
+        RootedObject func(cx);
+        HeapPtrFunction *innerFunctions = lazy->innerFunctions();
+        size_t numInnerFunctions = lazy->numInnerFunctions();
+        for (size_t i = 0; i < numInnerFunctions; i++) {
+            if (mode == XDR_ENCODE)
+                func = innerFunctions[i];
+
+            if (!XDRInterpretedFunction(xdr, fun, enclosingScript, &func))
+                return false;
+
+            if (mode == XDR_DECODE)
+                innerFunctions[i] = &func->as<JSFunction>();
+        }
+    }
+
+    if (mode == XDR_DECODE) {
+        JS_ASSERT(!lazy->sourceObject());
+        ScriptSourceObject *sourceObject = &enclosingScript->scriptSourceUnwrap();
+
+        // Set the enclosing scope of the lazy function, this would later be
+        // used to define the environment when the function would be used.
+        lazy->setParent(enclosingScope, sourceObject);
+    }
+
+    return true;
+}
+
+template bool
+js::XDRLazyScript(XDRState<XDR_ENCODE> *, HandleObject, HandleScript,
+                  HandleFunction, MutableHandle<LazyScript *>);
+
+template bool
+js::XDRLazyScript(XDRState<XDR_DECODE> *, HandleObject, HandleScript,
+                  HandleFunction, MutableHandle<LazyScript *>);
+
 void
 JSScript::setSourceObject(JSObject *object)
 {
     JS_ASSERT(compartment() == object->compartment());
     sourceObject_ = object;
 }
 
+js::ScriptSourceObject &
+JSScript::scriptSourceUnwrap() const {
+    return UncheckedUnwrap(sourceObject())->as<ScriptSourceObject>();
+}
+
 js::ScriptSource *
 JSScript::scriptSource() const {
-    return UncheckedUnwrap(sourceObject())->as<ScriptSourceObject>().source();
+    return scriptSourceUnwrap().source();
 }
 
 bool
 JSScript::initScriptCounts(JSContext *cx)
 {
     JS_ASSERT(!hasScriptCounts());
 
     size_t n = 0;
@@ -3237,40 +3409,28 @@ JSScript::formalIsAliased(unsigned argSl
 }
 
 bool
 JSScript::formalLivesInArgumentsObject(unsigned argSlot)
 {
     return argsObjAliasesFormals() && !formalIsAliased(argSlot);
 }
 
-LazyScript::LazyScript(JSFunction *fun, void *table, uint32_t numFreeVariables, uint32_t numInnerFunctions,
-                       JSVersion version, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
+LazyScript::LazyScript(JSFunction *fun, void *table, uint64_t packedFields, uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
   : script_(nullptr),
     function_(fun),
     enclosingScope_(nullptr),
     sourceObject_(nullptr),
     table_(table),
-    version_(version),
-    numFreeVariables_(numFreeVariables),
-    numInnerFunctions_(numInnerFunctions),
-    generatorKindBits_(GeneratorKindAsBits(NotGenerator)),
-    strict_(false),
-    bindingsAccessedDynamically_(false),
-    hasDebuggerStatement_(false),
-    directlyInsideEval_(false),
-    usesArgumentsAndApply_(false),
-    hasBeenCloned_(false),
-    treatAsRunOnce_(false),
+    packedFields_(packedFields),
     begin_(begin),
     end_(end),
     lineno_(lineno),
     column_(column)
 {
-    JS_ASSERT(this->version() == version);
     JS_ASSERT(begin <= end);
 }
 
 void
 LazyScript::initScript(JSScript *script)
 {
     JS_ASSERT(script && !script_);
     script_ = script;
@@ -3296,40 +3456,116 @@ LazyScript::setParent(JSObject *enclosin
 
 ScriptSourceObject *
 LazyScript::sourceObject() const
 {
     return sourceObject_ ? &sourceObject_->as<ScriptSourceObject>() : nullptr;
 }
 
 /* static */ LazyScript *
-LazyScript::Create(ExclusiveContext *cx, HandleFunction fun,
-                   uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version,
-                   uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
+LazyScript::CreateRaw(ExclusiveContext *cx, HandleFunction fun,
+                      uint64_t packedFields, uint32_t begin, uint32_t end,
+                      uint32_t lineno, uint32_t column)
 {
-    JS_ASSERT(begin <= end);
-
-    size_t bytes = (numFreeVariables * sizeof(HeapPtrAtom))
-                 + (numInnerFunctions * sizeof(HeapPtrFunction));
+    union {
+        PackedView p;
+        uint64_t packed;
+    };
+
+    packed = packedFields;
+
+    // Reset runtime flags to obtain a fresh LazyScript.
+    p.hasBeenCloned = false;
+    p.treatAsRunOnce = false;
+
+    size_t bytes = (p.numFreeVariables * sizeof(HeapPtrAtom))
+                 + (p.numInnerFunctions * sizeof(HeapPtrFunction));
 
     void *table = nullptr;
     if (bytes) {
         table = cx->malloc_(bytes);
         if (!table)
             return nullptr;
     }
 
     LazyScript *res = js_NewGCLazyScript(cx);
     if (!res)
         return nullptr;
 
     cx->compartment()->scheduleDelazificationForDebugMode();
 
-    return new (res) LazyScript(fun, table, numFreeVariables, numInnerFunctions, version,
-                                begin, end, lineno, column);
+    return new (res) LazyScript(fun, table, packed, begin, end, lineno, column);
+}
+
+/* static */ LazyScript *
+LazyScript::CreateRaw(ExclusiveContext *cx, HandleFunction fun,
+                      uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version,
+                      uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
+{
+    union {
+        PackedView p;
+        uint64_t packedFields;
+    };
+
+    p.version = version;
+    p.numFreeVariables = numFreeVariables;
+    p.numInnerFunctions = numInnerFunctions;
+    p.generatorKindBits = GeneratorKindAsBits(NotGenerator);
+    p.strict = false;
+    p.bindingsAccessedDynamically = false;
+    p.hasDebuggerStatement = false;
+    p.directlyInsideEval = false;
+    p.usesArgumentsAndApply = false;
+
+    LazyScript *res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column);
+    JS_ASSERT(res->version() == version);
+    return res;
+}
+
+/* static */ LazyScript *
+LazyScript::Create(ExclusiveContext *cx, HandleFunction fun,
+                   uint64_t packedFields, uint32_t begin, uint32_t end,
+                   uint32_t lineno, uint32_t column)
+{
+    // Dummy atom which is not a valid property name.
+    RootedAtom dummyAtom(cx, cx->names().comma);
+
+    // Dummy function which is not a valid function as this is the one which is
+    // holding this lazy script.
+    HandleFunction dummyFun = fun;
+
+    LazyScript *res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column);
+    if (!res)
+        return nullptr;
+
+    // Fill with dummies, to be GC-safe after the initialization of the free
+    // variables and inner functions.
+    size_t i, num;
+    HeapPtrAtom *variables = res->freeVariables();
+    for (i = 0, num = res->numFreeVariables(); i < num; i++)
+        variables[i].init(dummyAtom);
+
+    HeapPtrFunction *functions = res->innerFunctions();
+    for (i = 0, num = res->numInnerFunctions(); i < num; i++)
+        functions[i].init(dummyFun);
+
+    return res;
+}
+
+void
+LazyScript::initRuntimeFields(uint64_t packedFields)
+{
+    union {
+        PackedView p;
+        uint64_t packed;
+    };
+
+    packed = packedFields;
+    p_.hasBeenCloned = p.hasBeenCloned;
+    p_.treatAsRunOnce = p.treatAsRunOnce;
 }
 
 uint32_t
 LazyScript::staticLevel(JSContext *cx) const
 {
     for (StaticScopeIter<NoGC> ssi(enclosingScope()); !ssi.done(); ssi++) {
         if (ssi.type() == StaticScopeIter<NoGC>::FUNCTION)
             return ssi.funScript()->staticLevel() + 1;
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -590,16 +590,21 @@ template<XDRMode mode>
 bool
 XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
           HandleFunction fun, MutableHandleScript scriptp);
 
 JSScript *
 CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun, HandleScript script,
             NewObjectKind newKind = GenericObject);
 
+template<XDRMode mode>
+bool
+XDRLazyScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
+              HandleFunction fun, MutableHandle<LazyScript *> lazy);
+
 /*
  * Code any constant value.
  */
 template<XDRMode mode>
 bool
 XDRScriptConst(XDRState<mode> *xdr, MutableHandleValue vp);
 
 } /* namespace js */
@@ -1235,16 +1240,17 @@ class JSScript : public js::gc::Barriere
     JSFlatString *sourceData(JSContext *cx);
 
     static bool loadSource(JSContext *cx, js::ScriptSource *ss, bool *worked);
 
     void setSourceObject(JSObject *object);
     JSObject *sourceObject() const {
         return sourceObject_;
     }
+    js::ScriptSourceObject &scriptSourceUnwrap() const;
     js::ScriptSource *scriptSource() const;
     JSPrincipals *originPrincipals() const { return scriptSource()->originPrincipals(); }
     const char *filename() const { return scriptSource()->filename(); }
 
   public:
 
     /* Return whether this script was compiled for 'eval' */
     bool isForEval() { return isCachedEval() || isActiveEval(); }
@@ -1602,49 +1608,74 @@ class LazyScript : public gc::BarrieredC
 
     // Heap allocated table with any free variables or inner functions.
     void *table_;
 
 #if JS_BITS_PER_WORD == 32
     uint32_t padding;
 #endif
 
-    // Assorted bits that should really be in ScriptSourceObject.
-    uint32_t version_ : 8;
+    struct PackedView {
+        // Assorted bits that should really be in ScriptSourceObject.
+        uint32_t version : 8;
 
-    uint32_t numFreeVariables_ : 24;
-    uint32_t numInnerFunctions_ : 23;
+        uint32_t numFreeVariables : 24;
+        uint32_t numInnerFunctions : 23;
 
-    uint32_t generatorKindBits_:2;
+        uint32_t generatorKindBits : 2;
 
-    // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
-    uint32_t strict_ : 1;
-    uint32_t bindingsAccessedDynamically_ : 1;
-    uint32_t hasDebuggerStatement_ : 1;
-    uint32_t directlyInsideEval_:1;
-    uint32_t usesArgumentsAndApply_:1;
-    uint32_t hasBeenCloned_:1;
-    uint32_t treatAsRunOnce_:1;
+        // N.B. These are booleans but need to be uint32_t to pack correctly on MSVC.
+        uint32_t strict : 1;
+        uint32_t bindingsAccessedDynamically : 1;
+        uint32_t hasDebuggerStatement : 1;
+        uint32_t directlyInsideEval : 1;
+        uint32_t usesArgumentsAndApply : 1;
+        uint32_t hasBeenCloned : 1;
+        uint32_t treatAsRunOnce : 1;
+    };
+
+    union {
+        PackedView p_;
+        uint64_t packedFields_;
+    };
 
     // Source location for the script.
     uint32_t begin_;
     uint32_t end_;
     uint32_t lineno_;
     uint32_t column_;
 
-    LazyScript(JSFunction *fun, void *table,
-               uint32_t numFreeVariables, uint32_t numInnerFunctions, JSVersion version,
+    LazyScript(JSFunction *fun, void *table, uint64_t packedFields,
                uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
 
+    // Create a LazyScript without initializing the freeVariables and the
+    // innerFunctions. To be GC-safe, the caller must initialize both vectors
+    // with valid atoms and functions.
+    static LazyScript *CreateRaw(ExclusiveContext *cx, HandleFunction fun,
+                                 uint64_t packedData, uint32_t begin, uint32_t end,
+                                 uint32_t lineno, uint32_t column);
+
   public:
+    // Create a LazyScript without initializing the freeVariables and the
+    // innerFunctions. To be GC-safe, the caller must initialize both vectors
+    // with valid atoms and functions.
+    static LazyScript *CreateRaw(ExclusiveContext *cx, HandleFunction fun,
+                                 uint32_t numFreeVariables, uint32_t numInnerFunctions,
+                                 JSVersion version, uint32_t begin, uint32_t end,
+                                 uint32_t lineno, uint32_t column);
+
+    // Create a LazyScript and initialize the freeVariables and the
+    // innerFunctions with dummy values to be replaced in a later initialization
+    // phase.
     static LazyScript *Create(ExclusiveContext *cx, HandleFunction fun,
-                              uint32_t numFreeVariables, uint32_t numInnerFunctions,
-                              JSVersion version, uint32_t begin, uint32_t end,
+                              uint64_t packedData, uint32_t begin, uint32_t end,
                               uint32_t lineno, uint32_t column);
 
+    void initRuntimeFields(uint64_t packedFields);
+
     inline JSFunction *functionDelazifying(JSContext *cx) const;
     JSFunction *functionNonDelazifying() const {
         return function_;
     }
 
     void initScript(JSScript *script);
     void resetScript();
     JSScript *maybeScript() {
@@ -1658,99 +1689,99 @@ class LazyScript : public gc::BarrieredC
     ScriptSource *scriptSource() const {
         return sourceObject()->source();
     }
     JSPrincipals *originPrincipals() const {
         return scriptSource()->originPrincipals();
     }
     JSVersion version() const {
         JS_STATIC_ASSERT(JSVERSION_UNKNOWN == -1);
-        return (version_ == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(version_);
+        return (p_.version == JS_BIT(8) - 1) ? JSVERSION_UNKNOWN : JSVersion(p_.version);
     }
 
     void setParent(JSObject *enclosingScope, ScriptSourceObject *sourceObject);
 
     uint32_t numFreeVariables() const {
-        return numFreeVariables_;
+        return p_.numFreeVariables;
     }
     HeapPtrAtom *freeVariables() {
         return (HeapPtrAtom *)table_;
     }
 
     uint32_t numInnerFunctions() const {
-        return numInnerFunctions_;
+        return p_.numInnerFunctions;
     }
     HeapPtrFunction *innerFunctions() {
         return (HeapPtrFunction *)&freeVariables()[numFreeVariables()];
     }
 
-    GeneratorKind generatorKind() const { return GeneratorKindFromBits(generatorKindBits_); }
+    GeneratorKind generatorKind() const { return GeneratorKindFromBits(p_.generatorKindBits); }
 
     bool isGenerator() const { return generatorKind() != NotGenerator; }
 
     bool isLegacyGenerator() const { return generatorKind() == LegacyGenerator; }
 
     bool isStarGenerator() const { return generatorKind() == StarGenerator; }
 
     void setGeneratorKind(GeneratorKind kind) {
         // A script only gets its generator kind set as part of initialization,
         // so it can only transition from NotGenerator.
         JS_ASSERT(!isGenerator());
         // Legacy generators cannot currently be lazy.
         JS_ASSERT(kind != LegacyGenerator);
-        generatorKindBits_ = GeneratorKindAsBits(kind);
+        p_.generatorKindBits = GeneratorKindAsBits(kind);
     }
 
     bool strict() const {
-        return strict_;
+        return p_.strict;
     }
     void setStrict() {
-        strict_ = true;
+        p_.strict = true;
     }
 
     bool bindingsAccessedDynamically() const {
-        return bindingsAccessedDynamically_;
+        return p_.bindingsAccessedDynamically;
     }
     void setBindingsAccessedDynamically() {
-        bindingsAccessedDynamically_ = true;
+        p_.bindingsAccessedDynamically = true;
     }
 
     bool hasDebuggerStatement() const {
-        return hasDebuggerStatement_;
+        return p_.hasDebuggerStatement;
     }
     void setHasDebuggerStatement() {
-        hasDebuggerStatement_ = true;
+        p_.hasDebuggerStatement = true;
     }
 
     bool directlyInsideEval() const {
-        return directlyInsideEval_;
+        return p_.directlyInsideEval;
     }
     void setDirectlyInsideEval() {
-        directlyInsideEval_ = true;
+        p_.directlyInsideEval = true;
     }
 
     bool usesArgumentsAndApply() const {
-        return usesArgumentsAndApply_;
+        return p_.usesArgumentsAndApply;
     }
     void setUsesArgumentsAndApply() {
-        usesArgumentsAndApply_ = true;
+        p_.usesArgumentsAndApply = true;
     }
 
     bool hasBeenCloned() const {
-        return hasBeenCloned_;
+        return p_.hasBeenCloned;
     }
     void setHasBeenCloned() {
-        hasBeenCloned_ = true;
+        p_.hasBeenCloned = true;
     }
 
     bool treatAsRunOnce() const {
-        return treatAsRunOnce_;
+        return p_.treatAsRunOnce;
     }
     void setTreatAsRunOnce() {
-        treatAsRunOnce_ = true;
+        p_.treatAsRunOnce = true;
     }
 
     ScriptSource *source() const {
         return sourceObject()->source();
     }
     uint32_t begin() const {
         return begin_;
     }
@@ -1770,16 +1801,20 @@ class LazyScript : public gc::BarrieredC
     void finalize(js::FreeOp *fop);
 
     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_LAZY_SCRIPT; }
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
     {
         return mallocSizeOf(table_);
     }
+
+    uint64_t packedFields() const {
+        return packedFields_;
+    }
 };
 
 /* If this fails, add/remove padding within LazyScript. */
 JS_STATIC_ASSERT(sizeof(LazyScript) % js::gc::CellSize == 0);
 
 /*
  * New-script-hook calling is factored from JSScript::fullyInitFromEmitter() so
  * that it and callers of XDRScript() can share this code.  In the case of
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -388,17 +388,17 @@ js::str_resolve(JSContext *cx, HandleObj
 {
     if (!JSID_IS_INT(id))
         return true;
 
     RootedString str(cx, obj->as<StringObject>().unbox());
 
     int32_t slot = JSID_TO_INT(id);
     if ((size_t)slot < str->length()) {
-        JSString *str1 = cx->runtime()->staticStrings.getUnitStringForElement(cx, str, size_t(slot));
+        JSString *str1 = cx->staticStrings().getUnitStringForElement(cx, str, size_t(slot));
         if (!str1)
             return false;
         RootedValue value(cx, StringValue(str1));
         if (!JSObject::defineElement(cx, obj, uint32_t(slot), value, nullptr, nullptr,
                                      STRING_ELEMENT_ATTRS))
         {
             return false;
         }
@@ -859,17 +859,17 @@ js_str_charAt(JSContext *cx, unsigned ar
         if (args.length() > 0 && !ToInteger(cx, args[0], &d))
             return false;
 
         if (d < 0 || str->length() <= d)
             goto out_of_range;
         i = size_t(d);
     }
 
-    str = cx->runtime()->staticStrings.getUnitStringForElement(cx, str, i);
+    str = cx->staticStrings().getUnitStringForElement(cx, str, i);
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 
   out_of_range:
     args.rval().setString(cx->runtime()->emptyString);
     return true;
@@ -1858,17 +1858,17 @@ DoMatchLocal(JSContext *cx, CallArgs arg
     if (status == RegExpRunStatus_Success_NotFound) {
         args.rval().setNull();
         return true;
     }
 
     res->updateFromMatchPairs(cx, input, matches);
 
     RootedValue rval(cx);
-    if (!CreateRegExpMatchResult(cx, input, chars, charsLen, matches, &rval))
+    if (!CreateRegExpMatchResult(cx, input, matches, &rval))
         return false;
 
     args.rval().set(rval);
     return true;
 }
 
 /* ES5 15.5.4.10 step 8. */
 static bool
@@ -3236,17 +3236,17 @@ SplitHelper(JSContext *cx, Handle<JSLine
 // Fast-path for splitting a string into a character array via split("").
 static ArrayObject *
 CharSplitHelper(JSContext *cx, Handle<JSLinearString*> str, uint32_t limit)
 {
     size_t strLength = str->length();
     if (strLength == 0)
         return NewDenseEmptyArray(cx);
 
-    js::StaticStrings &staticStrings = cx->runtime()->staticStrings;
+    js::StaticStrings &staticStrings = cx->staticStrings();
     uint32_t resultlen = (limit < strLength ? limit : strLength);
 
     AutoValueVector splits(cx);
     if (!splits.reserve(resultlen))
         return nullptr;
 
     for (size_t i = 0; i < resultlen; ++i) {
         JSString *sub = staticStrings.getUnitStringForElement(cx, str, i);
@@ -3541,17 +3541,17 @@ str_slice(JSContext *cx, unsigned argc, 
         size_t begin = args[0].toInt32();
         size_t end = str->length();
         if (begin <= end) {
             size_t length = end - begin;
             if (length == 0) {
                 str = cx->runtime()->emptyString;
             } else {
                 str = (length == 1)
-                      ? cx->runtime()->staticStrings.getUnitStringForElement(cx, str, begin)
+                      ? cx->staticStrings().getUnitStringForElement(cx, str, begin)
                       : js_NewDependentString(cx, str, begin, length);
                 if (!str)
                     return false;
             }
             args.rval().setString(str);
             return true;
         }
     }
@@ -3859,17 +3859,17 @@ js::str_fromCharCode(JSContext *cx, unsi
     CallArgs args = CallArgsFromVp(argc, vp);
 
     JS_ASSERT(args.length() <= ARGS_LENGTH_MAX);
     if (args.length() == 1) {
         uint16_t code;
         if (!ToUint16(cx, args[0], &code))
             return false;
         if (StaticStrings::hasUnit(code)) {
-            args.rval().setString(cx->runtime()->staticStrings.getUnit(code));
+            args.rval().setString(cx->staticStrings().getUnit(code));
             return true;
         }
         args[0].setInt32(code);
     }
     jschar *chars = cx->pod_malloc<jschar>(args.length() + 1);
     if (!chars)
         return false;
     for (unsigned i = 0; i < args.length(); i++) {
@@ -3985,17 +3985,17 @@ js_NewDependentString(JSContext *cx, JSS
     if (!base)
         return nullptr;
 
     if (start == 0 && length == base->length())
         return base;
 
     const jschar *chars = base->chars() + start;
 
-    if (JSLinearString *staticStr = cx->runtime()->staticStrings.lookup(chars, length))
+    if (JSLinearString *staticStr = cx->staticStrings().lookup(chars, length))
         return staticStr;
 
     return JSDependentString::new_(cx, base, chars, length);
 }
 
 template <AllowGC allowGC>
 JSFlatString *
 js_NewStringCopyN(ExclusiveContext *cx, const jschar *s, size_t n)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -188,16 +188,19 @@ enum JSShellErrNum {
 };
 
 static JSContext *
 NewContext(JSRuntime *rt);
 
 static void
 DestroyContext(JSContext *cx, bool withGC);
 
+static JSObject *
+NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options);
+
 static const JSErrorFormatString *
 my_GetErrorMessage(void *userRef, const char *locale, const unsigned errorNumber);
 
 #ifdef EDITLINE
 extern "C" {
 extern JS_EXPORT_API(char *) readline(const char *prompt);
 extern JS_EXPORT_API(void)   add_history(char *line);
 } // extern "C"
@@ -2600,16 +2603,113 @@ EvalInFrame(JSContext *cx, unsigned argc
     bool ok = !!frame.evaluateUCInStackFrame(cx, chars, length,
                                              fpscript->filename(),
                                              JS_PCToLineNumber(cx, fpscript,
                                                                fi.pc()),
                                              MutableHandleValue::fromMarkedLocation(vp));
     return ok;
 }
 
+struct WorkerInput
+{
+    JSRuntime *runtime;
+    jschar *chars;
+    size_t length;
+
+    WorkerInput(JSRuntime *runtime, jschar *chars, size_t length)
+      : runtime(runtime), chars(chars), length(length)
+    {}
+
+    ~WorkerInput() {
+        js_free(chars);
+    }
+};
+
+static void
+WorkerMain(void *arg)
+{
+    WorkerInput *input = (WorkerInput *) arg;
+
+    JSRuntime *rt = JS_NewRuntime(8L * 1024L * 1024L,
+                                  JS_USE_HELPER_THREADS,
+                                  input->runtime);
+    if (!rt) {
+        js_delete(input);
+        return;
+    }
+
+    JSContext *cx = NewContext(rt);
+    if (!cx) {
+        JS_DestroyRuntime(rt);
+        js_delete(input);
+        return;
+    }
+
+    do {
+        JSAutoRequest ar(cx);
+
+        JS::CompartmentOptions compartmentOptions;
+        compartmentOptions.setVersion(JSVERSION_LATEST);
+        RootedObject global(cx, NewGlobalObject(cx, compartmentOptions));
+        if (!global)
+            break;
+
+        JSAutoCompartment ac(cx, global);
+
+        JS::CompileOptions options(cx);
+        options.setFileAndLine("<string>", 1)
+               .setCompileAndGo(true);
+
+        JSScript *script = JS::Compile(cx, global, options,
+                                       input->chars, input->length);
+        if (!script)
+            break;
+        RootedValue result(cx);
+        JS_ExecuteScript(cx, global, script, result.address());
+    } while (0);
+
+    DestroyContext(cx, false);
+    JS_DestroyRuntime(rt);
+
+    js_delete(input);
+}
+
+Vector<PRThread *, 0, SystemAllocPolicy> workerThreads;
+
+static bool
+EvalInWorker(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (argc < 1 || !args[0].isString()) {
+        JS_ReportError(cx, "Invalid arguments to evalInWorker");
+        return false;
+    }
+
+    if (!args[0].toString()->ensureLinear(cx))
+        return false;
+
+    JSLinearString *str = &args[0].toString()->asLinear();
+
+    jschar *chars = (jschar *) js_malloc(str->length() * sizeof(jschar));
+    if (!chars)
+        return false;
+    PodCopy(chars, str->chars(), str->length());
+
+    WorkerInput *input = js_new<WorkerInput>(cx->runtime(), chars, str->length());
+    if (!input)
+        return false;
+
+    PRThread *thread = PR_CreateThread(PR_USER_THREAD, WorkerMain, input,
+                                       PR_PRIORITY_NORMAL, PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
+    if (!thread || !workerThreads.append(thread))
+        return false;
+
+    return true;
+}
+
 static bool
 ShapeOf(JSContext *cx, unsigned argc, JS::Value *vp)
 {
     JS::Value v;
     if (argc < 1 || !((v = JS_ARGV(cx, vp)[0]).isObject())) {
         JS_ReportError(cx, "shapeOf: object expected");
         return false;
     }
@@ -3807,19 +3907,16 @@ WrapWithProto(JSContext *cx, unsigned ar
                                      &Wrapper::singletonWithPrototype, &options);
     if (!wrapped)
         return false;
 
     JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(wrapped));
     return true;
 }
 
-static JSObject *
-NewGlobalObject(JSContext *cx, JS::CompartmentOptions &options);
-
 static bool
 NewGlobal(JSContext *cx, unsigned argc, jsval *vp)
 {
     JS::CompartmentOptions options;
     options.setVersion(JSVERSION_LATEST);
 
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() == 1 && args[0].isObject()) {
@@ -4167,16 +4264,20 @@ static const JSFunctionSpecWithHelp shel
 "  if (s == '' && !o) return new o with eager standard classes\n"
 "  if (s == 'lazy' && !o) return new o with lazy standard classes"),
 
     JS_FN_HELP("evalInFrame", EvalInFrame, 2, 0,
 "evalInFrame(n,str,save)",
 "  Evaluate 'str' in the nth up frame.\n"
 "  If 'save' (default false), save the frame chain."),
 
+    JS_FN_HELP("evalInWorker", EvalInWorker, 1, 0,
+"evalInWorker(str)",
+"  Evaluate 'str' in a separate thread with its own runtime.\n"),
+
     JS_FN_HELP("shapeOf", ShapeOf, 1, 0,
 "shapeOf(obj)",
 "  Get the shape of obj (an implementation detail)."),
 
     JS_FN_HELP("resolver", Resolver, 1, 0,
 "resolver(src[, proto])",
 "  Create object with resolve hook that copies properties\n"
 "  from src. If proto is omitted, use Object.prototype."),
@@ -5947,12 +6048,15 @@ main(int argc, char **argv, char **envp)
 
     gTimeoutFunc = NullValue();
     JS_RemoveValueRootRT(rt, &gTimeoutFunc);
 
     DestroyContext(cx, true);
 
     KillWatchdog();
 
+    for (size_t i = 0; i < workerThreads.length(); i++)
+        PR_JoinThread(workerThreads[i]);
+
     JS_DestroyRuntime(rt);
     JS_ShutDown();
     return result;
 }
new file mode 100644
--- /dev/null
+++ b/js/src/tests/js1_8_5/extensions/column-numbers.js
@@ -0,0 +1,10 @@
+actual   = 'No Error';
+expected = /column-numbers\.js:4:5/;
+try {
+    throw new Error("test");
+}
+catch(ex) {
+    actual = ex.stack;
+    print('Caught exception ' + ex.stack);
+}
+reportMatch(expected, actual, 'column number present');
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -816,17 +816,17 @@ typedef HashSet<GlobalObject *, DefaultH
  * Convenience templates to generic constructor and prototype creation functions
  * for ClassSpecs.
  */
 
 template<JSNative ctor, size_t atomOffset, unsigned length>
 JSObject *
 GenericCreateConstructor(JSContext *cx, JSProtoKey key)
 {
-    JSAtom *atom = AtomStateOffsetToName(cx->runtime()->atomState, atomOffset);
+    JSAtom *atom = AtomStateOffsetToName(cx->names(), atomOffset);
     return cx->global()->createConstructor(cx, ctor, atom, length);
 }
 
 template<const Class *clasp>
 JSObject *
 GenericCreatePrototype(JSContext *cx, JSProtoKey key)
 {
     return cx->global()->createBlankPrototype(cx, clasp);
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -434,17 +434,17 @@ GetElementOperation(JSContext *cx, JSOp 
                     MutableHandleValue res)
 {
     JS_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
 
     uint32_t index;
     if (lref.isString() && IsDefinitelyIndex(rref, &index)) {
         JSString *str = lref.toString();
         if (index < str->length()) {
-            str = cx->runtime()->staticStrings.getUnitStringForElement(cx, str, index);
+            str = cx->staticStrings().getUnitStringForElement(cx, str, index);
             if (!str)
                 return false;
             res.setString(str);
             return true;
         }
     }
 
     bool isObject = lref.isObject();
@@ -453,24 +453,24 @@ GetElementOperation(JSContext *cx, JSOp 
         return false;
     return GetObjectElementOperation(cx, op, obj, isObject, rref, res);
 }
 
 static MOZ_ALWAYS_INLINE JSString *
 TypeOfOperation(const Value &v, JSRuntime *rt)
 {
     JSType type = js::TypeOfValue(v);
-    return TypeName(type, rt->atomState);
+    return TypeName(type, *rt->commonNames);
 }
 
 static inline JSString *
 TypeOfObjectOperation(JSObject *obj, JSRuntime *rt)
 {
     JSType type = js::TypeOfObject(obj);
-    return TypeName(type, rt->atomState);
+    return TypeName(type, *rt->commonNames);
 }
 
 static MOZ_ALWAYS_INLINE bool
 InitElemOperation(JSContext *cx, HandleObject obj, HandleValue idval, HandleValue val)
 {
     JS_ASSERT(!val.isMagic(JS_ELEMENTS_HOLE));
 
     RootedId id(cx);
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -650,20 +650,19 @@ RegExpCompartment::RegExpCompartment(JSR
 
 RegExpCompartment::~RegExpCompartment()
 {
     JS_ASSERT_IF(map_.initialized(), map_.empty());
     JS_ASSERT_IF(inUse_.initialized(), inUse_.empty());
 }
 
 JSObject *
-RegExpCompartment::getOrCreateMatchResultTemplateObject(JSContext *cx)
+RegExpCompartment::createMatchResultTemplateObject(JSContext *cx)
 {
-    if (matchResultTemplateObject_)
-        return matchResultTemplateObject_;
+    JS_ASSERT(!matchResultTemplateObject_);
 
     /* Create template array object */
     RootedObject templateObject(cx, NewDenseUnallocatedArray(cx, 0, nullptr, TenuredObject));
     if (!templateObject)
         return matchResultTemplateObject_; // = nullptr
 
     /* Set dummy index property */
     RootedValue index(cx, Int32Value(0));
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -320,31 +320,37 @@ class RegExpCompartment
 
     /*
      * This is the template object where the result of re.exec() is based on,
      * if there is a result. This is used in CreateRegExpMatchResult to set
      * the input/index properties faster.
      */
     ReadBarriered<JSObject> matchResultTemplateObject_;
 
+    JSObject *createMatchResultTemplateObject(JSContext *cx);
+
   public:
     RegExpCompartment(JSRuntime *rt);
     ~RegExpCompartment();
 
     bool init(JSContext *cx);
     void sweep(JSRuntime *rt);
     void clearTables();
 
     bool get(ExclusiveContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g);
 
     /* Like 'get', but compile 'maybeOpt' (if non-null). */
     bool get(JSContext *cx, HandleAtom source, JSString *maybeOpt, RegExpGuard *g);
 
     /* Get or create template object used to base the result of .exec() on. */
-    JSObject *getOrCreateMatchResultTemplateObject(JSContext *cx);
+    JSObject *getOrCreateMatchResultTemplateObject(JSContext *cx) {
+        if (matchResultTemplateObject_)
+            return matchResultTemplateObject_;
+        return createMatchResultTemplateObject(cx);
+    }
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
 };
 
 class RegExpObject : public JSObject
 {
     static const unsigned LAST_INDEX_SLOT          = 0;
     static const unsigned SOURCE_SLOT              = 1;
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -104,23 +104,24 @@ PerThreadData::init()
 }
 
 static const JSWrapObjectCallbacks DefaultWrapObjectCallbacks = {
     TransparentObjectWrapper,
     nullptr,
     nullptr
 };
 
-JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
+JSRuntime::JSRuntime(JSRuntime *parentRuntime, JSUseHelperThreads useHelperThreads)
   : JS::shadow::Runtime(
 #ifdef JSGC_GENERATIONAL
         &gcStoreBuffer
 #endif
     ),
     mainThread(this),
+    parentRuntime(parentRuntime),
     interrupt(false),
 #if defined(JS_THREADSAFE) && defined(JS_ION)
     interruptPar(false),
 #endif
     handlingSignal(false),
     operationCallback(nullptr),
 #ifdef JS_THREADSAFE
     operationCallbackLock(nullptr),
@@ -270,18 +271,22 @@ JSRuntime::JSRuntime(JSUseHelperThreads 
     thousandsSeparator(0),
     decimalSeparator(0),
     numGrouping(0),
 #endif
     mathCache_(nullptr),
     activeCompilations_(0),
     keepAtoms_(0),
     trustedPrincipals_(nullptr),
+    beingDestroyed_(false),
+    atoms_(nullptr),
     atomsCompartment_(nullptr),
-    beingDestroyed_(false),
+    staticStrings(nullptr),
+    commonNames(nullptr),
+    permanentAtoms(nullptr),
     wrapObjectCallbacks(&DefaultWrapObjectCallbacks),
     preserveWrapperCallback(nullptr),
 #ifdef DEBUG
     noGCOrAllocationCheck(0),
 #endif
     jitSupportsFloatingPoint(false),
     ionPcScriptCache(nullptr),
     threadPool(this),
@@ -301,17 +306,16 @@ JSRuntime::JSRuntime(JSUseHelperThreads 
     liveRuntimesCount++;
 
     setGCMode(JSGC_MODE_GLOBAL);
 
     /* Initialize infallibly first, so we can goto bad and JS_DestroyRuntime. */
     JS_INIT_CLIST(&onNewGlobalObjectWatchers);
 
     PodZero(&debugHooks);
-    PodZero(&atomState);
     PodArrayZero(nativeStackQuota);
     PodZero(&asmJSCacheOps);
 
 #if JS_STACK_GROWTH_DIRECTION > 0
     nativeStackLimit = UINTPTR_MAX;
 #endif
 }
 
@@ -384,19 +388,16 @@ JSRuntime::init(uint32_t maxbytes)
 
     atomsCompartment->isSystem = true;
     atomsZone->isSystem = true;
     atomsZone->setGCLastBytes(8192, GC_NORMAL);
 
     atomsZone.forget();
     this->atomsCompartment_ = atomsCompartment.forget();
 
-    if (!InitAtoms(this))
-        return false;
-
     if (!scriptDataTable_.init())
         return false;
 
     if (!evalCache.init())
         return false;
 
     /* The garbage collector depends on everything before this point being initialized. */
     gcInitialized = true;
@@ -414,16 +415,20 @@ JSRuntime::init(uint32_t maxbytes)
 
     nativeStackBase = GetNativeStackBase();
 
     jitSupportsFloatingPoint = JitSupportsFloatingPoint();
 
 #ifdef JS_ION
     signalHandlersInstalled_ = EnsureAsmJSSignalHandlersInstalled(this);
 #endif
+
+    if (!spsProfiler.init())
+        return false;
+
     return true;
 }
 
 JSRuntime::~JSRuntime()
 {
     JS_ASSERT(!isHeapBusy());
 
     if (gcInitialized) {
@@ -435,28 +440,25 @@ JSRuntime::~JSRuntime()
          * parse tasks. Waiting for AsmJS and compression tasks is done
          * synchronously (on the main thread or during parse tasks), so no
          * explicit canceling is needed for these.
          */
         for (CompartmentsIter comp(this, SkipAtoms); !comp.done(); comp.next())
             CancelOffThreadIonCompile(comp, nullptr);
         CancelOffThreadParses(this);
 
-        /* Poison common names before final GC. */
-        FinishCommonNames(this);
-
         /* Clear debugging state to remove GC roots. */
         for (CompartmentsIter comp(this, SkipAtoms); !comp.done(); comp.next()) {
             comp->clearTraps(defaultFreeOp());
             if (WatchpointMap *wpmap = comp->watchpointMap)
                 wpmap->clear();
         }
 
-        /* Clear the statics table to remove GC roots. */
-        staticStrings.finish();
+        /* Clear atoms to remove GC roots and heap allocations. */
+        finishAtoms();
 
         /*
          * Flag us as being destroyed. This allows the GC to free things like
          * interned atoms and Ion trampolines.
          */
         beingDestroyed_ = true;
 
         /* Allow the GC to release scripts that were being profiled. */
@@ -506,17 +508,16 @@ JSRuntime::~JSRuntime()
 "JS API usage error: %u context%s left in runtime upon JS_DestroyRuntime.\n",
                 cxcount, (cxcount == 1) ? "" : "s");
     }
 #endif
 
 #if !EXPOSE_INTL_API
     FinishRuntimeNumberState(this);
 #endif
-    FinishAtoms(this);
 
     js_FinishGC(this);
     atomsCompartment_ = nullptr;
 
 #ifdef JS_THREADSAFE
     if (gcLock)
         PR_DestroyLock(gcLock);
 #endif
@@ -577,17 +578,23 @@ JSRuntime::resetIonStackLimit()
 void
 JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *rtSizes)
 {
     // Several tables in the runtime enumerated below can be used off thread.
     AutoLockForExclusiveAccess lock(this);
 
     rtSizes->object += mallocSizeOf(this);
 
-    rtSizes->atomsTable += atoms().sizeOfExcludingThis(mallocSizeOf);
+    rtSizes->atomsTable += atoms().sizeOfIncludingThis(mallocSizeOf);
+
+    if (!parentRuntime) {
+        rtSizes->atomsTable += mallocSizeOf(staticStrings);
+        rtSizes->atomsTable += mallocSizeOf(commonNames);
+        rtSizes->atomsTable += permanentAtoms->sizeOfIncludingThis(mallocSizeOf);
+    }
 
     for (ContextIter acx(this); !acx.done(); acx.next())
         rtSizes->contexts += acx->sizeOfIncludingThis(mallocSizeOf);
 
     rtSizes->dtoa += mallocSizeOf(mainThread.dtoaState);
 
     rtSizes->temporary += tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
 
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -667,16 +667,22 @@ struct JSRuntime : public JS::shadow::Ru
      *
      * NB: This field is statically asserted to be at offset
      * sizeof(js::shadow::Runtime). See
      * PerThreadDataFriendFields::getMainThread.
      */
     js::PerThreadData mainThread;
 
     /*
+     * If non-null, another runtime guaranteed to outlive this one and whose
+     * permanent data may be used by this one where possible.
+     */
+    JSRuntime *parentRuntime;
+
+    /*
      * If true, we've been asked to call the operation callback as soon as
      * possible.
      */
     mozilla::Atomic<bool, mozilla::Relaxed> interrupt;
 
 #if defined(JS_THREADSAFE) && defined(JS_ION)
     /*
      * If non-zero, ForkJoin should service an interrupt. This is a separate
@@ -1473,59 +1479,73 @@ struct JSRuntime : public JS::shadow::Ru
     }
 
   private:
     const JSPrincipals  *trustedPrincipals_;
   public:
     void setTrustedPrincipals(const JSPrincipals *p) { trustedPrincipals_ = p; }
     const JSPrincipals *trustedPrincipals() const { return trustedPrincipals_; }
 
-    // Set of all currently-living atoms, and the compartment in which they
-    // reside. The atoms compartment is additionally used to hold runtime
-    // wide Ion code stubs. These may be modified by threads with an
-    // ExclusiveContext and require a lock.
   private:
-    js::AtomSet atoms_;
-    JSCompartment *atomsCompartment_;
     bool beingDestroyed_;
   public:
+    bool isBeingDestroyed() const {
+        return beingDestroyed_;
+    }
+
+  private:
+    // Set of all atoms other than those in permanentAtoms and staticStrings.
+    // This may be modified by threads with an ExclusiveContext and requires
+    // a lock.
+    js::AtomSet *atoms_;
+
+    // Compartment and associated zone containing all atoms in the runtime,
+    // as well as runtime wide IonCode stubs. The contents of this compartment
+    // may be modified by threads with an ExclusiveContext and requires a lock.
+    JSCompartment *atomsCompartment_;
+
+  public:
+    bool initializeAtoms(JSContext *cx);
+    void finishAtoms();
+
+    void sweepAtoms();
+
     js::AtomSet &atoms() {
         JS_ASSERT(currentThreadHasExclusiveAccess());
-        return atoms_;
+        return *atoms_;
     }
     JSCompartment *atomsCompartment() {
         JS_ASSERT(currentThreadHasExclusiveAccess());
         return atomsCompartment_;
     }
 
     bool isAtomsCompartment(JSCompartment *comp) {
         return comp == atomsCompartment_;
     }
 
-    bool isBeingDestroyed() const {
-        return beingDestroyed_;
-    }
-
     // The atoms compartment is the only one in its zone.
     inline bool isAtomsZone(JS::Zone *zone);
 
     bool activeGCInAtomsZone();
 
-    union {
-        /*
-         * Cached pointers to various interned property names, initialized in
-         * order from first to last via the other union arm.
-         */
-        JSAtomState atomState;
+    // Permanent atoms are fixed during initialization of the runtime and are
+    // not modified or collected until the runtime is destroyed. These may be
+    // shared with another, longer living runtime through |parentRuntime| and
+    // can be freely accessed with no locking necessary.
+
+    // Permanent atoms pre-allocated for general use.
+    js::StaticStrings *staticStrings;
 
-        js::FixedHeapPtr<js::PropertyName> firstCachedName;
-    };
+    // Cached pointers to various permanent property names.
+    JSAtomState *commonNames;
 
-    /* Tables of strings that are pre-allocated in the atomsCompartment. */
-    js::StaticStrings   staticStrings;
+    // All permanent atoms in the runtime, other than those in staticStrings.
+    js::AtomSet *permanentAtoms;
+
+    bool transformToPermanentAtoms();
 
     const JSWrapObjectCallbacks            *wrapObjectCallbacks;
     js::PreserveWrapperCallback            preserveWrapperCallback;
 
     // Table of bytecode and other data that may be shared across scripts
     // within the runtime. This may be modified by threads with an
     // ExclusiveContext and requires a lock.
   private:
@@ -1593,17 +1613,17 @@ struct JSRuntime : public JS::shadow::Ru
         ionReturnOverride_ = js::MagicValue(JS_ARG_POISON);
         return v;
     }
     void setIonReturnOverride(const js::Value &v) {
         JS_ASSERT(!hasIonReturnOverride());
         ionReturnOverride_ = v;
     }
 
-    JSRuntime(JSUseHelperThreads useHelperThreads);
+    JSRuntime(JSRuntime *parentRuntime, JSUseHelperThreads useHelperThreads);
     ~JSRuntime();
 
     bool init(uint32_t maxbytes);
 
     JSRuntime *thisFromCtor() { return this; }
 
     void setGCMaxMallocBytes(size_t value);
 
--- a/js/src/vm/SPSProfiler.cpp
+++ b/js/src/vm/SPSProfiler.cpp
@@ -20,34 +20,42 @@ using namespace js;
 using mozilla::DebugOnly;
 
 SPSProfiler::SPSProfiler(JSRuntime *rt)
   : rt(rt),
     stack_(nullptr),
     size_(nullptr),
     max_(0),
     slowAssertions(false),
-    enabled_(false)
+    enabled_(false),
+    lock_(nullptr)
 {
     JS_ASSERT(rt != nullptr);
+}
+
+bool
+SPSProfiler::init()
+{
 #ifdef JS_THREADSAFE
     lock_ = PR_NewLock();
     if (lock_ == nullptr)
-        MOZ_CRASH("Couldn't allocate lock!");
+        return false;
 #endif
+    return true;
 }
 
 SPSProfiler::~SPSProfiler()
 {
     if (strings.initialized()) {
         for (ProfileStringMap::Enum e(strings); !e.empty(); e.popFront())
             js_free(const_cast<char *>(e.front().value()));
     }
 #ifdef JS_THREADSAFE
-    PR_DestroyLock(lock_);
+    if (lock_)
+        PR_DestroyLock(lock_);
 #endif
 }
 
 void
 SPSProfiler::setProfilingStack(ProfileEntry *stack, uint32_t *size, uint32_t max)
 {
     AutoSPSLock lock(lock_);
     JS_ASSERT_IF(size_ && *size_ != 0, !enabled());
--- a/js/src/vm/SPSProfiler.h
+++ b/js/src/vm/SPSProfiler.h
@@ -129,16 +129,18 @@ class SPSProfiler
     const char *allocProfileString(JSScript *script, JSFunction *function);
     void push(const char *string, void *sp, JSScript *script, jsbytecode *pc);
     void pop();
 
   public:
     SPSProfiler(JSRuntime *rt);
     ~SPSProfiler();
 
+    bool init();
+
     uint32_t **addressOfSizePointer() {
         return &size_;
     }
 
     uint32_t *addressOfMaxSize() {
         return &max_;
     }
 
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -99,17 +99,17 @@ js::ScopeCoordinateName(ScopeCoordinateN
         Shape::Range<NoGC> r(shape);
         while (r.front().slot() != sc.slot())
             r.popFront();
         id = r.front().propidRaw();
     }
 
     /* Beware nameless destructuring formal. */
     if (!JSID_IS_ATOM(id))
-        return script->runtimeFromAnyThread()->atomState.empty;
+        return script->runtimeFromAnyThread()->commonNames->empty;
     return JSID_TO_ATOM(id)->asPropertyName();
 }
 
 JSScript *
 js::ScopeCoordinateFunctionScript(JSScript *script, jsbytecode *pc)
 {
     StaticScopeIter<NoGC> ssi(InnermostStaticScope(script, pc));
     uint32_t hops = ScopeCoordinate(pc).hops();
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -584,25 +584,25 @@ StaticStrings::init(JSContext *cx)
     AutoLockForExclusiveAccess lock(cx);
     AutoCompartment ac(cx, cx->runtime()->atomsCompartment());
 
     for (uint32_t i = 0; i < UNIT_STATIC_LIMIT; i++) {
         jschar buffer[] = { jschar(i), '\0' };
         JSFlatString *s = js_NewStringCopyN<NoGC>(cx, buffer, 1);
         if (!s)
             return false;
-        unitStaticTable[i] = s->morphAtomizedStringIntoAtom();
+        unitStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom();
     }
 
     for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) {
         jschar buffer[] = { FROM_SMALL_CHAR(i >> 6), FROM_SMALL_CHAR(i & 0x3F), '\0' };
         JSFlatString *s = js_NewStringCopyN<NoGC>(cx, buffer, 2);
         if (!s)
             return false;
-        length2StaticTable[i] = s->morphAtomizedStringIntoAtom();
+        length2StaticTable[i] = s->morphAtomizedStringIntoPermanentAtom();
     }
 
     for (uint32_t i = 0; i < INT_STATIC_LIMIT; i++) {
         if (i < 10) {
             intStaticTable[i] = unitStaticTable[i + '0'];
         } else if (i < 100) {
             size_t index = ((size_t)TO_SMALL_CHAR((i / 10) + '0') << 6) +
                 TO_SMALL_CHAR((i % 10) + '0');
@@ -610,43 +610,37 @@ StaticStrings::init(JSContext *cx)
         } else {
             jschar buffer[] = { jschar('0' + (i / 100)),
                                 jschar('0' + ((i / 10) % 10)),
                                 jschar('0' + (i % 10)),
                                 '\0' };
             JSFlatString *s = js_NewStringCopyN<NoGC>(cx, buffer, 3);
             if (!s)
                 return false;
-            intStaticTable[i] = s->morphAtomizedStringIntoAtom();
+            intStaticTable[i] = s->morphAtomizedStringIntoPermanentAtom();
         }
     }
 
     return true;
 }
 
 void
 StaticStrings::trace(JSTracer *trc)
 {
     /* These strings never change, so barriers are not needed. */
 
-    for (uint32_t i = 0; i < UNIT_STATIC_LIMIT; i++) {
-        if (unitStaticTable[i])
-            MarkStringUnbarriered(trc, &unitStaticTable[i], "unit-static-string");
-    }
+    for (uint32_t i = 0; i < UNIT_STATIC_LIMIT; i++)
+        MarkPermanentAtom(trc, unitStaticTable[i], "unit-static-string");
 
-    for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++) {
-        if (length2StaticTable[i])
-            MarkStringUnbarriered(trc, &length2StaticTable[i], "length2-static-string");
-    }
+    for (uint32_t i = 0; i < NUM_SMALL_CHARS * NUM_SMALL_CHARS; i++)
+        MarkPermanentAtom(trc, length2StaticTable[i], "length2-static-string");
 
     /* This may mark some strings more than once, but so be it. */
-    for (uint32_t i = 0; i < INT_STATIC_LIMIT; i++) {
-        if (intStaticTable[i])
-            MarkStringUnbarriered(trc, &intStaticTable[i], "int-static-string");
-    }
+    for (uint32_t i = 0; i < INT_STATIC_LIMIT; i++)
+        MarkPermanentAtom(trc, intStaticTable[i], "int-static-string");
 }
 
 bool
 StaticStrings::isStatic(JSAtom *atom)
 {
     const jschar *chars = atom->chars();
     switch (atom->length()) {
       case 1:
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -109,18 +109,20 @@ static const size_t UINT32_CHAR_BUFFER_L
  *  |
  * js::PropertyName             - / chars don't contain an index (uint32_t)
  *
  * Classes marked with (abstract) above are not literally C++ Abstract Base
  * Classes (since there are no virtual functions, pure or not, in this
  * hierarchy), but have the same meaning: there are no strings with this type as
  * its most-derived type.
  *
- * Technically, there are three additional most-derived types that satisfy the
- * invariants of more than one of the abovementioned most-derived types:
+ * Atoms can additionally be permanent, i.e. unable to be collected, and can
+ * be combined with other string types to create additional most-derived types
+ * that satisfy the invariants of more than one of the abovementioned
+ * most-derived types:
  *  - InlineAtom = JSInlineString + JSAtom (atom with inline chars)
  *  - ShortAtom  = JSShortString  + JSAtom (atom with (more) inline chars)
  *
  * Derived string types can be queried from ancestor types via isX() and
  * retrieved with asX() debug-only-checked casts.
  *
  * The ensureX() operations mutate 'this' in place to effectively the type to be
  * at least X (e.g., ensureLinear will change a JSRope to be a JSFlatString).
@@ -171,31 +173,30 @@ class JSString : public js::gc::Barriere
      *
      * The string type encoding can be summarized as follows. The "instance
      * encoding" entry for a type specifies the flag bits used to create a
      * string instance of that type. Abstract types have no instances and thus
      * have no such entry. The "subtype predicate" entry for a type specifies
      * the predicate used to query whether a JSString instance is subtype
      * (reflexively) of that type.
      *
-     *   Rope         0000       0000
-     *   Linear       -         !0000
-     *   HasBase      -          xxx1
-     *   Dependent    0001       0001
-     *   Flat         -          isLinear && !isDependent
-     *   Undepended   0011       0011
-     *   Extensible   0010       0010
-     *   Inline       0100       isFlat && !isExtensible && (u1.chars == inlineStorage) || isInt32)
-     *   Short        0100       header in FINALIZE_SHORT_STRING arena
-     *   External     0100       header in FINALIZE_EXTERNAL_STRING arena
-     *   Int32        0110       x110 (NYI, Bug 654190)
-     *   Atom         1000       1xxx
-     *   InlineAtom   1000       1000 && is Inline
-     *   ShortAtom    1000       1000 && is Short
-     *   Int32Atom    1110       1110 (NYI, Bug 654190)
+     *   Rope          0000       0000
+     *   Linear        -         !0000
+     *   HasBase       -          xxx1
+     *   Dependent     0001       0001
+     *   Flat          -          isLinear && !isDependent
+     *   Undepended    0011       0011
+     *   Extensible    0010       0010
+     *   Inline        0100       isFlat && !isExtensible && (u1.chars == inlineStorage)
+     *   Short         0100       header in FINALIZE_SHORT_STRING arena
+     *   External      0100       header in FINALIZE_EXTERNAL_STRING arena
+     *   Atom          -          1xxx
+     *   PermanentAtom 1100       1100
+     *   InlineAtom    -          isAtom && is Inline
+     *   ShortAtom     -          isAtom && is Short
      *
      *  "HasBase" here refers to the two string types that have a 'base' field:
      *  JSDependentString and JSUndependedString.
      *  A JSUndependedString is a JSDependentString which has been 'fixed' (by ensureFixed)
      *  to be null-terminated.  In such cases, the string must keep marking its base since
      *  there may be any number of *other* JSDependentStrings transitively depending on it.
      *
      */
@@ -208,18 +209,21 @@ class JSString : public js::gc::Barriere
     static const size_t UNDEPENDED_FLAGS      = JS_BIT(0) | JS_BIT(1);
     static const size_t EXTENSIBLE_FLAGS      = JS_BIT(1);
     static const size_t FIXED_FLAGS           = JS_BIT(2);
 
     static const size_t INT32_MASK            = JS_BITMASK(3);
     static const size_t INT32_FLAGS           = JS_BIT(1) | JS_BIT(2);
 
     static const size_t HAS_BASE_BIT          = JS_BIT(0);
+    static const size_t PERMANENT_BIT         = JS_BIT(2);
     static const size_t ATOM_BIT              = JS_BIT(3);
 
+    static const size_t PERMANENT_ATOM_FLAGS  = JS_BIT(2) | JS_BIT(3);
+
     static const size_t MAX_LENGTH            = JS_BIT(32 - LENGTH_SHIFT) - 1;
 
     size_t buildLengthAndFlags(size_t length, size_t flags) {
         JS_ASSERT(length <= MAX_LENGTH);
         JS_ASSERT(flags <= FLAGS_MASK);
         return (length << LENGTH_SHIFT) | flags;
     }
 
@@ -376,16 +380,21 @@ class JSString : public js::gc::Barriere
     }
 
     MOZ_ALWAYS_INLINE
     bool isAtom() const {
         return (d.lengthAndFlags & ATOM_BIT);
     }
 
     MOZ_ALWAYS_INLINE
+    bool isPermanentAtom() const {
+        return (d.lengthAndFlags & FLAGS_MASK) == PERMANENT_ATOM_FLAGS;
+    }
+
+    MOZ_ALWAYS_INLINE
     JSAtom &asAtom() const {
         JS_ASSERT(isAtom());
         return *(JSAtom *)this;
     }
 
     /* Only called by the GC for dependent or undepended strings. */
 
     inline bool hasBase() const {
@@ -420,16 +429,34 @@ class JSString : public js::gc::Barriere
     static inline js::ThingRootKind rootKind() { return js::THING_ROOT_STRING; }
 
 #ifdef DEBUG
     void dump();
     static void dumpChars(const jschar *s, size_t len);
     bool equals(const char *s);
 #endif
 
+    static MOZ_ALWAYS_INLINE void readBarrier(JSString *thing) {
+#ifdef JSGC_INCREMENTAL
+        if (thing->isPermanentAtom())
+            return;
+
+        js::gc::BarrieredCell<JSString>::readBarrier(thing);
+#endif
+    }
+
+    static MOZ_ALWAYS_INLINE void writeBarrierPre(JSString *thing) {
+#ifdef JSGC_INCREMENTAL
+        if (isNullLike(thing) || thing->isPermanentAtom())
+            return;
+
+        js::gc::BarrieredCell<JSString>::writeBarrierPre(thing);
+#endif
+    }
+
   private:
     JSString() MOZ_DELETE;
     JSString(const JSString &other) MOZ_DELETE;
     void operator=(const JSString &other) MOZ_DELETE;
 };
 
 class JSRope : public JSString
 {
@@ -565,16 +592,20 @@ class JSFlatString : public JSLinearStri
     /*
      * Once a JSFlatString sub-class has been added to the atom state, this
      * operation changes the string to the JSAtom type, in place.
      */
     MOZ_ALWAYS_INLINE JSAtom *morphAtomizedStringIntoAtom() {
         d.lengthAndFlags = buildLengthAndFlags(length(), ATOM_BIT);
         return &asAtom();
     }
+    MOZ_ALWAYS_INLINE JSAtom *morphAtomizedStringIntoPermanentAtom() {
+        d.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
+        return &asAtom();
+    }
 
     inline void finalize(js::FreeOp *fop);
 };
 
 JS_STATIC_ASSERT(sizeof(JSFlatString) == sizeof(JSString));
 
 class JSExtensibleString : public JSFlatString
 {
@@ -691,16 +722,27 @@ class JSAtom : public JSFlatString
     JSAtom &asAtom() const MOZ_DELETE;
 
   public:
     /* Returns the PropertyName for this.  isIndex() must be false. */
     inline js::PropertyName *asPropertyName();
 
     inline void finalize(js::FreeOp *fop);
 
+    MOZ_ALWAYS_INLINE
+    bool isPermanent() const {
+        return (d.lengthAndFlags & PERMANENT_BIT);
+    }
+
+    // Transform this atom into a permanent atom. This is only done during
+    // initialization of the runtime.
+    MOZ_ALWAYS_INLINE void morphIntoPermanentAtom() {
+        d.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
+    }
+
 #ifdef DEBUG
     void dump();
 #endif
 };
 
 JS_STATIC_ASSERT(sizeof(JSAtom) == sizeof(JSString));
 
 namespace js {
@@ -746,39 +788,30 @@ class StaticStrings
 {
   private:
     /* Bigger chars cannot be in a length-2 string. */
     static const size_t SMALL_CHAR_LIMIT    = 128U;
     static const size_t NUM_SMALL_CHARS     = 64U;
 
     JSAtom *length2StaticTable[NUM_SMALL_CHARS * NUM_SMALL_CHARS];
 
-    void clear() {
-        mozilla::PodArrayZero(unitStaticTable);
-        mozilla::PodArrayZero(length2StaticTable);
-        mozilla::PodArrayZero(intStaticTable);
-    }
-
   public:
     /* We keep these public for the JITs. */
     static const size_t UNIT_STATIC_LIMIT   = 256U;
     JSAtom *unitStaticTable[UNIT_STATIC_LIMIT];
 
     static const size_t INT_STATIC_LIMIT    = 256U;
     JSAtom *intStaticTable[INT_STATIC_LIMIT];
 
     StaticStrings() {
-        clear();
+        mozilla::PodZero(this);
     }
 
     bool init(JSContext *cx);
     void trace(JSTracer *trc);
-    void finish() {
-        clear();
-    }
 
     static bool hasUint(uint32_t u) { return u < INT_STATIC_LIMIT; }
 
     JSAtom *getUint(uint32_t u) {
         JS_ASSERT(hasUint(u));
         return intStaticTable[u];
     }
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -2955,17 +2955,17 @@ class XPCJSSourceHook: public js::Source
 
 static const JSWrapObjectCallbacks WrapObjectCallbacks = {
     xpc::WrapperFactory::Rewrap,
     xpc::WrapperFactory::WrapForSameCompartment,
     xpc::WrapperFactory::PrepareForWrapping
 };
 
 XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
-   : CycleCollectedJSRuntime(32L * 1024L * 1024L, JS_USE_HELPER_THREADS),
+   : CycleCollectedJSRuntime(nullptr, 32L * 1024L * 1024L, JS_USE_HELPER_THREADS),
    mJSContextStack(new XPCJSContextStack()),
    mCallContext(nullptr),
    mAutoRoots(nullptr),
    mResolveName(JSID_VOID),
    mResolvingWrapper(nullptr),
    mWrappedJSMap(JSObject2WrappedJSMap::newMap(XPC_JS_MAP_SIZE)),
    mWrappedJSClassMap(IID2WrappedJSClassMap::newMap(XPC_JS_CLASS_MAP_SIZE)),
    mIID2NativeInterfaceMap(IID2NativeInterfaceMap::newMap(XPC_NATIVE_INTERFACE_MAP_SIZE)),
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/973390-1.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html style="display: flex;">
+<head>
+<meta charset="UTF-8">
+</head>
+<body style="display: table-cell;"></body>
+</html>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -422,8 +422,9 @@ pref(layers.force-active,true) load 8596
 load 866588.html
 load 897852.html
 asserts(4-6) load 898913.html # bug 847368
 load 931464.html
 load 936988-1.html
 load 931460-1.html
 load 935765-1.html
 load 942690.html
+load 973390-1.html
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -2458,19 +2458,16 @@ nsCSSFrameConstructor::ConstructDocEleme
                    nullptr);
     newFrame = frameItems.FirstChild();
     NS_ASSERTION(frameItems.OnlyChild(), "multiple root element frames");
   }
 
   MOZ_ASSERT(newFrame);
   MOZ_ASSERT(contentFrame);
 
-  // set the primary frame
-  aDocElement->SetPrimaryFrame(contentFrame);
-
   NS_ASSERTION(processChildren ? !mRootElementFrame :
                  mRootElementFrame == contentFrame,
                "unexpected mRootElementFrame");
   mRootElementFrame = contentFrame;
 
   // Figure out which frame has the main style for the document element,
   // assigning it to mRootElementStyleFrame.
   // Backgrounds should be propagated from that frame to the viewport.
@@ -2491,16 +2488,19 @@ nsCSSFrameConstructor::ConstructDocEleme
     // Use a null PendingBinding, since our binding is not in fact pending.
     ProcessChildren(state, aDocElement, styleContext, contentFrame, true,
                     childItems, false, nullptr);
 
     // Set the initial child lists
     contentFrame->SetInitialChildList(kPrincipalList, childItems);
   }
 
+  // set the primary frame
+  aDocElement->SetPrimaryFrame(contentFrame);
+
   SetInitialSingleChild(mDocElementContainingBlock, newFrame);
 
   return newFrame;
 }
 
 
 nsIFrame*
 nsCSSFrameConstructor::ConstructRootFrame()
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -1212,18 +1212,17 @@ void nsDisplayList::PaintForFrame(nsDisp
                      aBuilder->FindReferenceFrameFor(aForFrame),
                      root, mVisibleRect, viewport,
                      (usingDisplayport ? &displayport : nullptr),
                      (usingCriticalDisplayport ? &criticalDisplayport : nullptr),
                      id, isRoot, containerParameters);
   if (usingDisplayport &&
       !(root->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
     // See bug 693938, attachment 567017
-    NS_WARNING("We don't support transparent content with displayports, force it to be opqaue");
-    root->SetContentFlags(Layer::CONTENT_OPAQUE);
+    NS_WARNING("Transparent content with displayports can be expensive.");
   }
 
   layerManager->SetRoot(root);
   layerBuilder->WillEndTransaction();
   bool temp = aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
   LayerManager::EndTransactionFlags flags = LayerManager::END_DEFAULT;
   if (layerManager->NeedsWidgetInvalidation()) {
     if (aFlags & PAINT_NO_COMPOSITE) {
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -165,19 +165,16 @@ class RefTest(object):
 
     for v in options.extraPrefs:
       thispref = v.split('=')
       if len(thispref) < 2:
         print "Error: syntax error in --setpref=" + v
         sys.exit(1)
       prefs[thispref[0]] = mozprofile.Preferences.cast(thispref[1].strip())
 
-    # We need to set this here, see bug 972099
-    prefs['gfx.color_management.force_srgb'] = True
-
     # install the reftest extension bits into the profile
     addons = []
     addons.append(os.path.join(SCRIPT_DIRECTORY, "reftest"))
 
     # I would prefer to use "--install-extension reftest/specialpowers", but that requires tight coordination with
     # release engineering and landing on multiple branches at once.
     if special_powers and (manifest.endswith('crashtests.list') or manifest.endswith('jstests.list')):
       addons.append(os.path.join(SCRIPT_DIRECTORY, 'specialpowers'))
--- a/media/webrtc/moz.build
+++ b/media/webrtc/moz.build
@@ -164,17 +164,16 @@ if CONFIG['MOZ_WEBRTC_SIGNALING']:
         'signaling/src/sipcc/core/src-common/util_ios_queue.c',
         'signaling/src/sipcc/cpr/android/cpr_android_init.c',
         'signaling/src/sipcc/cpr/android/cpr_android_stdio.c',
         'signaling/src/sipcc/cpr/android/cpr_android_timers_using_select.c',
         'signaling/src/sipcc/cpr/darwin/cpr_darwin_init.c',
         'signaling/src/sipcc/cpr/darwin/cpr_darwin_stdio.c',
         'signaling/src/sipcc/cpr/darwin/cpr_darwin_timers_using_select.c',
         'signaling/src/sipcc/cpr/linux/cpr_linux_init.c',
-        'signaling/src/sipcc/cpr/linux/cpr_linux_ipc.c',
         'signaling/src/sipcc/cpr/linux/cpr_linux_stdio.c',
         'signaling/src/sipcc/cpr/linux/cpr_linux_timers_using_select.c',
         'signaling/src/sipcc/cpr/win32/cpr_win_stdio.c',
         'signaling/src/sipcc/cpr/win32/cpr_win_timers.c',
         'signaling/src/sipcc/plat/common/dns_utils.c',
         'signaling/src/sipcc/plat/csf2g/reset_api.c',
         'signaling/src/sipcc/plat/win32/dns_utils.c',
         'signaling/src/sipcc/plat/win32/mystub.c',
--- a/media/webrtc/signaling/signaling.gyp
+++ b/media/webrtc/signaling/signaling.gyp
@@ -553,16 +553,17 @@
         './src/sipcc/cpr/include/cpr_stdio.h',
         './src/sipcc/cpr/include/cpr_stdlib.h',
         './src/sipcc/cpr/include/cpr_string.h',
         './src/sipcc/cpr/include/cpr_strings.h',
         './src/sipcc/cpr/include/cpr_threads.h',
         './src/sipcc/cpr/include/cpr_time.h',
         './src/sipcc/cpr/include/cpr_timers.h',
         './src/sipcc/cpr/include/cpr_types.h',
+        './src/sipcc/cpr/common/cpr_ipc.c',
         './src/sipcc/cpr/common/cpr_string.c',
         # INCLUDE
         './src/sipcc/include/cc_blf.h',
         './src/sipcc/include/cc_blf_listener.h',
         './src/sipcc/include/cc_call_feature.h',
         './src/sipcc/include/cc_call_listener.h',
         './src/sipcc/include/cc_config.h',
         './src/sipcc/include/cc_constants.h',
@@ -654,29 +655,27 @@
             './src/sipcc/core/sipstack/sip_platform_task.c',
 
             # PLAT
             './src/sipcc/plat/common/dns_utils.c',
 
             # CPR
             './src/sipcc/cpr/android/cpr_android_errno.c',
             './src/sipcc/cpr/android/cpr_android_init.c',
-            './src/sipcc/cpr/android/cpr_android_ipc.c',
             './src/sipcc/cpr/android/cpr_android_socket.c',
             './src/sipcc/cpr/android/cpr_android_stdio.c',
             './src/sipcc/cpr/android/cpr_android_string.c',
             './src/sipcc/cpr/android/cpr_android_threads.c',
             './src/sipcc/cpr/android/cpr_android_timers_using_select.c',
 
             './src/sipcc/cpr/android/cpr_assert.h',
             './src/sipcc/cpr/android/cpr_android_align.h',
             './src/sipcc/cpr/android/cpr_android_assert.h',
             './src/sipcc/cpr/android/cpr_android_errno.h',
             './src/sipcc/cpr/android/cpr_android_in.h',
-            './src/sipcc/cpr/android/cpr_darwin_ipc.h',
             './src/sipcc/cpr/android/cpr_android_private.h',
             './src/sipcc/cpr/android/cpr_android_rand.h',
             './src/sipcc/cpr/android/cpr_android_socket.h',
             './src/sipcc/cpr/android/cpr_android_stdio.h',
             './src/sipcc/cpr/android/cpr_android_string.h',
             './src/sipcc/cpr/android/cpr_android_strings.h',
             './src/sipcc/cpr/android/cpr_android_time.h',
             './src/sipcc/cpr/android/cpr_android_timers.h',
@@ -690,29 +689,27 @@
             './src/sipcc/core/sipstack/sip_platform_task.c',
 
             # PLAT
             './src/sipcc/plat/common/dns_utils.c',
 
             # CPR
             './src/sipcc/cpr/linux/cpr_linux_errno.c',
             './src/sipcc/cpr/linux/cpr_linux_init.c',
-            './src/sipcc/cpr/linux/cpr_linux_ipc.c',
             './src/sipcc/cpr/linux/cpr_linux_socket.c',
             './src/sipcc/cpr/linux/cpr_linux_stdio.c',
             './src/sipcc/cpr/linux/cpr_linux_string.c',
             './src/sipcc/cpr/linux/cpr_linux_threads.c',
             './src/sipcc/cpr/linux/cpr_linux_timers_using_select.c',
 
             './src/sipcc/cpr/linux/cpr_assert.h',
             './src/sipcc/cpr/linux/cpr_linux_align.h',
             './src/sipcc/cpr/linux/cpr_linux_assert.h',
             './src/sipcc/cpr/linux/cpr_linux_errno.h',
             './src/sipcc/cpr/linux/cpr_linux_in.h',
-            './src/sipcc/cpr/linux/cpr_linux_ipc.h',
             './src/sipcc/cpr/linux/cpr_linux_private.h',
             './src/sipcc/cpr/linux/cpr_linux_rand.h',
             './src/sipcc/cpr/linux/cpr_linux_socket.h',
             './src/sipcc/cpr/linux/cpr_linux_stdio.h',
             './src/sipcc/cpr/linux/cpr_linux_string.h',
             './src/sipcc/cpr/linux/cpr_linux_strings.h',
             './src/sipcc/cpr/linux/cpr_linux_time.h',
             './src/sipcc/cpr/linux/cpr_linux_timers.h',
@@ -740,18 +737,16 @@
             './src/sipcc/cpr/win32/cpr_win_assert.h',
             './src/sipcc/cpr/win32/cpr_win_debug.c',
             './src/sipcc/cpr/win32/cpr_win_debug.h',
             './src/sipcc/cpr/win32/cpr_win_defines.h',
             './src/sipcc/cpr/win32/cpr_win_errno.c',
             './src/sipcc/cpr/win32/cpr_win_errno.h',
             './src/sipcc/cpr/win32/cpr_win_in.h',
             './src/sipcc/cpr/win32/cpr_win_init.c',
-            './src/sipcc/cpr/win32/cpr_win_ipc.c',
-            './src/sipcc/cpr/win32/cpr_win_ipc.h',
             './src/sipcc/cpr/win32/cpr_win_locks.c',
             './src/sipcc/cpr/win32/cpr_win_locks.h',
             './src/sipcc/cpr/win32/cpr_win_rand.c',
             './src/sipcc/cpr/win32/cpr_win_rand.h',
             './src/sipcc/cpr/win32/cpr_win_socket.c',
             './src/sipcc/cpr/win32/cpr_win_socket.h',
             './src/sipcc/cpr/win32/cpr_win_stdio.c',
             './src/sipcc/cpr/win32/cpr_win_stdio.h',
@@ -796,18 +791,16 @@
             #'./src/sipcc/plat/unix-common/random.c',
 
             # CPR
             './src/sipcc/cpr/darwin/cpr_darwin_assert.h',
             './src/sipcc/cpr/darwin/cpr_darwin_errno.c',
             './src/sipcc/cpr/darwin/cpr_darwin_errno.h',
             './src/sipcc/cpr/darwin/cpr_darwin_in.h',
             './src/sipcc/cpr/darwin/cpr_darwin_init.c',
-            './src/sipcc/cpr/darwin/cpr_darwin_ipc.c',
-            './src/sipcc/cpr/darwin/cpr_darwin_ipc.h',
             './src/sipcc/cpr/darwin/cpr_darwin_private.h',
             './src/sipcc/cpr/darwin/cpr_darwin_rand.h',
             './src/sipcc/cpr/darwin/cpr_darwin_socket.c',
             './src/sipcc/cpr/darwin/cpr_darwin_socket.h',
             './src/sipcc/cpr/darwin/cpr_darwin_stdio.c',
             './src/sipcc/cpr/darwin/cpr_darwin_stdio.h',
             './src/sipcc/cpr/darwin/cpr_darwin_string.c',
             './src/sipcc/cpr/darwin/cpr_darwin_string.h',
deleted file mode 100644
--- a/media/webrtc/signaling/src/sipcc/cpr/android/cpr_android_ipc.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "cpr.h"
-#include "cpr_stdlib.h"
-#include <cpr_stdio.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <time.h>
-#include <plat_api.h>
-#include "cpr_string.h"
-
-/*
- * If building with debug test interface,
- * allow access to internal CPR functions
- */
-#define STATIC static
-
-#define OS_MSGTQL 31 /* need to check number for MV linux and put here */
-
-/*
- * Internal CPR API
- */
-extern pthread_t cprGetThreadId(cprThread_t thread);
-
-/*
- * Extended internal message queue node
- *
- * A double-linked list holding the nessasary message information
- */
-typedef struct cpr_msgq_node_s
-{
-    struct cpr_msgq_node_s *next;
-    struct cpr_msgq_node_s *prev;
-    void *msg;
-    void *pUserData;
-} cpr_msgq_node_t;
-
-/*
- * Msg queue information needed to hide OS differences in implementation.
- * To use msg queues, the application code may pass in a name to the
- * create function for msg queues. CPR does not use this field, it is
- * solely for the convenience of the application and to aid in debugging.
- *
- * Note: Statistics are not protected by a mutex; therefore, there exists
- * the possibility that the results may not be accurate.
- *
- * Note:if the depth supplied by OS is insufficient,a message queue owner may
- * increase the message queue depth via cprCreateMessageQueue's depth
- * parameter where the value can range from MSGTQL to CPR_MAX_MSG_Q_DEPTH.
- */
-typedef struct cpr_msg_queue_s
-{
-    struct cpr_msg_queue_s *next;
-    const char *name;
-    pthread_t thread;
-    int32_t queueId;
-    uint16_t currentCount;
-    uint32_t totalCount;
-    uint32_t sendErrors;
-    uint32_t reTries;
-    uint32_t highAttempts;
-    uint32_t selfQErrors;
-    uint16_t extendedQDepth;
-    uint16_t maxExtendedQDepth;
-    pthread_mutex_t mutex;       /* lock for managing extended queue     */
-	pthread_cond_t cond;		 /* signal for queue/dequeue */
-    cpr_msgq_node_t *head;       /* extended queue head (newest element) */
-    cpr_msgq_node_t *tail;       /* extended queue tail (oldest element) */
-} cpr_msg_queue_t;
-
-/*
- * A enumeration used to report the result of posting a message to
- * a message queue
- */
-typedef enum
-{
-    CPR_MSGQ_POST_SUCCESS,
-    CPR_MSGQ_POST_FAILED,
-    CPR_MSGQ_POST_PENDING
-} cpr_msgq_post_result_e;
-
-
-/*
- * Head of list of message queues
- */
-static cpr_msg_queue_t *msgQueueList = NULL;
-
-/*
- * Mutex to manage message queue list
- */
-pthread_mutex_t msgQueueListMutex;
-
-/*
- * String to represent message queue name when it is not provided
- */
-static const char unnamed_string[] = "unnamed";
-
-
-/*
- * CPR_MAX_MSG_Q_DEPTH
- *
- * The maximum queue depth supported by the CPR layer.  This value
- * is arbitrary though the purpose is to limit the memory usage
- * by CPR and avoid (nearly) unbounded situations.
- *
- * Note: This value should be greater than MSGTQL which is currently
- *       defined as 31
- */
-#define CPR_MAX_MSG_Q_DEPTH 256
-
-/*
- * CPR_SND_TIMEOUT_WAIT_INTERVAL
- *
- * The interval of time to wait in milliseconds between attempts to
- * send a message to the message queue
- *
- * Note: 20 ms. to avoid less than a tick wake up since on most
- *       OSes 10ms is one 1 tick
- *       this should really be OS_TICK_MS * 2 or OS_TICK_MS + X
- */
-#define CPR_SND_TIMEOUT_WAIT_INTERVAL 20
-
-/*
- * CPR_ATTEMPTS_TO_SEND
- *
- * The number of attempts made to send a message when the message
- * would otherwise be blocked.  Note in this condition the thread
- * will sleep the timeout interval to allow the msg queue to be
- * drained.
- *
- * Note: 25 attempts for upto .5 seconds at the interval of
- *       CPR_SND_TIMEOUT_WAIT_INTERVAL worst case.
- */
-#define CPR_ATTEMPTS_TO_SEND 25
-
-/*
- * Also, important to note that the total timeout interval must be
- * greater than the SIP's select call timeout value which is 25msec.
- * This is necessary to cover the case where the SIP message queue
- * is full and the select timeout occurs.
- *
- * Total timeout interval = CPR_SND_TIMEOUT_WAIT_INTERVAL *
- *                          CPR_ATTEMPTS_TO_SEND;
- */
-
-
-/*
- * Prototype declarations
- */
-static cpr_msgq_post_result_e
-cprPostMessage(cpr_msg_queue_t *msgq, void *msg, void **ppUserData);
-static void
-cprPegSendMessageStats(cpr_msg_queue_t *msgq, uint16_t numAttempts);
-
-
-/*
- * Functions
- */
-
-/**
- * Creates a message queue
- *
- * @param name  - name of the message queue
- * @param depth - the message queue depth, optional field which will
- *                default if set to zero(0)
- *
- * @return Msg queue handle or NULL if init failed, errno provided
- *
- * @note the actual message queue depth will be bounded by the
- *       standard system message queue depth and CPR_MAX_MSG_Q_DEPTH.
- *       If 'depth' is outside of the bounds, the value will be
- *       reset automatically.
- */
-cprMsgQueue_t
-cprCreateMessageQueue (const char *name, uint16_t depth)
-{
-    static const char fname[] = "cprCreateMessageQueue";
-    cpr_msg_queue_t *msgq;
-    static int key_id = 100; /* arbitrary starting number */
-    pthread_cond_t _cond = PTHREAD_COND_INITIALIZER;
-    pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
-
-    msgq = cpr_calloc(1, sizeof(cpr_msg_queue_t));
-    if (msgq == NULL) {
-        printf("%s: Malloc failed: %s\n", fname,
-                  name ? name : unnamed_string);
-        errno = ENOMEM;
-        return NULL;
-    }
-
-    msgq->name = name ? name : unnamed_string;
-    msgq->queueId = key_id++;
-    msgq->cond = _cond;
-    msgq->mutex = _lock;
-
-    /*
-     * Add message queue to list for statistics reporting
-     */
-    pthread_mutex_lock(&msgQueueListMutex);
-    msgq->next = msgQueueList;
-    msgQueueList = msgq;
-    pthread_mutex_unlock(&msgQueueListMutex);
-
-    return msgq;
-}
-
-
-/**
- * Removes all messages from the queue and then destroy the message queue
- *
- * @param msgQueue - message queue to destroy
- *
- * @return CPR_SUCCESS or CPR_FAILURE, errno provided
- */
-cprRC_t
-cprDestroyMessageQueue (cprMsgQueue_t msgQueue)
-{
-    static const char fname[] = "cprDestroyMessageQueue";
-    cpr_msg_queue_t *msgq;
-    void *msg;
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq == NULL) {
-        /* Bad application! */
-        CPR_ERROR("%s: Invalid input\n", fname);
-        errno = EINVAL;
-        return CPR_FAILURE;
-    }
-
-    /* Drain message queue */
-    msg = cprGetMessage(msgQueue, FALSE, NULL);
-    while (msg != NULL) {
-        cpr_free(msg);
-        msg = cprGetMessage(msgQueue, FALSE, NULL);
-    }
-
-    /* Remove message queue from list */
-    pthread_mutex_lock(&msgQueueListMutex);
-    if (msgq == msgQueueList) {
-        msgQueueList = msgq->next;
-    } else {
-        cpr_msg_queue_t *msgql = msgQueueList;
-
-        while ((msgql->next != NULL) && (msgql->next != msgq)) {
-            msgql = msgql->next;
-        }
-        if (msgql->next == msgq) {
-            msgql->next = msgq->next;
-        }
-    }
-    pthread_mutex_unlock(&msgQueueListMutex);
-
-    /* Remove message queue mutex */
-    if (pthread_mutex_destroy(&msgq->mutex) != 0) {
-        CPR_ERROR("%s: Failed to destroy msg queue (%s) mutex: %d\n",
-                  fname, msgq->name, errno);
-    }
-
-    cpr_free(msgq);
-    return CPR_SUCCESS;
-}
-
-
-/**
- * Associate a thread with the message queue
- *
- * @param msgQueue  - msg queue to set
- * @param thread    - CPR thread to associate with queue
- *
- * @return CPR_SUCCESS or CPR_FAILURE
- *
- * @note Nothing is done to prevent overwriting the thread ID
- *       when the value has already been set.
- */
-cprRC_t
-cprSetMessageQueueThread (cprMsgQueue_t msgQueue, cprThread_t thread)
-{
-    static const char fname[] = "cprSetMessageQueueThread";
-    cpr_msg_queue_t *msgq;
-
-    if ((!msgQueue) || (!thread)) {
-        CPR_ERROR("%s: Invalid input\n", fname);
-        return CPR_FAILURE;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq->thread != 0) {
-        CPR_ERROR("%s: over-writing previously msgq thread name for %s",
-                  fname, msgq->name);
-    }
-
-    msgq->thread = cprGetThreadId(thread);
-    return CPR_SUCCESS;
-}
-
-
-/**
- * Retrieve a message from a particular message queue
- *
- * @param[in]  msgQueue    - msg queue from which to retrieve the message
- * @param[in]  waitForever - boolean to either wait forever (TRUE) or not
- *                           wait at all (FALSE) if the msg queue is empty.
- * @param[out] ppUserData  - pointer to a pointer to user defined data
- *
- * @return Retrieved message buffer or NULL if failure occurred or
- *         the waitForever flag was set to false and no messages were
- *         on the queue.
- *
- * @note   If ppUserData is defined, the value will be initialized to NULL
- */
-void *
-cprGetMessage (cprMsgQueue_t msgQueue, boolean waitForever, void **ppUserData)
-{
-    static const char fname[] = "cprGetMessage";
-
-    void *buffer = 0;
-    cpr_msg_queue_t *msgq;
-    cpr_msgq_node_t *node;
-    struct timespec timeout;
-    struct timeval tv;
-    struct timezone tz;
-
-    /* Initialize ppUserData */
-    if (ppUserData) {
-        *ppUserData = NULL;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq == NULL) {
-        /* Bad application! */
-        CPR_ERROR("%s: Invalid input\n", fname);
-        errno = EINVAL;
-        return NULL;
-    }
-
-    /*
-     * If waitForever is set, block on the message queue
-     * until a message is received, else return after
-     * 25msec of waiting
-     */
-	pthread_mutex_lock(&msgq->mutex);
-
-	if (!waitForever)
-	{
-		// We'll wait till 25uSec from now
-		gettimeofday(&tv, &tz);
-		timeout.tv_nsec = (tv.tv_usec * 1000) + 25000;
-		timeout.tv_sec = tv.tv_sec;
-
-		pthread_cond_timedwait(&msgq->cond, &msgq->mutex, &timeout);
-	}
-	else
-	{
-		while(msgq->tail==NULL)
-		{
-			pthread_cond_wait(&msgq->cond, &msgq->mutex);
-		}
-	}
-
-	// If there is a message on the queue, de-queue it
-	if (msgq->tail)
-	{
-		node = msgq->tail;
-		msgq->tail = node->prev;
-		if (msgq->tail) {
-			msgq->tail->next = NULL;
-		}
-		if (msgq->head == node) {
-			msgq->head = NULL;
-		}
-		msgq->currentCount--;
-		/*
-		 * Pull out the data
-		 */
-		if (ppUserData) {
-			*ppUserData = node->pUserData;
-		}
-		buffer = node->msg;
-
-	}
-
-	pthread_mutex_unlock(&msgq->mutex);
-
-    return buffer;
-}
-
-
-/**
- * Place a message on a particular queue.  Note that caller may
- * block (see comments below)
- *
- * @param msgQueue   - msg queue on which to place the message
- * @param msg        - pointer to the msg to place on the queue
- * @param ppUserData - pointer to a pointer to user defined data
- *
- * @return CPR_SUCCESS or CPR_FAILURE, errno provided
- *
- * @note 1. Messages queues are set to be non-blocking, those cases
- *       where the system call fails with a would-block error code
- *       (EAGAIN) the function will attempt other mechanisms described
- *       below.
- * @note 2. If enabled with an extended message queue, either via a
- *       call to cprCreateMessageQueue with depth value or a call to
- *       cprSetExtendMessageQueueDepth() (when unit testing), the message
- *       will be added to the extended message queue and the call will
- *       return successfully.  When room becomes available on the
- *       system's message queue, those messages will be added.
- * @note 3. If the message queue becomes full and no space is availabe
- *       on the extended message queue, then the function will attempt
- *       to resend the message up to CPR_ATTEMPTS_TO_SEND and the
- *       calling thread will *BLOCK* CPR_SND_TIMEOUT_WAIT_INTERVAL
- *       milliseconds after each failed attempt.  If unsuccessful
- *       after all attempts then EGAIN error code is returned.
- * @note 4. This applies to all CPR threads, including the timer thread.
- *       So it is possible that the timer thread would be forced to
- *       sleep which would have the effect of delaying all active
- *       timers.  The work to fix this rare situation is not considered
- *       worth the effort to fix....so just leaving as is.
- */
-cprRC_t
-cprSendMessage (cprMsgQueue_t msgQueue, void *msg, void **ppUserData)
-{
-    static const char fname[] = "cprSendMessage";
-    static const char error_str[] = "%s: Msg not sent to %s queue: %s\n";
-    cpr_msgq_post_result_e rc;
-    cpr_msg_queue_t *msgq;
-    int16_t attemptsToSend = CPR_ATTEMPTS_TO_SEND;
-    uint16_t numAttempts   = 0;
-
-    /* Bad application? */
-    if (msgQueue == NULL) {
-        CPR_ERROR(error_str, fname, "undefined", "invalid input");
-        errno = EINVAL;
-        return CPR_FAILURE;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-
-    /*
-     * Attempt to send message
-     */
-    do {
-
-		/*
-		 * Post the message to the Queue
-		 */
-		rc = cprPostMessage(msgq, msg, ppUserData);
-
-		if (rc == CPR_MSGQ_POST_SUCCESS) {
-			cprPegSendMessageStats(msgq, numAttempts);
-			return CPR_SUCCESS;
-		} else if (rc == CPR_MSGQ_POST_FAILED) {
-			CPR_ERROR("%s: Msg not sent to %s queue: %d\n",
-					  fname, msgq->name, errno);
-			msgq->sendErrors++;
-			/*
-			 * If posting to calling thread's own queue,
-			 * then peg the self queue error.
-			 */
-			if (pthread_self() == msgq->thread) {
-				msgq->selfQErrors++;
-			}
-
-			return CPR_FAILURE;
-		}
-
-
-        /*
-         * Did not succeed in sending the message, so continue
-         * to attempt up to the CPR_ATTEMPTS_TO_SEND.
-         */
-        attemptsToSend--;
-        if (attemptsToSend > 0) {
-            /*
-             * Force a context-switch of the thread attempting to
-             * send the message, in order to help the case where
-             * the msg queue is full and the owning thread may get
-             * a a chance be scheduled so it can drain it (Note:
-             * no guarantees, more of a "last-ditch effort" to
-             * recover...especially when temporarily over-whelmed).
-             */
-            cprSleep(CPR_SND_TIMEOUT_WAIT_INTERVAL);
-            msgq->reTries++;
-            numAttempts++;
-        }
-    } while (attemptsToSend > 0);
-
-    CPR_ERROR(error_str, fname, msgq->name, "FULL");
-    msgq->sendErrors++;
-    return CPR_FAILURE;
-}
-
-/**
- * Peg the statistics for successfully posting a message
- *
- * @param msgq        - message queue
- * @param numAttempts - number of attempts to post message to message queue
- *
- * @return none
- *
- * @pre (msgq not_eq NULL)
- */
-static void
-cprPegSendMessageStats (cpr_msg_queue_t *msgq, uint16_t numAttempts)
-{
-    /*
-     * Collect statistics
-     */
-    msgq->totalCount++;
-
-    if (numAttempts > msgq->highAttempts) {
-        msgq->highAttempts = numAttempts;
-    }
-}
-
-/**
- * Post message to system message queue
- *
- * @param msgq       - message queue
- * @param msg        - message to post
- * @param ppUserData - ptr to ptr to option user data
- *
- * @return the post result which is CPR_MSGQ_POST_SUCCESS,
- *         CPR_MSGQ_POST_FAILURE or CPR_MSGQ_POST_PENDING
- *
- * @pre (msgq not_eq NULL)
- * @pre (msg not_eq NULL)
- */
-static cpr_msgq_post_result_e
-cprPostMessage (cpr_msg_queue_t *msgq, void *msg, void **ppUserData)
-{
-	cpr_msgq_node_t *node;
-
-	/*
-	 * Allocate new message queue node
-	 */
-	node = cpr_malloc(sizeof(*node));
-	if (!node) {
-		errno = ENOMEM;
-		return CPR_MSGQ_POST_FAILED;
-	}
-
-	pthread_mutex_lock(&msgq->mutex);
-
-	/*
-	 * Fill in data
-	 */
-	node->msg = msg;
-	if (ppUserData != NULL) {
-		node->pUserData = *ppUserData;
-	} else {
-		node->pUserData = NULL;
-	}
-
-	/*
-	 * Push onto list
-	 */
-	node->prev = NULL;
-	node->next = msgq->head;
-	msgq->head = node;
-
-	if (node->next) {
-		node->next->prev = node;
-	}
-
-	if (msgq->tail == NULL) {
-		msgq->tail = node;
-	}
-	msgq->currentCount++;
-
-	pthread_cond_signal(&msgq->cond);
-	pthread_mutex_unlock(&msgq->mutex);
-
-	return CPR_MSGQ_POST_SUCCESS;
-
-}
-
-
-/**
- * cprGetDepth
- *
- * @brief get depth of a message queue
- *
- * The pSIPCC uses this API to look at the depth of a message queue for internal
- * routing and throttling decision
- *
- * @param[in] msgQueue - message queue
- *
- * @return depth of msgQueue
- *
- * @pre (msgQueue not_eq NULL)
- */
-uint16_t cprGetDepth (cprMsgQueue_t msgQueue)
-{
-        cpr_msg_queue_t *msgq;
-        msgq = (cpr_msg_queue_t *) msgQueue;
-        return msgq->currentCount;
-}
-
deleted file mode 100644
--- a/media/webrtc/signaling/src/sipcc/cpr/android/cpr_android_ipc.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef _CPR_CNU_IPC_H_
-#define _CPR_CNU_IPC_H_
-
-#include "cpr_threads.h"
-#include <pthread.h>
-
-/* Enable support for cprSetMessageQueueThread API */
-#define CPR_USE_SET_MESSAGE_QUEUE_THREAD
-
-/* Maximum message size allowed by CNU */
-#define CPR_MAX_MSG_SIZE  8192
-
-/* Our CNU msgtype */
-#define CPR_IPC_MSG 1
-
-
-/* Message buffer layout */
-struct msgbuffer {
-    long    mtype;    /* Message type */
-    void   *msgPtr;   /* Ptr to msg */
-    void   *usrPtr;   /* Ptr to user data */
-};
-
-/* For gathering statistics regarding message queues */
-typedef struct {
-    char name[16];
-    uint16_t currentCount;
-    uint32_t totalCount;
-    uint32_t rcvTimeouts;
-    uint32_t sendErrors;
-    uint32_t reTries;
-    uint32_t highAttempts;
-    uint32_t selfQErrors;
-    uint16_t extendedDepth;
-} cprMsgQueueStats_t;
-
-
-/*
- * Mutex for updating the message queue list
- */
-extern pthread_mutex_t msgQueueListMutex;
-
-
-/**
- * cprGetDepth
- *
- * Get depth of a message queue
- */
-uint16_t cprGetDepth(cprMsgQueue_t msgQueue);
-
-#endif
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/sipcc/cpr/common/cpr_ipc.c
@@ -0,0 +1,685 @@
+/* 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 "cpr.h"
+#include "cpr_stdlib.h"
+#include "cpr_stdio.h"
+#include "plat_api.h"
+#include "cpr_string.h"
+
+#ifdef SIP_OS_WINDOWS
+#include <windows.h>
+#include <process.h>
+#include <winuser.h>
+#else
+#include <errno.h>
+#include <sys/time.h>
+#include <time.h>
+#endif /* SIP_OS_WINDOWS */
+
+
+#ifdef SIP_OS_WINDOWS
+extern cprMsgQueue_t sip_msgq;
+extern cprMsgQueue_t gsm_msgq;
+extern cprMsgQueue_t tmr_msgq;
+
+extern void gsm_shutdown();
+extern void sip_shutdown();
+
+/*
+ * Buffer to hold the messages sent/received by CPR. All
+ * CPR does is pass four bytes (CNU msg type) and an unsigned
+ * four bytes (pointer to the msg buffer).
+ */
+static char rcvBuffer[100];
+#define MSG_BUF 0xF000
+
+#else
+
+#define OS_MSGTQL 31 /* need to check number for MV linux and put here */
+
+/*
+ * Internal CPR API
+ */
+extern pthread_t cprGetThreadId(cprThread_t thread);
+
+
+/*
+ * Extended internal message queue node
+ *
+ * A double-linked list holding the nessasary message information
+ */
+typedef struct cpr_msgq_node_s
+{
+    struct cpr_msgq_node_s *next;
+    struct cpr_msgq_node_s *prev;
+    void *msg;
+    void *pUserData;
+} cpr_msgq_node_t;
+
+/*
+ * Msg queue information needed to hide OS differences in implementation.
+ * To use msg queues, the application code may pass in a name to the
+ * create function for msg queues. CPR does not use this field, it is
+ * solely for the convenience of the application and to aid in debugging.
+ *
+ * Note: Statistics are not protected by a mutex; therefore, there exists
+ * the possibility that the results may not be accurate.
+ *
+ * Note:if the depth supplied by OS is insufficient,a message queue owner may
+ * increase the message queue depth via cprCreateMessageQueue's depth
+ * parameter where the value can range from MSGTQL to CPR_MAX_MSG_Q_DEPTH.
+ */
+typedef struct cpr_msg_queue_s
+{
+    struct cpr_msg_queue_s *next;
+    const char *name;
+    pthread_t thread;
+    int32_t queueId;
+    uint16_t currentCount;
+    uint32_t totalCount;
+    uint32_t sendErrors;
+    uint32_t reTries;
+    uint32_t highAttempts;
+    uint32_t selfQErrors;
+    uint16_t extendedQDepth;
+    uint16_t maxExtendedQDepth;
+    pthread_mutex_t mutex;       /* lock for managing extended queue     */
+    pthread_cond_t cond;         /* signal for queue/dequeue */
+    cpr_msgq_node_t *head;       /* extended queue head (newest element) */
+    cpr_msgq_node_t *tail;       /* extended queue tail (oldest element) */
+} cpr_msg_queue_t;
+
+/*
+ * A enumeration used to report the result of posting a message to
+ * a message queue
+ */
+typedef enum
+{
+    CPR_MSGQ_POST_SUCCESS,
+    CPR_MSGQ_POST_FAILED,
+    CPR_MSGQ_POST_PENDING
+} cpr_msgq_post_result_e;
+
+
+/*
+ * Head of list of message queues
+ */
+static cpr_msg_queue_t *msgQueueList = NULL;
+
+/*
+ * Mutex to manage message queue list
+ */
+pthread_mutex_t msgQueueListMutex;
+
+/*
+ * CPR_MAX_MSG_Q_DEPTH
+ *
+ * The maximum queue depth supported by the CPR layer.  This value
+ * is arbitrary though the purpose is to limit the memory usage
+ * by CPR and avoid (nearly) unbounded situations.
+ *
+ * Note: This value should be greater than MSGTQL which is currently
+ *       defined as 31
+ */
+#define CPR_MAX_MSG_Q_DEPTH 256
+
+/*
+ * CPR_SND_TIMEOUT_WAIT_INTERVAL
+ *
+ * The interval of time to wait in milliseconds between attempts to
+ * send a message to the message queue
+ *
+ * Note: 20 ms. to avoid less than a tick wake up since on most
+ *       OSes 10ms is one 1 tick
+ *       this should really be OS_TICK_MS * 2 or OS_TICK_MS + X
+ */
+#define CPR_SND_TIMEOUT_WAIT_INTERVAL 20
+
+/*
+ * CPR_ATTEMPTS_TO_SEND
+ *
+ * The number of attempts made to send a message when the message
+ * would otherwise be blocked.  Note in this condition the thread
+ * will sleep the timeout interval to allow the msg queue to be
+ * drained.
+ *
+ * Note: 25 attempts for upto .5 seconds at the interval of
+ *       CPR_SND_TIMEOUT_WAIT_INTERVAL worst case.
+ */
+#define CPR_ATTEMPTS_TO_SEND 25
+
+/*
+ * Also, important to note that the total timeout interval must be
+ * greater than the SIP's select call timeout value which is 25msec.
+ * This is necessary to cover the case where the SIP message queue
+ * is full and the select timeout occurs.
+ *
+ * Total timeout interval = CPR_SND_TIMEOUT_WAIT_INTERVAL *
+ *                          CPR_ATTEMPTS_TO_SEND;
+ */
+
+
+/**
+ * Peg the statistics for successfully posting a message
+ *
+ * @param msgq        - message queue
+ * @param numAttempts - number of attempts to post message to message queue
+ *
+ * @return none
+ *
+ * @pre (msgq not_eq NULL)
+ */
+static void
+cprPegSendMessageStats (cpr_msg_queue_t *msgq, uint16_t numAttempts)
+{
+    /*
+     * Collect statistics
+     */
+    msgq->totalCount++;
+
+    if (numAttempts > msgq->highAttempts) {
+        msgq->highAttempts = numAttempts;
+    }
+}
+
+/**
+ * Post message to system message queue
+ *
+ * @param msgq       - message queue
+ * @param msg        - message to post
+ * @param ppUserData - ptr to ptr to option user data
+ *
+ * @return the post result which is CPR_MSGQ_POST_SUCCESS,
+ *         CPR_MSGQ_POST_FAILURE or CPR_MSGQ_POST_PENDING
+ *
+ * @pre (msgq not_eq NULL)
+ * @pre (msg not_eq NULL)
+ */
+static cpr_msgq_post_result_e
+cprPostMessage (cpr_msg_queue_t *msgq, void *msg, void **ppUserData)
+{
+    cpr_msgq_node_t *node;
+
+    /*
+     * Allocate new message queue node
+     */
+    node = cpr_malloc(sizeof(*node));
+    if (!node) {
+        errno = ENOMEM;
+        return CPR_MSGQ_POST_FAILED;
+    }
+
+    pthread_mutex_lock(&msgq->mutex);
+
+    /*
+     * Fill in data
+     */
+    node->msg = msg;
+    if (ppUserData != NULL) {
+        node->pUserData = *ppUserData;
+    } else {
+        node->pUserData = NULL;
+    }
+
+    /*
+     * Push onto list
+     */
+    node->prev = NULL;
+    node->next = msgq->head;
+    msgq->head = node;
+
+    if (node->next) {
+        node->next->prev = node;
+    }
+
+    if (msgq->tail == NULL) {
+        msgq->tail = node;
+    }
+    msgq->currentCount++;
+
+    pthread_cond_signal(&msgq->cond);
+    pthread_mutex_unlock(&msgq->mutex);
+
+    return CPR_MSGQ_POST_SUCCESS;
+
+}
+#endif /* !SIP_OS_WINDOWS */
+
+/*
+ * Functions
+ */
+
+/**
+ * Creates a message queue
+ *
+ * @param name  - name of the message queue
+ * @param depth - the message queue depth, optional field which will
+ *                default if set to zero(0).  This parameter is currently
+ *                not supported on Windows.
+ *
+ * @return Msg queue handle or NULL if init failed, errno provided
+ *
+ * @note the actual message queue depth will be bounded by the
+ *       standard system message queue depth and CPR_MAX_MSG_Q_DEPTH.
+ *       If 'depth' is outside of the bounds, the value will be
+ *       reset automatically.
+ */
+cprMsgQueue_t
+cprCreateMessageQueue (const char *name, uint16_t depth)
+{
+    cpr_msg_queue_t *msgq;
+
+    msgq = cpr_calloc(1, sizeof(cpr_msg_queue_t));
+    if (msgq == NULL) {
+        printf("%s: Malloc failed: %s\n", __FUNCTION__,
+               name ? name : "unnamed");
+        errno = ENOMEM;
+        return NULL;
+    }
+
+    msgq->name = name ? name : "unnamed";
+
+#ifndef SIP_OS_WINDOWS
+    static int key_id = 100; /* arbitrary starting number */
+    pthread_cond_t _cond = PTHREAD_COND_INITIALIZER;
+    pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
+
+    msgq->queueId = key_id++;
+    msgq->cond = _cond;
+    msgq->mutex = _lock;
+
+    /*
+     * Add message queue to list for statistics reporting
+     */
+    pthread_mutex_lock(&msgQueueListMutex);
+    msgq->next = msgQueueList;
+    msgQueueList = msgq;
+    pthread_mutex_unlock(&msgQueueListMutex);
+#endif /* SIP_OS_WINDOWS */
+
+    return msgq;
+}
+
+
+
+/**
+ * Associate a thread with the message queue
+ *
+ * @param msgQueue  - msg queue to set
+ * @param thread    - CPR thread to associate with queue
+ *
+ * @return CPR_SUCCESS or CPR_FAILURE
+ *
+ * @note Nothing is done to prevent overwriting the thread ID
+ *       when the value has already been set.
+ */
+cprRC_t
+cprSetMessageQueueThread (cprMsgQueue_t msgQueue, cprThread_t thread)
+{
+    cpr_msg_queue_t *msgq;
+
+    if ((!msgQueue) || (!thread)) {
+        CPR_ERROR("%s: Invalid input\n", __FUNCTION__);
+        return CPR_FAILURE;
+    }
+
+#ifdef SIP_OS_WINDOWS
+    ((cpr_msg_queue_t *)msgQueue)->handlePtr = thread;
+#else
+    msgq = (cpr_msg_queue_t *) msgQueue;
+    if (msgq->thread != 0) {
+        CPR_ERROR("%s: over-writing previously msgq thread name for %s",
+                  __FUNCTION__, msgq->name);
+    }
+
+    msgq->thread = cprGetThreadId(thread);
+#endif /* SIP_OS_WINDOWS */
+
+    return CPR_SUCCESS;
+}
+
+
+/**
+ * Retrieve a message from a particular message queue
+ *
+ * @param[in]  msgQueue    - msg queue from which to retrieve the message
+ * @param[in]  waitForever - boolean to either wait forever (TRUE) or not
+ *                           wait at all (FALSE) if the msg queue is empty.
+ * @param[out] ppUserData  - pointer to a pointer to user defined data
+ *
+ * @return Retrieved message buffer or NULL if failure occurred or
+ *         the waitForever flag was set to false and no messages were
+ *         on the queue.
+ *
+ * @note   If ppUserData is defined, the value will be initialized to NULL
+ */
+void *
+cprGetMessage (cprMsgQueue_t msgQueue, boolean waitForever, void **ppUserData)
+{
+    void *buffer = NULL;
+
+#ifdef SIP_OS_WINDOWS
+    struct msgbuffer *rcvMsg = (struct msgbuffer *)rcvBuffer;
+    cpr_msg_queue_t *pCprMsgQueue;
+    MSG msg;
+    cpr_thread_t *pThreadPtr;
+#endif
+
+    if (!msgQueue) {
+        CPR_ERROR("%s - invalid msgQueue\n", __FUNCTION__);
+        return NULL;
+    }
+
+    /* Initialize ppUserData */
+    if (ppUserData) {
+        *ppUserData = NULL;
+    }
+
+#ifdef SIP_OS_WINDOWS
+    pCprMsgQueue = (cpr_msg_queue_t *)msgQueue;
+    memset(&msg, 0, sizeof(MSG));
+
+    if (waitForever == TRUE) {
+        if (GetMessage(&msg, NULL, 0, 0) == -1) {
+            CPR_ERROR("%s - msgQueue = %x failed: %d\n",
+                      __FUNCTION__, msgQueue, GetLastError());
+            return NULL;
+        }
+    } else {
+        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == 0) {
+            /* no message present */
+            return NULL;
+        }
+    }
+
+    switch (msg.message) {
+        case WM_CLOSE:
+            if (msgQueue == &gsm_msgq)
+            {
+                CPR_ERROR("%s - WM_CLOSE GSM msg queue\n", __FUNCTION__);
+                gsm_shutdown();
+            }
+            else if (msgQueue == &sip_msgq)
+            {
+                CPR_ERROR("%s - WM_CLOSE SIP msg queue\n", __FUNCTION__);
+                sip_regmgr_destroy_cc_conns();
+                sip_shutdown();
+            }
+            else if (msgQueue == &tmr_msgq)
+            {
+                CPR_ERROR("%s - WM_CLOSE TMR msg queue\n", __FUNCTION__);
+            }
+
+            pThreadPtr=(cpr_thread_t *)pCprMsgQueue->handlePtr;
+            if (pThreadPtr)
+            {
+                CloseHandle(pThreadPtr->u.handlePtr);
+            }
+            /* zap the thread ptr, since the thread is going away now */
+            pCprMsgQueue->handlePtr = NULL;
+            _endthreadex(0);
+            break;
+        case MSG_BUF:
+            rcvMsg = (struct msgbuffer *)msg.wParam;
+            buffer = rcvMsg->msgPtr;
+            if (ppUserData) {
+                *ppUserData = rcvMsg->usrPtr;
+            }
+            cpr_free((void *)msg.wParam);
+            break;
+        case MSG_ECHO_EVENT:
+            {
+                HANDLE event;
+                event = (HANDLE*)msg.wParam;
+                SetEvent( event );
+            }
+            break;
+        case WM_TIMER:
+            DispatchMessage(&msg);
+            return NULL;
+            break;
+        default:
+            break;
+    }
+#else
+    cpr_msg_queue_t *msgq;
+    cpr_msgq_node_t *node;
+    struct timespec timeout;
+    struct timeval tv;
+    struct timezone tz;
+
+    msgq = (cpr_msg_queue_t *) msgQueue;
+
+    /*
+     * If waitForever is set, block on the message queue
+     * until a message is received, else return after
+     * 25msec of waiting
+     */
+    pthread_mutex_lock(&msgq->mutex);
+
+    if (!waitForever)
+    {
+        // We'll wait till 25uSec from now
+        gettimeofday(&tv, &tz);
+        timeout.tv_nsec = (tv.tv_usec * 1000) + 25000;
+        timeout.tv_sec = tv.tv_sec;
+
+        pthread_cond_timedwait(&msgq->cond, &msgq->mutex, &timeout);
+    }
+    else
+    {
+        while(msgq->tail==NULL)
+        {
+            pthread_cond_wait(&msgq->cond, &msgq->mutex);
+        }
+    }
+
+    // If there is a message on the queue, de-queue it
+    if (msgq->tail)
+    {
+        node = msgq->tail;
+        msgq->tail = node->prev;
+        if (msgq->tail) {
+            msgq->tail->next = NULL;
+        }
+        if (msgq->head == node) {
+            msgq->head = NULL;
+        }
+        msgq->currentCount--;
+        /*
+         * Pull out the data
+         */
+        if (ppUserData) {
+            *ppUserData = node->pUserData;
+        }
+        buffer = node->msg;
+
+    }
+
+    pthread_mutex_unlock(&msgq->mutex);
+#endif /* SIP_OS_WINDOWS */
+
+    return buffer;
+}
+
+
+/**
+ * Place a message on a particular queue.  Note that caller may
+ * block (see comments below)
+ *
+ * @param msgQueue   - msg queue on which to place the message
+ * @param msg        - pointer to the msg to place on the queue
+ * @param ppUserData - pointer to a pointer to user defined data
+ *
+ * @return CPR_SUCCESS or CPR_FAILURE, errno provided
+ *
+ * @note 1. Messages queues are set to be non-blocking, those cases
+ *       where the system call fails with a would-block error code
+ *       (EAGAIN) the function will attempt other mechanisms described
+ *       below.
+ * @note 2. If enabled with an extended message queue, either via a
+ *       call to cprCreateMessageQueue with depth value or a call to
+ *       cprSetExtendMessageQueueDepth() (when unit testing), the message
+ *       will be added to the extended message queue and the call will
+ *       return successfully.  When room becomes available on the
+ *       system's message queue, those messages will be added.
+ * @note 3. If the message queue becomes full and no space is availabe
+ *       on the extended message queue, then the function will attempt
+ *       to resend the message up to CPR_ATTEMPTS_TO_SEND and the
+ *       calling thread will *BLOCK* CPR_SND_TIMEOUT_WAIT_INTERVAL
+ *       milliseconds after each failed attempt.  If unsuccessful
+ *       after all attempts then EGAIN error code is returned.
+ * @note 4. This applies to all CPR threads, including the timer thread.
+ *       So it is possible that the timer thread would be forced to
+ *       sleep which would have the effect of delaying all active
+ *       timers.  The work to fix this rare situation is not considered
+ *       worth the effort to fix....so just leaving as is.
+ */
+cprRC_t
+cprSendMessage (cprMsgQueue_t msgQueue, void *msg, void **ppUserData)
+{
+#ifdef SIP_OS_WINDOWS
+    struct msgbuffer *sendMsg;
+    cpr_thread_t *pCprThread;
+    HANDLE *hThread;
+#endif
+
+    if (!msgQueue) {
+        CPR_ERROR("%s - msgQueue is NULL\n", __FUNCTION__);
+        return CPR_FAILURE;
+    }
+
+#ifdef SIP_OS_WINDOWS
+    pCprThread = (cpr_thread_t *)(((cpr_msg_queue_t *)msgQueue)->handlePtr);
+    if (!pCprThread) {
+        CPR_ERROR("%s - msgQueue(%x) not associated with a thread\n",
+                  __FUNCTION__, msgQueue);
+        return CPR_FAILURE;
+    }
+
+    hThread = (HANDLE*)(pCprThread->u.handlePtr);
+    if (!hThread) {
+        CPR_ERROR("%s - msgQueue(%x)'s thread(%x) not assoc. with Windows\n",
+                __FUNCTION__, msgQueue, pCprThread);
+        return CPR_FAILURE;
+    }
+
+    /* Package up the message */
+    sendMsg = (struct msgbuffer *)cpr_calloc(1, sizeof(struct msgbuffer));
+    if (!sendMsg) {
+        CPR_ERROR("%s - No memory\n", __FUNCTION__);
+        return CPR_FAILURE;
+    }
+    sendMsg->mtype = PHONE_IPC_MSG;
+
+    /* Save the address of the message */
+    sendMsg->msgPtr = msg;
+
+    /* Allow the ppUserData to be optional */
+    if (ppUserData) {
+        sendMsg->usrPtr = *ppUserData;
+    }
+
+    /* Post the message */
+    if (hThread == NULL || PostThreadMessage(pCprThread->threadId, MSG_BUF,
+        (WPARAM)sendMsg, 0) == 0 ) {
+        CPR_ERROR("%s - Msg not sent: %d\n", __FUNCTION__, GetLastError());
+        cpr_free(sendMsg);
+        return CPR_FAILURE;
+    }
+    return CPR_SUCCESS;
+
+#else
+    static const char error_str[] = "%s: Msg not sent to %s queue: %s\n";
+    cpr_msgq_post_result_e rc;
+    cpr_msg_queue_t *msgq;
+    int16_t attemptsToSend = CPR_ATTEMPTS_TO_SEND;
+    uint16_t numAttempts   = 0;
+
+    msgq = (cpr_msg_queue_t *) msgQueue;
+
+    /*
+     * Attempt to send message
+     */
+    do {
+
+        /*
+         * Post the message to the Queue
+         */
+        rc = cprPostMessage(msgq, msg, ppUserData);
+
+        if (rc == CPR_MSGQ_POST_SUCCESS) {
+            cprPegSendMessageStats(msgq, numAttempts);
+            return CPR_SUCCESS;
+        } else if (rc == CPR_MSGQ_POST_FAILED) {
+            CPR_ERROR("%s: Msg not sent to %s queue: %d\n",
+                      __FUNCTION__, msgq->name, errno);
+            msgq->sendErrors++;
+            /*
+             * If posting to calling thread's own queue,
+             * then peg the self queue error.
+             */
+            if (pthread_self() == msgq->thread) {
+                msgq->selfQErrors++;
+            }
+
+            return CPR_FAILURE;
+        }
+
+
+        /*
+         * Did not succeed in sending the message, so continue
+         * to attempt up to the CPR_ATTEMPTS_TO_SEND.
+         */
+        attemptsToSend--;
+        if (attemptsToSend > 0) {
+            /*
+             * Force a context-switch of the thread attempting to
+             * send the message, in order to help the case where
+             * the msg queue is full and the owning thread may get
+             * a a chance be scheduled so it can drain it (Note:
+             * no guarantees, more of a "last-ditch effort" to
+             * recover...especially when temporarily over-whelmed).
+             */
+            cprSleep(CPR_SND_TIMEOUT_WAIT_INTERVAL);
+            msgq->reTries++;
+            numAttempts++;
+        }
+    } while (attemptsToSend > 0);
+
+    CPR_ERROR(error_str, __FUNCTION__, msgq->name, "FULL");
+    msgq->sendErrors++;
+    return CPR_FAILURE;
+#endif /* SIP_OS_WINDOWS */
+}
+
+
+
+/**
+ * cprGetDepth
+ *
+ * @brief get depth of a message queue
+ *
+ * The pSIPCC uses this API to look at the depth of a message queue for internal
+ * routing and throttling decision
+ *
+ * @param[in] msgQueue - message queue
+ *
+ * @return depth of msgQueue
+ *
+ * @pre (msgQueue not_eq NULL)
+ */
+uint16_t cprGetDepth (cprMsgQueue_t msgQueue)
+{
+#ifdef SIP_OS_WINDOWS
+    return 0;
+#else
+    cpr_msg_queue_t *msgq;
+    msgq = (cpr_msg_queue_t *) msgQueue;
+    return msgq->currentCount;
+#endif /* SIP_OS_WINDOWS */
+}
+
+
deleted file mode 100644
--- a/media/webrtc/signaling/src/sipcc/cpr/darwin/cpr_darwin_ipc.c
+++ /dev/null
@@ -1,611 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "cpr.h"
-#include "cpr_stdlib.h"
-#include <cpr_stdio.h>
-#include <errno.h>
-#include <sys/time.h>
-#include <time.h>
-#include <plat_api.h>
-#include "cpr_string.h"
-
-/*
- * If building with debug test interface,
- * allow access to internal CPR functions
- */
-#define STATIC static
-
-#define OS_MSGTQL 31 /* need to check number for MV linux and put here */
-
-/*
- * Internal CPR API
- */
-extern pthread_t cprGetThreadId(cprThread_t thread);
-
-/*
- * Extended internal message queue node
- *
- * A double-linked list holding the nessasary message information
- */
-typedef struct cpr_msgq_node_s
-{
-    struct cpr_msgq_node_s *next;
-    struct cpr_msgq_node_s *prev;
-    void *msg;
-    void *pUserData;
-} cpr_msgq_node_t;
-
-/*
- * Msg queue information needed to hide OS differences in implementation.
- * To use msg queues, the application code may pass in a name to the
- * create function for msg queues. CPR does not use this field, it is
- * solely for the convenience of the application and to aid in debugging.
- *
- * Note: Statistics are not protected by a mutex; therefore, there exists
- * the possibility that the results may not be accurate.
- *
- * Note:if the depth supplied by OS is insufficient,a message queue owner may
- * increase the message queue depth via cprCreateMessageQueue's depth
- * parameter where the value can range from MSGTQL to CPR_MAX_MSG_Q_DEPTH.
- */
-typedef struct cpr_msg_queue_s
-{
-    struct cpr_msg_queue_s *next;
-    const char *name;
-    pthread_t thread;
-    int32_t queueId;
-    uint16_t currentCount;
-    uint32_t totalCount;
-    uint32_t sendErrors;
-    uint32_t reTries;
-    uint32_t highAttempts;
-    uint32_t selfQErrors;
-    uint16_t extendedQDepth;
-    uint16_t maxExtendedQDepth;
-    pthread_mutex_t mutex;       /* lock for managing extended queue     */
-	pthread_cond_t cond;		 /* signal for queue/dequeue */
-    cpr_msgq_node_t *head;       /* extended queue head (newest element) */
-    cpr_msgq_node_t *tail;       /* extended queue tail (oldest element) */
-} cpr_msg_queue_t;
-
-/*
- * A enumeration used to report the result of posting a message to
- * a message queue
- */
-typedef enum
-{
-    CPR_MSGQ_POST_SUCCESS,
-    CPR_MSGQ_POST_FAILED,
-    CPR_MSGQ_POST_PENDING
-} cpr_msgq_post_result_e;
-
-
-/*
- * Head of list of message queues
- */
-static cpr_msg_queue_t *msgQueueList = NULL;
-
-/*
- * Mutex to manage message queue list
- */
-pthread_mutex_t msgQueueListMutex;
-
-/*
- * String to represent message queue name when it is not provided
- */
-static const char unnamed_string[] = "unnamed";
-
-
-/*
- * CPR_MAX_MSG_Q_DEPTH
- *
- * The maximum queue depth supported by the CPR layer.  This value
- * is arbitrary though the purpose is to limit the memory usage
- * by CPR and avoid (nearly) unbounded situations.
- *
- * Note: This value should be greater than MSGTQL which is currently
- *       defined as 31
- */
-#define CPR_MAX_MSG_Q_DEPTH 256
-
-/*
- * CPR_SND_TIMEOUT_WAIT_INTERVAL
- *
- * The interval of time to wait in milliseconds between attempts to
- * send a message to the message queue
- *
- * Note: 20 ms. to avoid less than a tick wake up since on most
- *       OSes 10ms is one 1 tick
- *       this should really be OS_TICK_MS * 2 or OS_TICK_MS + X
- */
-#define CPR_SND_TIMEOUT_WAIT_INTERVAL 20
-
-/*
- * CPR_ATTEMPTS_TO_SEND
- *
- * The number of attempts made to send a message when the message
- * would otherwise be blocked.  Note in this condition the thread
- * will sleep the timeout interval to allow the msg queue to be
- * drained.
- *
- * Note: 25 attempts for upto .5 seconds at the interval of
- *       CPR_SND_TIMEOUT_WAIT_INTERVAL worst case.
- */
-#define CPR_ATTEMPTS_TO_SEND 25
-
-/*
- * Also, important to note that the total timeout interval must be
- * greater than the SIP's select call timeout value which is 25msec.
- * This is necessary to cover the case where the SIP message queue
- * is full and the select timeout occurs.
- *
- * Total timeout interval = CPR_SND_TIMEOUT_WAIT_INTERVAL *
- *                          CPR_ATTEMPTS_TO_SEND;
- */
-
-
-/*
- * Prototype declarations
- */
-static cpr_msgq_post_result_e
-cprPostMessage(cpr_msg_queue_t *msgq, void *msg, void **ppUserData);
-static void
-cprPegSendMessageStats(cpr_msg_queue_t *msgq, uint16_t numAttempts);
-
-
-/*
- * Functions
- */
-
-/**
- * Creates a message queue
- *
- * @param name  - name of the message queue
- * @param depth - the message queue depth, optional field which will
- *                default if set to zero(0)
- *
- * @return Msg queue handle or NULL if init failed, errno provided
- *
- * @note the actual message queue depth will be bounded by the
- *       standard system message queue depth and CPR_MAX_MSG_Q_DEPTH.
- *       If 'depth' is outside of the bounds, the value will be
- *       reset automatically.
- */
-cprMsgQueue_t
-cprCreateMessageQueue (const char *name, uint16_t depth)
-{
-    static const char fname[] = "cprCreateMessageQueue";
-    cpr_msg_queue_t *msgq;
-    static int key_id = 100; /* arbitrary starting number */
-
-    msgq = cpr_calloc(1, sizeof(cpr_msg_queue_t));
-    if (msgq == NULL) {
-        printf("%s: Malloc failed: %s\n", fname,
-                  name ? name : unnamed_string);
-        errno = ENOMEM;
-        return NULL;
-    }
-
-    msgq->name = name ? name : unnamed_string;
-	msgq->queueId = key_id++;
-
-	pthread_cond_t _cond = PTHREAD_COND_INITIALIZER;
-	msgq->cond = _cond;
-	pthread_mutex_t _lock = PTHREAD_MUTEX_INITIALIZER;
-	msgq->mutex = _lock;
-
-    /*
-     * Add message queue to list for statistics reporting
-     */
-    pthread_mutex_lock(&msgQueueListMutex);
-    msgq->next = msgQueueList;
-    msgQueueList = msgq;
-    pthread_mutex_unlock(&msgQueueListMutex);
-
-    return msgq;
-}
-
-
-/**
- * Removes all messages from the queue and then destroy the message queue
- *
- * @param msgQueue - message queue to destroy
- *
- * @return CPR_SUCCESS or CPR_FAILURE, errno provided
- */
-cprRC_t
-cprDestroyMessageQueue (cprMsgQueue_t msgQueue)
-{
-    static const char fname[] = "cprDestroyMessageQueue";
-    cpr_msg_queue_t *msgq;
-    void *msg;
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq == NULL) {
-        /* Bad application! */
-        CPR_ERROR("%s: Invalid input\n", fname);
-        errno = EINVAL;
-        return CPR_FAILURE;
-    }
-
-    /* Drain message queue */
-    msg = cprGetMessage(msgQueue, FALSE, NULL);
-    while (msg != NULL) {
-        cpr_free(msg);
-        msg = cprGetMessage(msgQueue, FALSE, NULL);
-    }
-
-    /* Remove message queue from list */
-    pthread_mutex_lock(&msgQueueListMutex);
-    if (msgq == msgQueueList) {
-        msgQueueList = msgq->next;
-    } else {
-        cpr_msg_queue_t *msgql = msgQueueList;
-
-        while ((msgql->next != NULL) && (msgql->next != msgq)) {
-            msgql = msgql->next;
-        }
-        if (msgql->next == msgq) {
-            msgql->next = msgq->next;
-        }
-    }
-    pthread_mutex_unlock(&msgQueueListMutex);
-
-    /* Remove message queue mutex */
-    if (pthread_mutex_destroy(&msgq->mutex) != 0) {
-        CPR_ERROR("%s: Failed to destroy msg queue (%s) mutex: %d\n",
-                  fname, msgq->name, errno);
-    }
-
-    cpr_free(msgq);
-    return CPR_SUCCESS;
-}
-
-
-/**
- * Associate a thread with the message queue
- *
- * @param msgQueue  - msg queue to set
- * @param thread    - CPR thread to associate with queue
- *
- * @return CPR_SUCCESS or CPR_FAILURE
- *
- * @note Nothing is done to prevent overwriting the thread ID
- *       when the value has already been set.
- */
-cprRC_t
-cprSetMessageQueueThread (cprMsgQueue_t msgQueue, cprThread_t thread)
-{
-    static const char fname[] = "cprSetMessageQueueThread";
-    cpr_msg_queue_t *msgq;
-
-    if ((!msgQueue) || (!thread)) {
-        CPR_ERROR("%s: Invalid input\n", fname);
-        return CPR_FAILURE;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq->thread != 0) {
-        CPR_ERROR("%s: over-writing previously msgq thread name for %s",
-                  fname, msgq->name);
-    }
-
-    msgq->thread = cprGetThreadId(thread);
-    return CPR_SUCCESS;
-}
-
-
-/**
- * Retrieve a message from a particular message queue
- *
- * @param[in]  msgQueue    - msg queue from which to retrieve the message
- * @param[in]  waitForever - boolean to either wait forever (TRUE) or not
- *                           wait at all (FALSE) if the msg queue is empty.
- * @param[out] ppUserData  - pointer to a pointer to user defined data
- *
- * @return Retrieved message buffer or NULL if failure occurred or
- *         the waitForever flag was set to false and no messages were
- *         on the queue.
- *
- * @note   If ppUserData is defined, the value will be initialized to NULL
- */
-void *
-cprGetMessage (cprMsgQueue_t msgQueue, boolean waitForever, void **ppUserData)
-{
-    static const char fname[] = "cprGetMessage";
-
-    void *buffer = 0;
-    cpr_msg_queue_t *msgq;
-    cpr_msgq_node_t *node;
-	struct timespec timeout;
-	struct timeval tv;
-#ifndef __APPLE__
-	struct timezone tz;
-#else
-	// On the iPhone, there is a DarwinAlias problem with "timezone"
-	struct _timezone {
-		int     tz_minuteswest; /* of Greenwich */
-		int     tz_dsttime;     /* type of dst correction to apply */
-	} tz;
-#endif
-
-    /* Initialize ppUserData */
-    if (ppUserData) {
-        *ppUserData = NULL;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq == NULL) {
-        /* Bad application! */
-        CPR_ERROR("%s: Invalid input\n", fname);
-        errno = EINVAL;
-        return NULL;
-    }
-
-    /*
-     * If waitForever is set, block on the message queue
-     * until a message is received, else return after
-	 * 25msec of waiting
-     */
-	pthread_mutex_lock(&msgq->mutex);
-
-	if (!waitForever)
-	{
-		// We'll wait till 25uSec from now
-		gettimeofday(&tv, &tz);
-		timeout.tv_nsec = (tv.tv_usec * 1000) + 25000;
-		timeout.tv_sec = tv.tv_sec;
-
-		pthread_cond_timedwait(&msgq->cond, &msgq->mutex, &timeout);
-
-	}
-	else
-	{
-		while(msgq->tail==NULL)
-		{
-			pthread_cond_wait(&msgq->cond, &msgq->mutex);
-		}
-	}
-
-	// If there is a message on the queue, de-queue it
-	if (msgq->tail)
-	{
-		node = msgq->tail;
-		msgq->tail = node->prev;
-		if (msgq->tail) {
-			msgq->tail->next = NULL;
-		}
-		if (msgq->head == node) {
-			msgq->head = NULL;
-		}
-		msgq->currentCount--;
-		/*
-		 * Pull out the data
-		 */
-		if (ppUserData) {
-			*ppUserData = node->pUserData;
-		}
-		buffer = node->msg;
-
-	}
-
-	pthread_mutex_unlock(&msgq->mutex);
-
-    return buffer;
-}
-
-
-/**
- * Place a message on a particular queue.  Note that caller may
- * block (see comments below)
- *
- * @param msgQueue   - msg queue on which to place the message
- * @param msg        - pointer to the msg to place on the queue
- * @param ppUserData - pointer to a pointer to user defined data
- *
- * @return CPR_SUCCESS or CPR_FAILURE, errno provided
- *
- * @note 1. Messages queues are set to be non-blocking, those cases
- *       where the system call fails with a would-block error code
- *       (EAGAIN) the function will attempt other mechanisms described
- *       below.
- * @note 2. If enabled with an extended message queue, either via a
- *       call to cprCreateMessageQueue with depth value or a call to
- *       cprSetExtendMessageQueueDepth() (when unit testing), the message
- *       will be added to the extended message queue and the call will
- *       return successfully.  When room becomes available on the
- *       system's message queue, those messages will be added.
- * @note 3. If the message queue becomes full and no space is availabe
- *       on the extended message queue, then the function will attempt
- *       to resend the message up to CPR_ATTEMPTS_TO_SEND and the
- *       calling thread will *BLOCK* CPR_SND_TIMEOUT_WAIT_INTERVAL
- *       milliseconds after each failed attempt.  If unsuccessful
- *       after all attempts then EGAIN error code is returned.
- * @note 4. This applies to all CPR threads, including the timer thread.
- *       So it is possible that the timer thread would be forced to
- *       sleep which would have the effect of delaying all active
- *       timers.  The work to fix this rare situation is not considered
- *       worth the effort to fix....so just leaving as is.
- */
-cprRC_t
-cprSendMessage (cprMsgQueue_t msgQueue, void *msg, void **ppUserData)
-{
-    static const char fname[] = "cprSendMessage";
-    static const char error_str[] = "%s: Msg not sent to %s queue: %s\n";
-    cpr_msgq_post_result_e rc;
-    cpr_msg_queue_t *msgq;
-    int16_t attemptsToSend = CPR_ATTEMPTS_TO_SEND;
-    uint16_t numAttempts   = 0;
-
-    /* Bad application? */
-    if (msgQueue == NULL) {
-        CPR_ERROR(error_str, fname, "undefined", "invalid input");
-        errno = EINVAL;
-        return CPR_FAILURE;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-
-    /*
-     * Attempt to send message
-     */
-    do {
-
-		/*
-		 * Post the message to the Queue
-		 */
-		rc = cprPostMessage(msgq, msg, ppUserData);
-
-		if (rc == CPR_MSGQ_POST_SUCCESS) {
-			cprPegSendMessageStats(msgq, numAttempts);
-			return CPR_SUCCESS;
-		} else if (rc == CPR_MSGQ_POST_FAILED) {
-			CPR_ERROR("%s: Msg not sent to %s queue: %d\n",
-					  fname, msgq->name, errno);
-			msgq->sendErrors++;
-			/*
-			 * If posting to calling thread's own queue,
-			 * then peg the self queue error.
-			 */
-			if (pthread_self() == msgq->thread) {
-				msgq->selfQErrors++;
-			}
-
-			return CPR_FAILURE;
-		}
-
-
-        /*
-         * Did not succeed in sending the message, so continue
-         * to attempt up to the CPR_ATTEMPTS_TO_SEND.
-         */
-        attemptsToSend--;
-        if (attemptsToSend > 0) {
-            /*
-             * Force a context-switch of the thread attempting to
-             * send the message, in order to help the case where
-             * the msg queue is full and the owning thread may get
-             * a a chance be scheduled so it can drain it (Note:
-             * no guarantees, more of a "last-ditch effort" to
-             * recover...especially when temporarily over-whelmed).
-             */
-            cprSleep(CPR_SND_TIMEOUT_WAIT_INTERVAL);
-            msgq->reTries++;
-            numAttempts++;
-        }
-    } while (attemptsToSend > 0);
-
-    CPR_ERROR(error_str, fname, msgq->name, "FULL");
-    msgq->sendErrors++;
-    return CPR_FAILURE;
-}
-
-/**
- * Peg the statistics for successfully posting a message
- *
- * @param msgq        - message queue
- * @param numAttempts - number of attempts to post message to message queue
- *
- * @return none
- *
- * @pre (msgq not_eq NULL)
- */
-static void
-cprPegSendMessageStats (cpr_msg_queue_t *msgq, uint16_t numAttempts)
-{
-    /*
-     * Collect statistics
-     */
-    msgq->totalCount++;
-
-    if (numAttempts > msgq->highAttempts) {
-        msgq->highAttempts = numAttempts;
-    }
-}
-
-/**
- * Post message to system message queue
- *
- * @param msgq       - message queue
- * @param msg        - message to post
- * @param ppUserData - ptr to ptr to option user data
- *
- * @return the post result which is CPR_MSGQ_POST_SUCCESS,
- *         CPR_MSGQ_POST_FAILURE or CPR_MSGQ_POST_PENDING
- *
- * @pre (msgq not_eq NULL)
- * @pre (msg not_eq NULL)
- */
-static cpr_msgq_post_result_e
-cprPostMessage (cpr_msg_queue_t *msgq, void *msg, void **ppUserData)
-{
-	cpr_msgq_node_t *node;
-
-	/*
-	 * Allocate new message queue node
-	 */
-	node = cpr_malloc(sizeof(*node));
-	if (!node) {
-		errno = ENOMEM;
-		return CPR_MSGQ_POST_FAILED;
-	}
-
-	pthread_mutex_lock(&msgq->mutex);
-
-	/*
-	 * Fill in data
-	 */
-	node->msg = msg;
-	if (ppUserData != NULL) {
-		node->pUserData = *ppUserData;
-	} else {
-		node->pUserData = NULL;
-	}
-
-	/*
-	 * Push onto list
-	 */
-	node->prev = NULL;
-	node->next = msgq->head;
-	msgq->head = node;
-
-	if (node->next) {
-		node->next->prev = node;
-	}
-
-	if (msgq->tail == NULL) {
-		msgq->tail = node;
-	}
-	msgq->currentCount++;
-
-	pthread_cond_signal(&msgq->cond);
-	pthread_mutex_unlock(&msgq->mutex);
-
-	return CPR_MSGQ_POST_SUCCESS;
-
-}
-
-
-/**
- * cprGetDepth
- *
- * @brief get depth of a message queue
- *
- * The pSIPCC uses this API to look at the depth of a message queue for internal
- * routing and throttling decision
- *
- * @param[in] msgQueue - message queue
- *
- * @return depth of msgQueue
- *
- * @pre (msgQueue not_eq NULL)
- */
-uint16_t cprGetDepth (cprMsgQueue_t msgQueue)
-{
-        cpr_msg_queue_t *msgq;
-        msgq = (cpr_msg_queue_t *) msgQueue;
-        return msgq->currentCount;
-}
-
deleted file mode 100644
--- a/media/webrtc/signaling/src/sipcc/cpr/darwin/cpr_darwin_ipc.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef _CPR_DARWIN_IPC_H_
-#define _CPR_DARWIN_IPC_H_
-
-#include "cpr_threads.h"
-#include <pthread.h>
-
-/* Enable support for cprSetMessageQueueThread API */
-#define CPR_USE_SET_MESSAGE_QUEUE_THREAD
-
-/* Maximum message size allowed by CNU */
-#define CPR_MAX_MSG_SIZE  8192
-
-/* Our CNU msgtype */
-#define PHONE_IPC_MSG 1
-
-
-/* For gathering statistics regarding message queues */
-typedef struct {
-    char name[16];
-    uint16_t currentCount;
-    uint32_t totalCount;
-    uint32_t rcvTimeouts;
-    uint32_t sendErrors;
-    uint32_t reTries;
-    uint32_t highAttempts;
-    uint32_t selfQErrors;
-    uint16_t extendedDepth;
-} cprMsgQueueStats_t;
-
-/*
- * Mutex for updating the message queue list
- */
-extern pthread_mutex_t msgQueueListMutex;
-
-/**
- * cprGetDepth
- *
- * Get depth of a message queue
- */
-uint16_t cprGetDepth(cprMsgQueue_t msgQueue);
-
-
-#endif
--- a/media/webrtc/signaling/src/sipcc/cpr/include/cpr_ipc.h
+++ b/media/webrtc/signaling/src/sipcc/cpr/include/cpr_ipc.h
@@ -1,38 +1,62 @@
 /* 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 _CPR_IPC_H_
 #define _CPR_IPC_H_
 
 #include "cpr_types.h"
+#include "cpr_threads.h"
+
+#ifndef SIP_OS_WINDOWS
+#include <pthread.h>
+#endif /* !SIP_OS_WINDOWS */
 
 __BEGIN_DECLS
 
 /**
  * Define handle for message queues
  */
 typedef void* cprMsgQueue_t;
 
 /*
  * A timeout value of -1 means wait forever when
  * attempting to get a message. Just #define something
  * so the application code is easier to read.
  */
 #define WAIT_FOREVER -1
 
-#if defined SIP_OS_LINUX
-#include "../linux/cpr_linux_ipc.h"
-#elif defined SIP_OS_WINDOWS
-#include "../win32/cpr_win_ipc.h"
-#elif defined SIP_OS_OSX
-#include "../darwin/cpr_darwin_ipc.h"
-#endif
+/* Enable support for cprSetMessageQueueThread API */
+#define CPR_USE_SET_MESSAGE_QUEUE_THREAD
+
+/* Maximum message size allowed by CNU */
+#define CPR_MAX_MSG_SIZE  8192
+
+/* Our CNU msgtype */
+#ifdef SIP_OS_WINDOWS
+#define PHONE_IPC_MSG 0xF005
+
+/* Msg buffer layout */
+struct msgbuffer {
+    int32_t mtype; /* Message type */
+    void *msgPtr;  /* Ptr to msg */
+    void *usrPtr;  /* Ptr to user data */
+};
+
+#else
+#define PHONE_IPC_MSG 1
+
+/*
+ * Mutex for updating the message queue list
+ */
+extern pthread_mutex_t msgQueueListMutex;
+
+#endif /* SIP_OS_WINDOWS */
 
 /* Function prototypes */
 /**
  * Creates a message queue
  *
  * @brief The cprCreateMessageQueue function is called to allow the OS to
  * perform whatever work is needed to create a message queue.
 
@@ -55,33 +79,16 @@ typedef void* cprMsgQueue_t;
  *       standard system message queue depth and CPR_MAX_MSG_Q_DEPTH.
  *       If 'depth' is outside of the bounds, the value will be
  *       reset automatically.
  */
 cprMsgQueue_t
 cprCreateMessageQueue(const char *name, uint16_t depth);
 
 
-/**
-  * cprDestroyMessageQueue
- * @brief Removes all messages from the queue and then destroy the message queue
- *
- * The cprDestroyMessageQueue function is called to destroy a message queue. The
- * function drains any messages from the queue and the frees the
- * message queue. Any messages on the queue are to be deleted, and not sent to the intended
- * recipient. It is the application's responsibility to ensure that no threads are
- * blocked on a message queue when it is destroyed.
- *
- * @param[in] msgQueue - message queue to destroy
- *
- * @return CPR_SUCCESS or CPR_FAILURE, errno should be provided in this case
- */
-cprRC_t
-cprDestroyMessageQueue(cprMsgQueue_t msgQueue);
-
 #ifdef CPR_USE_SET_MESSAGE_QUEUE_THREAD
 /**
   * cprSetMessageQueueThread
  * @brief Associate a thread with the message queue
  *
  * This method is used by pSIPCC to associate a thread and a message queue.
  * @param[in] msgQueue  - msg queue to set
  * @param[in] thread    - CPR thread to associate with queue
@@ -154,12 +161,19 @@ cprGetMessage(cprMsgQueue_t msgQueue,
  *       timers.  The work to fix this rare situation is not considered
  *       worth the effort to fix....so just leaving as is.
  */
 cprRC_t
 cprSendMessage(cprMsgQueue_t msgQueue,
                void* msg,
                void** usrPtr);
 
+/**
+ * cprGetDepth
+ *
+ * Get depth of a message queue
+ */
+uint16_t cprGetDepth(cprMsgQueue_t msgQueue);
+
 __END_DECLS
 
 #endif
 
deleted file mode 100644
--- a/media/webrtc/signaling/src/sipcc/cpr/linux/cpr_linux_ipc.c
+++ /dev/null
@@ -1,965 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-/**
- *  @brief CPR layer for interprocess communication
- *
- * The name of this file may be overly broad, rather this file deals
- * with IPC via message queues.  A user may create, destroy and
- * associate a thread with a message queue.  Once established, messages
- * can be delivered and retrieved.
- *
- * The send/get APIs attempt to reliably deliver messages even when
- * under stress.  Two mechanisms have been added to deal with a full
- * message queue.  First, the message queue size may be extended to
- * allow more messages to be handled than supported by an OS.
- * Second, if the queue is indeed full a sleep-and-retry
- * method is used to force a context-switch to allow for other threads
- * to run in hope of clearing some messages off of the queue.  The
- * latter method is always-on by default.  The former method must be
- * enabled by extending the message queue by some size greater than
- * zero (0).
- *
- * @defgroup IPC The Inter Process Communication module
- * @ingroup CPR
- * @brief The module related to IPC abstraction for the pSIPCC
- * @addtogroup MsgQIPCAPIs The Message Queue IPC APIs
- * @ingroup IPC
- * @brief APIs expected by pSIPCC for using message queues
- *
- * @{
- *
- *
- */
-#include "cpr.h"
-#include "cpr_stdlib.h"
-#include <cpr_stdio.h>
-#include <errno.h>
-#if defined(WEBRTC_GONK)
-#include <sys/syscall.h>
-#include <unistd.h>
-#include <linux/msg.h>
-#include <linux/ipc.h>
-#else
-#include <sys/msg.h>
-#include <sys/ipc.h>
-#endif
-#include "plat_api.h"
-#include "CSFLog.h"
-
-static const char *logTag = "cpr_linux_ipc";
-
-#define STATIC static
-
-#if defined(WEBRTC_GONK)
-
-#if defined(__i386__)
-# include <asm-generic/ipc.h>
-#endif /* __i386__ */
-
-int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
-{
-#if defined(__i386__)
-  return syscall(__NR_ipc, MSGSND, msqid, msgsz, msgflg, msgp);
-#else
-  return syscall(__NR_msgsnd, msqid, msgp, msgsz, msgflg);
-#endif
-}
-
-ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
-{
-#if defined(__i386__)
-  struct ipc_kludge tmp = {
-    .msgp = msgp,
-    .msgtyp = msgtyp
-  };
-
-  return syscall(__NR_ipc, MSGRCV, msqid, msgsz, msgflg, &tmp);
-#else
-  return syscall(__NR_msgrcv, msqid, msgp, msgsz, msgtyp, msgflg);
-#endif
-}
-
-int msgctl(int msqid, int cmd, struct msqid_ds *buf)
-{
-#if defined(__i386__)
-  /* Android defines |struct ipc_perm| as old ABI. */
-  return syscall(__NR_ipc, MSGCTL, msqid, cmd | IPC_64, 0, buf);
-#else
-  return syscall(__NR_msgctl, msqid, cmd, buf);
-#endif
-}
-
-int msgget(key_t key, int msgflg)
-{
-#if defined(__i386__)
-  return syscall(__NR_ipc, MSGGET, key, msgflg, 0, NULL);
-#else
-  return syscall(__NR_msgget, key, msgflg);
-#endif
-}
-#endif
-
-/* @def The Message Queue depth */
-#define OS_MSGTQL 31
-
-/*
- * Internal CPR API
- */
-extern pthread_t cprGetThreadId(cprThread_t thread);
-
-/**
- * @struct cpr_msgq_node_s
- * Extended internal message queue node
- *
- * A double-linked list holding the necessary message information
- */
-typedef struct cpr_msgq_node_s
-{
-    struct cpr_msgq_node_s *next;
-    struct cpr_msgq_node_s *prev;
-    void *msg;
-    void *pUserData;
-} cpr_msgq_node_t;
-
-/**
- * @struct cpr_msg_queue_s
- * Msg queue information needed to hide OS differences in implementation.
- * To use msg queues, the application code may pass in a name to the
- * create function for msg queues. CPR does not use this field, it is
- * solely for the convenience of the application and to aid in debugging.
- *
- * Note: Statistics are not protected by a mutex; therefore, there exists
- * the possibility that the results may not be accurate.
- *
- * Note:if the depth supplied by OS is insufficient,a message queue owner may
- * increase the message queue depth via cprCreateMessageQueue's depth
- * parameter where the value can range from MSGTQL to CPR_MAX_MSG_Q_DEPTH.
- */
-typedef struct cpr_msg_queue_s
-{
-    struct cpr_msg_queue_s *next;
-    const char *name;
-    pthread_t thread;
-    int32_t queueId;
-    uint16_t currentCount;
-    uint32_t totalCount;
-    uint32_t sendErrors;
-    uint32_t reTries;
-    uint32_t highAttempts;
-    uint32_t selfQErrors;
-    uint16_t extendedQDepth;
-    uint16_t maxExtendedQDepth;
-    pthread_mutex_t mutex;       /* lock for managing extended queue     */
-    cpr_msgq_node_t *head;       /* extended queue head (newest element) */
-    cpr_msgq_node_t *tail;       /* extended queue tail (oldest element) */
-} cpr_msg_queue_t;
-
-/**
- * @enum cpr_msgq_post_result_e
- * A enumeration used to report the result of posting a message to
- * a message queue
- */
-typedef enum
-{
-    CPR_MSGQ_POST_SUCCESS,
-    CPR_MSGQ_POST_FAILED,
-    CPR_MSGQ_POST_PENDING
-} cpr_msgq_post_result_e;
-
-
-/*
- * Head of list of message queues
- */
-static cpr_msg_queue_t *msgQueueList = NULL;
-
-/*
- * Mutex to manage message queue list
- */
-pthread_mutex_t msgQueueListMutex;
-
-/*
- * String to represent message queue name when it is not provided
- */
-static const char unnamed_string[] = "unnamed";
-
-
-/*
- * CPR_MAX_MSG_Q_DEPTH
- *
- * The maximum queue depth supported by the CPR layer.  This value
- * is arbitrary though the purpose is to limit the memory usage
- * by CPR and avoid (nearly) unbounded situations.
- *
- * Note: This value should be greater than MSGTQL which is currently
- *       defined as 31
- */
-#define CPR_MAX_MSG_Q_DEPTH 256
-
-/*
- * CPR_SND_TIMEOUT_WAIT_INTERVAL
- *
- * The interval of time to wait in milliseconds between attempts to
- * send a message to the message queue
- *
- * Note: 20 ms. to avoid less than a tick wake up since on most
- *       OSes 10ms is one 1 tick
- *       this should really be OS_TICK_MS * 2 or OS_TICK_MS + X
- */
-#define CPR_SND_TIMEOUT_WAIT_INTERVAL 20
-
-/*
- * CPR_ATTEMPTS_TO_SEND
- *
- * The number of attempts made to send a message when the message
- * would otherwise be blocked.  Note in this condition the thread
- * will sleep the timeout interval to allow the msg queue to be
- * drained.
- *
- * Note: 25 attempts for upto .5 seconds at the interval of
- *       CPR_SND_TIMEOUT_WAIT_INTERVAL worst case.
- */
-#define CPR_ATTEMPTS_TO_SEND 25
-
-/*
- * Also, important to note that the total timeout interval must be
- * greater than the SIP's select call timeout value which is 25msec.
- * This is necessary to cover the case where the SIP message queue
- * is full and the select timeout occurs.
- *
- * Total timeout interval = CPR_SND_TIMEOUT_WAIT_INTERVAL *
- *                          CPR_ATTEMPTS_TO_SEND;
- */
-
-
-/*
- * Prototype declarations
- */
-static cpr_msgq_post_result_e
-cprPostMessage(cpr_msg_queue_t *msgq, void *msg, void **ppUserData);
-static void
-cprPegSendMessageStats(cpr_msg_queue_t *msgq, uint16_t numAttempts);
-static cpr_msgq_post_result_e
-cprPostExtendedQMsg(cpr_msg_queue_t *msgq, void *msg, void **ppUserData);
-static void
-cprMoveMsgToQueue(cpr_msg_queue_t *msgq);
-
-/*
- * Functions
- */
-
-/**
- * Creates a message queue
- *
- * @brief The cprCreateMessageQueue function is called to allow the OS to
- * perform whatever work is needed to create a message queue.
-
- * If the name is present, CPR should assign this name to the message queue to assist in
- * debugging. The message queue depth is the second input parameter and is for
- * setting the desired queue depth. This parameter may not be supported by all OS.
- * Its primary intention is to set queue depth beyond the default queue depth
- * limitation.
- * On any OS where there is no limit on the message queue depth or
- * its queue depth is sufficiently large then this parameter is ignored on that
- * OS.
- *
- * @param[in] name  - name of the message queue (optional)
- * @param[in] depth - the message queue depth, optional field which should
- *                default if set to zero(0)
- *
- * @return Msg queue handle or NULL if init failed, errno should be provided
- *
- * @note the actual message queue depth will be bounded by the
- *       standard system message queue depth and CPR_MAX_MSG_Q_DEPTH.
- *       If 'depth' is outside of the bounds, the value will be
- *       reset automatically.
- */
-cprMsgQueue_t
-cprCreateMessageQueue (const char *name, uint16_t depth)
-{
-    cpr_msg_queue_t *msgq;
-    struct msqid_ds buf;
-
-    msgq =(cpr_msg_queue_t *)cpr_calloc(1, sizeof(cpr_msg_queue_t));
-    if (msgq == NULL) {
-        CPR_ERROR("%s: Malloc failed: %s\n", __FUNCTION__,
-                  name ? name : unnamed_string);
-        errno = ENOMEM;
-        return NULL;
-    }
-
-    msgq->name = name ? name : unnamed_string;
-
-    /*
-     * Set creation flag so that OS will create the message queue
-     */
-    msgq->queueId = msgget(IPC_PRIVATE, (IPC_EXCL | IPC_CREAT | 0666));
-
-    if (msgq->queueId == -1) {
-        CPR_ERROR("%s: Creation failed: %s: %d\n", __FUNCTION__, name, errno);
-        if (errno == EEXIST) {
-
-        }
-
-        cpr_free(msgq);
-        return NULL;
-    }
-    CSFLogDebug(logTag, "create message q with id=%x\n", msgq->queueId);
-
-    /* flush the q before ?? */
-
-    /*
-     * Create mutex for extended (overflow) queue
-     */
-    if (pthread_mutex_init(&msgq->mutex, NULL) != 0) {
-        CPR_ERROR("%s: Failed to create msg queue (%s) mutex: %d\n",
-                  __FUNCTION__, name, errno);
-        (void) msgctl(msgq->queueId, IPC_RMID, &buf);
-        cpr_free(msgq);
-        return NULL;
-    }
-
-    /*
-     * Set the extended message queue depth (within bounds)
-     */
-    if (depth > CPR_MAX_MSG_Q_DEPTH) {
-        CPR_INFO("%s: Depth too large (%d) reset to %d\n", __FUNCTION__, depth,
-                 CPR_MAX_MSG_Q_DEPTH);
-        depth = CPR_MAX_MSG_Q_DEPTH;
-    }
-
-    if (depth < OS_MSGTQL) {
-        if (depth) {
-            CPR_INFO("%s: Depth too small (%d) reset to %d\n", __FUNCTION__, depth, OS_MSGTQL);
-        }
-        depth = OS_MSGTQL;
-    }
-    msgq->maxExtendedQDepth = depth - OS_MSGTQL;
-
-    /*
-     * Add message queue to list for statistics reporting
-     */
-    pthread_mutex_lock(&msgQueueListMutex);
-    msgq->next = msgQueueList;
-    msgQueueList = msgq;
-    pthread_mutex_unlock(&msgQueueListMutex);
-
-    return msgq;
-}
-
-
-/**
-  * cprDestroyMessageQueue
- * @brief Removes all messages from the queue and then destroy the message queue
- *
- * The cprDestroyMessageQueue function is called to destroy a message queue. The
- * function drains any messages from the queue and the frees the
- * message queue. Any messages on the queue are to be deleted, and not sent to the intended
- * recipient. It is the application's responsibility to ensure that no threads are
- * blocked on a message queue when it is destroyed.
- *
- * @param[in] msgQueue - message queue to destroy
- *
- * @return CPR_SUCCESS or CPR_FAILURE, errno should be provided in this case
- */
-cprRC_t
-cprDestroyMessageQueue (cprMsgQueue_t msgQueue)
-{
-    static const char fname[] = "cprDestroyMessageQueue";
-    cpr_msg_queue_t *msgq;
-    void *msg;
-    struct msqid_ds buf;
-    CSFLogDebug(logTag, "Destroy message Q called..\n");
-
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq == NULL) {
-        /* Bad application! */
-        CPR_ERROR("%s: Invalid input\n", fname);
-        errno = EINVAL;
-        return CPR_FAILURE;
-    }
-
-    /* Drain message queue */
-    msg = cprGetMessage(msgQueue, FALSE, NULL);
-    while (msg != NULL) {
-        cpr_free(msg);
-        msg = cprGetMessage(msgQueue, FALSE, NULL);
-    }
-
-    /* Remove message queue from list */
-    pthread_mutex_lock(&msgQueueListMutex);
-    if (msgq == msgQueueList) {
-        msgQueueList = msgq->next;
-    } else {
-        cpr_msg_queue_t *msgql = msgQueueList;
-
-        while ((msgql->next != NULL) && (msgql->next != msgq)) {
-            msgql = msgql->next;
-        }
-        if (msgql->next == msgq) {
-            msgql->next = msgq->next;
-        }
-    }
-    pthread_mutex_unlock(&msgQueueListMutex);
-
-    /* Remove message queue */
-    if (msgctl(msgq->queueId, IPC_RMID, &buf) == -1) {
-        CPR_ERROR("%s: Destruction failed: %s: %d\n", fname,
-                  msgq->name, errno);
-        return CPR_FAILURE;
-    }
-
-    /* Remove message queue mutex */
-    if (pthread_mutex_destroy(&msgq->mutex) != 0) {
-        CPR_ERROR("%s: Failed to destroy msg queue (%s) mutex: %d\n",
-                  fname, msgq->name, errno);
-    }
-
-    cpr_free(msgq);
-    return CPR_SUCCESS;
-}
-
-
-/**
-  * cprSetMessageQueueThread
- * @brief Associate a thread with the message queue
- *
- * This method is used by pSIPCC to associate a thread and a message queue.
- * @param[in] msgQueue  - msg queue to set
- * @param[in] thread    - CPR thread to associate with queue
- *
- * @return CPR_SUCCESS or CPR_FAILURE
- *
- * @note Nothing is done to prevent overwriting the thread ID
- *       when the value has already been set.
- */
-cprRC_t
-cprSetMessageQueueThread (cprMsgQueue_t msgQueue, cprThread_t thread)
-{
-    static const char fname[] = "cprSetMessageQueueThread";
-    cpr_msg_queue_t *msgq;
-
-    if ((!msgQueue) || (!thread)) {
-        CPR_ERROR("%s: Invalid input\n", fname);
-        return CPR_FAILURE;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq->thread != 0) {
-        CPR_ERROR("%s: over-writing previously msgq thread name for %s",
-                  fname, msgq->name);
-    }
-
-    msgq->thread = cprGetThreadId(thread);
-    return CPR_SUCCESS;
-}
-
-/**
-  * cprGetMessage
- * @brief Retrieve a message from a particular message queue
- *
- * The cprGetMessage function retrieves the first message from the message queue
- * specified and returns a void pointer to that message.
- *
- * @param[in]  msgQueue    - msg queue from which to retrieve the message. This
- * is the handle returned from cprCreateMessageQueue.
- * @param[in]  waitForever - boolean to either wait forever (TRUE) or not
- *                           wait at all (FALSE) if the msg queue is empty.
- * @param[out] ppUserData  - pointer to a pointer to user defined data. This
- * will be NULL if no user data was present.
- *
- * @return Retrieved message buffer or NULL if failure occurred or
- *         the waitForever flag was set to false and no messages were
- *         on the queue.
- *
- * @note   If ppUserData is defined, the value will be initialized to NULL
- */
-void *
-cprGetMessage (cprMsgQueue_t msgQueue, boolean waitForever, void **ppUserData)
-{
-    static const char fname[] = "cprGetMessage";
-    struct msgbuffer rcvBuffer = { 0 };
-    struct msgbuffer *rcvMsg = &rcvBuffer;
-    void *buffer;
-    int msgrcvflags;
-    cpr_msg_queue_t *msgq;
-
-    /* Initialize ppUserData */
-    if (ppUserData) {
-        *ppUserData = NULL;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-    if (msgq == NULL) {
-        /* Bad application! */
-        CPR_ERROR("%s: Invalid input\n", fname);
-        errno = EINVAL;
-        return NULL;
-    }
-
-    /*
-     * If waitForever is set, block on the message queue
-     * until a message is received.
-     */
-    if (waitForever) {
-        msgrcvflags = 0;
-    } else {
-        msgrcvflags = IPC_NOWAIT;
-    }
-
-    if (msgrcv(msgq->queueId, rcvMsg,
-        sizeof(struct msgbuffer) - offsetof(struct msgbuffer, msgPtr),
-        0, msgrcvflags) == -1) {
-    	if (!waitForever && errno == ENOMSG) {
-    		CPR_INFO("%s: no message on queue %s (non-blocking receive "
-                         " operation), returning\n", fname, msgq->name);
-    	} else {
-    		CPR_ERROR("%s: msgrcv for queue %s failed: %d\n",
-                              fname, msgq->name, errno);
-        }
-        return NULL;
-    }
-    CPR_INFO("%s: msgrcv success for queue %s \n",fname, msgq->name);
-
-    (void) pthread_mutex_lock(&msgq->mutex);
-    /* Update statistics */
-    msgq->currentCount--;
-    (void) pthread_mutex_unlock(&msgq->mutex);
-
-    /*
-     * Pull out the data
-     */
-    if (ppUserData) {
-        *ppUserData = rcvMsg->usrPtr;
-    }
-    buffer = rcvMsg->msgPtr;
-
-    /*
-     * If there are messages on the extended queue, attempt to
-     * push a message back onto the real system queue
-     */
-    if (msgq->extendedQDepth) {
-        cprMoveMsgToQueue(msgq);
-    }
-
-    return buffer;
-}
-
-
-/**
-  * cprSendMessage
- * @brief Place a message on a particular queue.  Note that caller may
- * block (see comments below)
- *
- * @param[in] msgQueue   - msg queue on which to place the message
- * @param[in] msg        - pointer to the msg to place on the queue
- * @param[in] ppUserData - pointer to a pointer to user defined data
- *
- * @return CPR_SUCCESS or CPR_FAILURE, errno should be provided
- *
- * @note 1. Messages queues are set to be non-blocking, those cases
- *       where the system call fails with a would-block error code
- *       (EAGAIN) the function will attempt other mechanisms described
- *       below.
- * @note 2. If enabled with an extended message queue, either via a
- *       call to cprCreateMessageQueue with depth value or a call to
- *       cprSetExtendMessageQueueDepth() (when unit testing), the message
- *       will be added to the extended message queue and the call will
- *       return successfully.  When room becomes available on the
- *       system's message queue, those messages will be added.
- * @note 3. If the message queue becomes full and no space is availabe
- *       on the extended message queue, then the function will attempt
- *       to resend the message up to CPR_ATTEMPTS_TO_SEND and the
- *       calling thread will *BLOCK* CPR_SND_TIMEOUT_WAIT_INTERVAL
- *       milliseconds after each failed attempt.  If unsuccessful
- *       after all attempts then EGAIN error code is returned.
- * @note 4. This applies to all CPR threads, including the timer thread.
- *       So it is possible that the timer thread would be forced to
- *       sleep which would have the effect of delaying all active
- *       timers.  The work to fix this rare situation is not considered
- *       worth the effort to fix....so just leaving as is.
- */
-cprRC_t
-cprSendMessage (cprMsgQueue_t msgQueue, void *msg, void **ppUserData)
-{
-    static const char fname[] = "cprSendMessage";
-    static const char error_str[] = "%s: Msg not sent to %s queue: %s\n";
-    cpr_msgq_post_result_e rc;
-    cpr_msg_queue_t *msgq;
-    int16_t attemptsToSend = CPR_ATTEMPTS_TO_SEND;
-    uint16_t numAttempts   = 0;
-
-    /* Bad application? */
-    if (msgQueue == NULL) {
-        CPR_ERROR(error_str, fname, "undefined", "invalid input");
-        errno = EINVAL;
-        return CPR_FAILURE;
-    }
-
-    msgq = (cpr_msg_queue_t *) msgQueue;
-
-    /*
-     * Attempt to send message
-     */
-    do {
-        (void) pthread_mutex_lock(&msgq->mutex);
-
-        /*
-         * If in a queue overflow condition, post message to the
-         * extended queue; otherwise, post to normal message queue
-         */
-        if (msgq->extendedQDepth) {
-            /*
-             * Check if extended queue is full, if not then
-             * attempt to add the message.
-             */
-            if (msgq->extendedQDepth < msgq->maxExtendedQDepth) {
-                rc = cprPostExtendedQMsg(msgq, msg, ppUserData);
-                // do under lock to avoid races
-                if (rc == CPR_MSGQ_POST_SUCCESS) {
-                    cprPegSendMessageStats(msgq, numAttempts);
-                } else {