Merge inbound to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 30 May 2014 16:23:21 -0400
changeset 185948 323156681cef300e59308d16e57a8003ab82c5db
parent 185947 6f9eb2bb1103e2b87152e6f3f996bd658f7000c6 (current diff)
parent 185870 3ac2205532ed66999c8fa7b25d42f8ccb7908617 (diff)
child 185949 c57a20e0c95c81dabccc7fe045121311344fd7be
child 186002 85f6afe5cdde83d93a40849c3a1684447814c73f
child 186008 7e3dbe00b1e7f23250fc109717ff203a899780f1
child 186072 82559671ba31e8132c6e3c8efc013c10b512c3ec
push id44197
push userryanvm@gmail.com
push dateFri, 30 May 2014 20:24:52 +0000
treeherdermozilla-inbound@c57a20e0c95c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone32.0a1
first release with
nightly linux32
323156681cef / 32.0a1 / 20140531030204 / files
nightly linux64
323156681cef / 32.0a1 / 20140531030204 / files
nightly mac
323156681cef / 32.0a1 / 20140531030204 / files
nightly win32
323156681cef / 32.0a1 / 20140531030204 / files
nightly win64
323156681cef / 32.0a1 / 20140531030204 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to m-c.
--- a/b2g/installer/Makefile.in
+++ b/b2g/installer/Makefile.in
@@ -69,16 +69,23 @@ endif
 
 ifdef MOZ_REPLACE_MALLOC
 DEFINES += -DMOZ_REPLACE_MALLOC
 endif
 ifdef MOZ_JEMALLOC3
 DEFINES += -DMOZ_JEMALLOC3
 endif
 
+ifdef MOZ_WIDGET_GTK
+DEFINES += -DMOZ_GTK=1
+ifdef MOZ_ENABLE_GTK3
+DEFINES += -DMOZ_GTK3=1
+endif
+endif
+
 ifdef MOZ_PKG_MANIFEST_P
 $(MOZ_PKG_MANIFEST): $(MOZ_PKG_MANIFEST_P) FORCE
 	$(call py_action,preprocessor,$(DEFINES) $(ACDEFINES) $< -o $@)
 ifdef MOZ_CHROME_MULTILOCALE
 	printf '\n[multilocale]\n' >> $@
 	for LOCALE in $(MOZ_CHROME_MULTILOCALE) ;\
 	do \
 	  printf '$(BINPATH)/chrome/'"$$LOCALE"'$(JAREXT)\n' >> $@; \
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -91,16 +91,20 @@
 #ifdef ANDROID
 @BINPATH@/AndroidManifest.xml
 @BINPATH@/resources.arsc
 @BINPATH@/classes.dex
 @BINPATH@/res/drawable
 @BINPATH@/res/drawable-hdpi
 @BINPATH@/res/layout
 #endif
+#ifdef MOZ_GTK3
+@BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
+@BINPATH@/@DLL_PREFIX@mozgtk2@DLL_SUFFIX@
+#endif
 
 [browser]
 ; [Base Browser Files]
 #ifndef XP_UNIX
 @BINPATH@/@MOZ_APP_NAME@.exe
 #else
 @BINPATH@/@MOZ_APP_NAME@-bin
 @BINPATH@/@MOZ_APP_NAME@
@@ -212,17 +216,17 @@
 @BINPATH@/components/downloads.xpt
 @BINPATH@/components/editor.xpt
 @BINPATH@/components/embed_base.xpt
 @BINPATH@/components/extensions.xpt
 @BINPATH@/components/exthandler.xpt
 @BINPATH@/components/exthelper.xpt
 @BINPATH@/components/fastfind.xpt
 @BINPATH@/components/feeds.xpt
-#ifdef MOZ_GTK2
+#ifdef MOZ_GTK
 @BINPATH@/components/filepicker.xpt
 #endif
 @BINPATH@/components/find.xpt
 @BINPATH@/components/fuel.xpt
 @BINPATH@/components/gfx.xpt
 @BINPATH@/components/hal.xpt
 @BINPATH@/components/html5.xpt
 @BINPATH@/components/htmlparser.xpt
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -33,16 +33,19 @@ DEFINES += -DMOZ_DEBUG=1
 endif
 
 ifdef MOZ_ENABLE_GNOME_COMPONENT
 DEFINES += -DMOZ_ENABLE_GNOME_COMPONENT=1
 endif
 
 ifdef MOZ_WIDGET_GTK
 DEFINES += -DMOZ_GTK=1
+ifdef MOZ_ENABLE_GTK3
+DEFINES += -DMOZ_GTK3=1
+endif
 endif
 
 ifdef MOZ_NATIVE_NSPR
 DEFINES += -DMOZ_NATIVE_NSPR=1
 endif
 
 ifdef MOZ_NATIVE_NSS
 DEFINES += -DMOZ_NATIVE_NSS=1
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -113,16 +113,20 @@
 #endif
 #endif
 #endif
 #ifdef MOZ_REPLACE_MALLOC
 #ifndef MOZ_JEMALLOC3
 @BINPATH@/@DLL_PREFIX@replace_jemalloc@DLL_SUFFIX@
 #endif
 #endif
+#ifdef MOZ_GTK3
+@BINPATH@/@DLL_PREFIX@mozgtk@DLL_SUFFIX@
+@BINPATH@/@DLL_PREFIX@mozgtk2@DLL_SUFFIX@
+#endif
 
 [browser]
 ; [Base Browser Files]
 #ifndef XP_UNIX
 @BINPATH@/@MOZ_APP_NAME@.exe
 #else
 @BINPATH@/@MOZ_APP_NAME@-bin
 @BINPATH@/@MOZ_APP_NAME@
--- a/configure.in
+++ b/configure.in
@@ -4372,17 +4372,17 @@ fi
 if test "$MOZ_INSTRUMENT_EVENT_LOOP"; then
    AC_DEFINE(MOZ_INSTRUMENT_EVENT_LOOP)
 fi
 
 if test "$COMPILE_ENVIRONMENT"; then
   if test "$MOZ_ENABLE_GTK3"; then
     PKG_CHECK_MODULES(MOZ_GTK3, gtk+-3.0 >= $GTK3_VERSION gtk+-unix-print-3.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
   fi
-  if test "$MOZ_ENABLE_GTK2"; then
+  if test "$MOZ_ENABLE_GTK"; then
     if test "$MOZ_X11"; then
       GDK_PACKAGES=gdk-x11-2.0
     fi
 
     PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
   fi
 
 fi # COMPILE_ENVIRONMENT
@@ -8857,17 +8857,16 @@ AC_SUBST(OBJ_SUFFIX)
 AC_SUBST(BIN_SUFFIX)
 AC_SUBST(ASM_SUFFIX)
 AC_SUBST(IMPORT_LIB_SUFFIX)
 AC_SUBST(USE_N32)
 AC_SUBST(CC_VERSION)
 AC_SUBST(CXX_VERSION)
 AC_SUBST(MSMANIFEST_TOOL)
 AC_SUBST(NS_ENABLE_TSF)
-AC_SUBST(MOZ_NSS_PATCH)
 AC_SUBST(MOZ_APP_COMPONENT_LIBS)
 AC_SUBST(MOZ_APP_EXTRA_LIBS)
 
 AC_SUBST(MOZ_WAVE)
 AC_SUBST(MOZ_VORBIS)
 AC_SUBST(MOZ_TREMOR)
 AC_SUBST(MOZ_OPUS)
 AC_SUBST(MOZ_WEBM)
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -1868,42 +1868,42 @@ PeerConnectionWrapper.prototype = {
               // ssrc is a 32 bit number returned as a string by spec
               ok(res.ssrc.length > 0, "Ssrc has length");
               ok(res.ssrc.length < 11, "Ssrc not lengthy");
               ok(!/[^0-9]/.test(res.ssrc), "Ssrc numeric");
               ok(parseInt(res.ssrc) < Math.pow(2,32), "Ssrc within limits");
 
               if (res.type == "outboundrtp") {
                 ok(res.packetsSent !== undefined, "Rtp packetsSent");
-                // minimum fragment is 8 (from RFC 791)
-                ok(res.bytesSent >= res.packetsSent * 8, "Rtp bytesSent");
+                // We assume minimum payload to be 1 byte (guess from RFC 3550)
+                ok(res.bytesSent >= res.packetsSent, "Rtp bytesSent");
               } else {
                 ok(res.packetsReceived !== undefined, "Rtp packetsReceived");
-                ok(res.bytesReceived >= res.packetsReceived * 8, "Rtp bytesReceived");
+                ok(res.bytesReceived >= res.packetsReceived, "Rtp bytesReceived");
               }
               if (res.remoteId) {
                 var rem = stats[res.remoteId];
                 ok(rem.isRemote, "Remote is rtcp");
                 ok(rem.remoteId == res.id, "Remote backlink match");
                 if(res.type == "outboundrtp") {
                   ok(rem.type == "inboundrtp", "Rtcp is inbound");
                   ok(rem.packetsReceived !== undefined, "Rtcp packetsReceived");
                   ok(rem.packetsReceived <= res.packetsSent, "No more than sent");
                   ok(rem.packetsLost !== undefined, "Rtcp packetsLost");
-                  ok(rem.bytesReceived >= rem.packetsReceived * 8, "Rtcp bytesReceived");
+                  ok(rem.bytesReceived >= rem.packetsReceived, "Rtcp bytesReceived");
                   ok(rem.bytesReceived <= res.bytesSent, "No more than sent bytes");
                   ok(rem.jitter !== undefined, "Rtcp jitter");
                   ok(rem.mozRtt !== undefined, "Rtcp rtt");
                   ok(rem.mozRtt >= 0, "Rtcp rtt " + rem.mozRtt + " >= 0");
                   ok(rem.mozRtt < 60000, "Rtcp rtt " + rem.mozRtt + " < 1 min");
                 } else {
                   ok(rem.type == "outboundrtp", "Rtcp is outbound");
                   ok(rem.packetsSent !== undefined, "Rtcp packetsSent");
                   // We may have received more than outdated Rtcp packetsSent
-                  ok(rem.bytesSent >= rem.packetsSent * 8, "Rtcp bytesSent");
+                  ok(rem.bytesSent >= rem.packetsSent, "Rtcp bytesSent");
                 }
                 ok(rem.ssrc == res.ssrc, "Remote ssrc match");
               } else {
                 info("No rtcp info received yet");
               }
             }
             break;
           }
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -245,16 +245,21 @@ nsNPAPIPlugin::PluginCrashed(const nsASt
 {
   nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
   host->PluginCrashed(this, pluginDumpID, browserDumpID);
 }
 
 bool
 nsNPAPIPlugin::RunPluginOOP(const nsPluginTag *aPluginTag)
 {
+#if (MOZ_WIDGET_GTK == 3)
+  // We force OOP on Linux/GTK3 because some plugins use GTK2 and both GTK
+  // libraries can't be loaded in the same process.
+  return true;
+#else
   if (PR_GetEnv("MOZ_DISABLE_OOP_PLUGINS")) {
     return false;
   }
 
   if (!aPluginTag) {
     return false;
   }
 
@@ -371,16 +376,17 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
 #ifdef ACCESSIBILITY
     useA11yPref ? Preferences::GetBool("dom.ipc.plugins.enabled.a11y", false) :
 #endif
     Preferences::GetBool("dom.ipc.plugins.enabled", false);
 #endif
   }
 
   return oopPluginsEnabled;
+#endif
 }
 
 inline PluginLibrary*
 GetNewPluginLibrary(nsPluginTag *aPluginTag)
 {
   if (!aPluginTag) {
     return nullptr;
   }
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -714,20 +714,20 @@ void nsPluginHost::OnPluginInstanceDestr
   // going from one page to another, so state is retained without an instance
   // for only a very short period of time. In order to allow this to work
   // we don't unload plugins immediately by default. This is supported
   // via a hidden user pref though.
   //
   // Another reason not to unload immediately is that loading is expensive,
   // and it is better to leave popular plugins loaded.
   //
-  // Our default behavior is to try to unload a plugin three minutes after
-  // its last instance is destroyed. This seems like a reasonable compromise
-  // that allows us to reclaim memory while allowing short state retention
-  // and avoid perf hits for loading popular plugins.
+  // Our default behavior is to try to unload a plugin after a pref-controlled
+  // delay once its last instance is destroyed. This seems like a reasonable
+  // compromise that allows us to reclaim memory while allowing short state
+  // retention and avoid perf hits for loading popular plugins.
   if (!hasInstance) {
     if (UnloadPluginsASAP()) {
       aPluginTag->TryUnloadPlugin(false);
     } else {
       if (aPluginTag->mUnloadTimer) {
         aPluginTag->mUnloadTimer->Cancel();
       } else {
         aPluginTag->mUnloadTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -62,19 +62,18 @@ static NS_DEFINE_CID(kAppShellCID, NS_AP
 #include <winuser.h>
 #endif
 
 #ifdef XP_MACOSX
 #include <Carbon/Carbon.h>
 #include "nsPluginUtilsOSX.h"
 #endif
 
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
 #include <gdk/gdk.h>
-#include <gdk/gdkx.h>
 #include <gtk/gtk.h>
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "ANPBase.h"
 #include "AndroidBridge.h"
 #include "nsWindow.h"
 
--- a/dom/plugins/base/nsPluginNativeWindowGtk.cpp
+++ b/dom/plugins/base/nsPluginNativeWindowGtk.cpp
@@ -12,17 +12,21 @@
 #include "nsDebug.h"
 #include "nsPluginNativeWindow.h"
 #include "nsNPAPIPlugin.h"
 #include "npapi.h"
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
 #include <gdk/gdk.h>
 
+#if (GTK_MAJOR_VERSION == 3)
+#include <gtk/gtkx.h>
+#else
 #include "gtk2xtbin.h"
+#endif
 #include "mozilla/X11Util.h"
 
 class nsPluginNativeWindowGtk : public nsPluginNativeWindow {
 public: 
   nsPluginNativeWindowGtk();
   virtual ~nsPluginNativeWindowGtk();
 
   virtual nsresult CallSetWindow(nsRefPtr<nsNPAPIPluginInstance> &aPluginInstance);
--- a/dom/plugins/ipc/Makefile.in
+++ b/dom/plugins/ipc/Makefile.in
@@ -1,10 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 include $(topsrcdir)/config/rules.mk
 
+ifneq ($(MOZ_WIDGET_TOOLKIT),gtk3)
+CXXFLAGS += $(TK_CFLAGS)
+else
+# Force build against gtk+2 for struct offsets and such.
+CXXFLAGS += $(MOZ_GTK2_CFLAGS)
+endif
+
 CXXFLAGS += \
-  $(TK_CFLAGS) \
   $(MOZ_CAIRO_CFLAGS) \
   $(NULL)
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -37,24 +37,19 @@ using mozilla::ipc::ProcessChild;
 using namespace mozilla::plugins;
 using namespace mozilla::layers;
 using namespace mozilla::gfx;
 using namespace std;
 
 #ifdef MOZ_WIDGET_GTK
 
 #include <gtk/gtk.h>
-#if (MOZ_WIDGET_GTK == 3)
-#include <gtk/gtkx.h>
-#endif
 #include <gdk/gdkx.h>
 #include <gdk/gdk.h>
-#if (MOZ_WIDGET_GTK == 2)
 #include "gtk2xtbin.h"
-#endif
 
 #elif defined(MOZ_WIDGET_QT)
 #undef KeyPress
 #undef KeyRelease
 #elif defined(OS_WIN)
 #ifndef WM_MOUSEHWHEEL
 #define WM_MOUSEHWHEEL     0x020E
 #endif
@@ -103,17 +98,17 @@ PluginInstanceChild::PluginInstanceChild
     , mContentsScaleFactor(1.0)
 #endif
     , mDrawingModel(kDefaultDrawingModel)
     , mCurrentAsyncSurface(0)
     , mAsyncInvalidateMutex("PluginInstanceChild::mAsyncInvalidateMutex")
     , mAsyncInvalidateTask(0)
     , mCachedWindowActor(nullptr)
     , mCachedElementActor(nullptr)
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
     , mXEmbed(false)
 #endif // MOZ_WIDGET_GTK
 #if defined(OS_WIN)
     , mPluginWindowHWND(0)
     , mPluginWndProc(0)
     , mPluginParentHWND(0)
     , mCachedWinlessPluginHWND(0)
     , mWinlessPopupSurrogateHWND(0)
@@ -147,17 +142,17 @@ PluginInstanceChild::PluginInstanceChild
 {
     memset(&mWindow, 0, sizeof(mWindow));
     mWindow.type = NPWindowTypeWindow;
     mData.ndata = (void*) this;
     mData.pdata = nullptr;
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     mWindow.ws_info = &mWsInfo;
     memset(&mWsInfo, 0, sizeof(mWsInfo));
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
     mWsInfo.display = nullptr;
     mXtClient.top_widget = nullptr;
 #else
     mWsInfo.display = DefaultXDisplay();
 #endif
 #endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
 #if defined(OS_WIN)
     memset(&mAlphaExtract, 0, sizeof(mAlphaExtract));
@@ -477,17 +472,17 @@ PluginInstanceChild::NPN_SetValue(NPPVar
     case NPPVpluginWindowBool: {
         NPError rv;
         bool windowed = (NPBool) (intptr_t) aValue;
 
         if (!CallNPN_SetValue_NPPVpluginWindow(windowed, &rv))
             return NPERR_GENERIC_ERROR;
 
         NPWindowType newWindowType = windowed ? NPWindowTypeWindow : NPWindowTypeDrawable;
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
         if (mWindow.type != newWindowType && mWsInfo.display) {
            // plugin type has been changed but we already have a valid display
            // so update it for the recent plugin mode
            if (mXEmbed || !windowed) {
                // Use default GTK display for XEmbed and windowless plugins
                mWsInfo.display = DefaultXDisplay();
            }
            else {
@@ -1021,17 +1016,17 @@ PluginInstanceChild::RecvContentsScaleFa
 bool PluginInstanceChild::CreateWindow(const NPRemoteWindow& aWindow)
 { 
     PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)",
                       FULLFUNCTION,
                       aWindow.window,
                       aWindow.x, aWindow.y,
                       aWindow.width, aWindow.height));
 
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
     if (mXEmbed) {
         mWindow.window = reinterpret_cast<void*>(aWindow.window);
     }
     else {
         Window browserSocket = (Window)(aWindow.window);
         xt_client_init(&mXtClient, mWsInfo.visual, mWsInfo.colormap, mWsInfo.depth);
         xt_client_create(&mXtClient, browserSocket, mWindow.width, mWindow.height); 
         mWindow.window = (void *)XtWindow(mXtClient.child_widget);
@@ -1050,17 +1045,17 @@ void PluginInstanceChild::DeleteWindow()
                     FULLFUNCTION,
                     mWindow.window,
                     mWindow.x, mWindow.y,
                     mWindow.width, mWindow.height));
 
   if (!mWindow.window)
       return;
 
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
   if (mXtClient.top_widget) {     
       xt_client_unrealize(&mXtClient);
       xt_client_destroy(&mXtClient); 
       mXtClient.top_widget = nullptr;
   }
 #endif
 
   // We don't have to keep the plug-in window ID any longer.
@@ -1098,17 +1093,17 @@ PluginInstanceChild::AnswerNPP_SetWindow
     FindVisualAndDepth(mWsInfo.display, aWindow.visualID,
                        &mWsInfo.visual, &depth);
     mWsInfo.depth = depth;
 
     if (!mWindow.window && mWindow.type == NPWindowTypeWindow) {
         CreateWindow(aWindow);
     }
 
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
     if (mXEmbed && gtk_check_version(2,18,7) != nullptr) { // older
         if (aWindow.type == NPWindowTypeWindow) {
             GdkWindow* socket_window = gdk_window_lookup(static_cast<GdkNativeWindow>(aWindow.window));
             if (socket_window) {
                 // A GdkWindow for the socket already exists.  Need to
                 // workaround https://bugzilla.gnome.org/show_bug.cgi?id=607061
                 // See wrap_gtk_plug_embedded in PluginModuleChild.cpp.
                 g_object_set_data(G_OBJECT(socket_window),
@@ -1231,17 +1226,17 @@ PluginInstanceChild::AnswerNPP_SetWindow
 #endif
 
     return true;
 }
 
 bool
 PluginInstanceChild::Initialize()
 {
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
     NPError rv;
 
     if (mWsInfo.display) {
         // Already initialized
         return false;
     }
 
     // Request for windowless plugins is set in newp(), before this call.
@@ -3985,17 +3980,17 @@ PluginInstanceChild::AnswerNPP_Destroy(N
 
     mPendingAsyncCalls.Clear();
     
     if (mAsyncBitmaps.Count()) {
         NS_ERROR("Not all AsyncBitmaps were finalized by a plugin!");
         mAsyncBitmaps.Enumerate(DeleteSurface, this);
     }
 
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
     if (mWindow.type == NPWindowTypeWindow && !mXEmbed) {
       xt_client_xloop_destroy();
     }
 #endif
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     DeleteWindow();
 #endif
 
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -28,17 +28,17 @@
 #include "ChildAsyncCall.h"
 #include "ChildTimer.h"
 #include "nsRect.h"
 #include "nsTHashtable.h"
 #include "mozilla/PaintTracker.h"
 
 #include <map>
 
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
 #include "gtk2xtbin.h"
 #endif
 
 class gfxASurface;
 
 namespace mozilla {
 
 namespace layers {
@@ -380,17 +380,17 @@ private:
     CancelableTask *mAsyncInvalidateTask;
 
     // Cached scriptable actors to avoid IPC churn
     PluginScriptableObjectChild* mCachedWindowActor;
     PluginScriptableObjectChild* mCachedElementActor;
 
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     NPSetWindowCallbackStruct mWsInfo;
-#if (MOZ_WIDGET_GTK == 2)
+#ifdef MOZ_WIDGET_GTK
     bool mXEmbed;
     XtClient mXtClient;
 #endif
 #elif defined(OS_WIN)
     HWND mPluginWindowHWND;
     WNDPROC mPluginWndProc;
     HWND mPluginParentHWND;
     int mNestedEventLevelDepth;
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -15,19 +15,16 @@
 
 /* This must occur *after* plugins/PluginModuleChild.h to avoid typedefs conflicts. */
 #include "mozilla/ArrayUtils.h"
 
 #include "mozilla/ipc/MessageChannel.h"
 
 #ifdef MOZ_WIDGET_GTK
 #include <gtk/gtk.h>
-#if (MOZ_WIDGET_GTK == 3)
-#include <gtk/gtkx.h>
-#endif
 #endif
 
 #include "nsIFile.h"
 
 #include "pratom.h"
 #include "nsDebug.h"
 #include "nsCOMPtr.h"
 #include "nsPluginsDir.h"
@@ -1091,17 +1088,17 @@ NPError
         case NPNVSupportsWindowless: { // Intentional fall-through
             NPError result;
             bool value;
             PluginModuleChild::current()->
                 CallNPN_GetValue_WithBoolReturn(aVariable, &result, &value);
             *(NPBool*)aValue = value ? true : false;
             return result;
         }
-#if (MOZ_WIDGET_GTK == 2)
+#if defined(MOZ_WIDGET_GTK)
         case NPNVxDisplay: {
             if (aNPP) {
                 return InstCast(aNPP)->NPN_GetValue(aVariable, aValue);
             } 
             else {
                 *(void **)aValue = xt_client_get_display();
             }          
             return NPERR_NO_ERROR;
--- a/dom/plugins/ipc/PluginProcessParent.cpp
+++ b/dom/plugins/ipc/PluginProcessParent.cpp
@@ -6,16 +6,17 @@
 
 #include "mozilla/plugins/PluginProcessParent.h"
 
 #include "base/string_util.h"
 #include "base/process_util.h"
 
 #include "mozilla/ipc/BrowserProcessSubThread.h"
 #include "mozilla/plugins/PluginMessageUtils.h"
+#include "mozilla/Telemetry.h"
 
 using std::vector;
 using std::string;
 
 using mozilla::ipc::BrowserProcessSubThread;
 using mozilla::ipc::GeckoChildProcessHost;
 using mozilla::plugins::PluginProcessParent;
 using base::ProcessArchitecture;
@@ -70,16 +71,17 @@ PluginProcessParent::Launch(int32_t time
         }
         else {
             return false;
         }
     }
 
     vector<string> args;
     args.push_back(MungePluginDsoPath(mPluginFilePath));
+    Telemetry::AutoTimer<Telemetry::PLUGIN_STARTUP_MS> timer;
     return SyncLaunch(args, timeoutMs, selectedArchitecture);
 }
 
 void
 PluginProcessParent::Delete()
 {
   MessageLoop* currentLoop = MessageLoop::current();
   MessageLoop* ioLoop = XRE_GetIOMessageLoop();
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -525,23 +525,23 @@ AsyncPanZoomController::AsyncPanZoomCont
                                                GestureBehavior aGestures)
   :  mLayersId(aLayersId),
      mPaintThrottler(GetFrameTime()),
      mGeckoContentController(aGeckoContentController),
      mRefPtrMonitor("RefPtrMonitor"),
      mSharingFrameMetricsAcrossProcesses(false),
      mMonitor("AsyncPanZoomController"),
      mTouchActionPropertyEnabled(gfxPrefs::TouchActionEnabled()),
+     mState(NOTHING),
      mContentResponseTimeoutTask(nullptr),
      mX(MOZ_THIS_IN_INITIALIZER_LIST()),
      mY(MOZ_THIS_IN_INITIALIZER_LIST()),
      mPanDirRestricted(false),
      mZoomConstraints(false, false, MIN_ZOOM, MAX_ZOOM),
      mLastSampleTime(GetFrameTime()),
-     mState(NOTHING),
      mLastAsyncScrollTime(GetFrameTime()),
      mLastAsyncScrollOffset(0, 0),
      mCurrentAsyncScrollOffset(0, 0),
      mAsyncScrollTimeoutTask(nullptr),
      mHandlingTouchQueue(false),
      mTreeManager(aTreeManager),
      mScrollParentId(FrameMetrics::NULL_SCROLL_ID),
      mAPZCId(sAsyncPanZoomControllerCount++),
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -314,16 +314,39 @@ public:
   bool HasScrollgrab() const { return mFrameMetrics.mHasScrollgrab; }
 
   /**
    * Returns whether this APZC has room to be panned (in any direction).
    */
   bool IsPannable() const;
 
 protected:
+  enum PanZoomState {
+    NOTHING,                  /* no touch-start events received */
+    FLING,                    /* all touches removed, but we're still scrolling page */
+    TOUCHING,                 /* one touch-start event received */
+
+    PANNING,                  /* panning the frame */
+    PANNING_LOCKED_X,         /* touch-start followed by move (i.e. panning with axis lock) X axis */
+    PANNING_LOCKED_Y,         /* as above for Y axis */
+
+    CROSS_SLIDING_X,          /* Panning disabled while user does a horizontal gesture
+                                 on a vertically-scrollable view. This used for the
+                                 Windows Metro "cross-slide" gesture. */
+    CROSS_SLIDING_Y,          /* as above for Y axis */
+
+    PINCHING,                 /* nth touch-start, where n > 1. this mode allows pan and zoom */
+    ANIMATING_ZOOM,           /* animated zoom to a new rect */
+    WAITING_CONTENT_RESPONSE, /* a state halfway between NOTHING and TOUCHING - the user has
+                                 put a finger down, but we don't yet know if a touch listener has
+                                 prevented the default actions yet and the allowed touch behavior
+                                 was not set yet. we still need to abort animations. */
+    SNAP_BACK,                /* snap-back animation to relieve overscroll */
+  };
+
   // Protected destructor, to discourage deletion outside of Release():
   ~AsyncPanZoomController();
 
   /**
    * Helper method for touches beginning. Sets everything up for panning and any
    * multitouch gestures.
    */
   nsEventStatus OnTouchStart(const MultiTouchInput& aEvent);
@@ -514,39 +537,16 @@ protected:
    * Timeout function for mozbrowserasyncscroll event. Because we throttle
    * mozbrowserasyncscroll events in some conditions, this function ensures
    * that the last mozbrowserasyncscroll event will be fired after a period of
    * time.
    */
   void FireAsyncScrollOnTimeout();
 
 private:
-  enum PanZoomState {
-    NOTHING,                  /* no touch-start events received */
-    FLING,                    /* all touches removed, but we're still scrolling page */
-    TOUCHING,                 /* one touch-start event received */
-
-    PANNING,                  /* panning the frame */
-    PANNING_LOCKED_X,         /* touch-start followed by move (i.e. panning with axis lock) X axis */
-    PANNING_LOCKED_Y,         /* as above for Y axis */
-
-    CROSS_SLIDING_X,          /* Panning disabled while user does a horizontal gesture
-                                 on a vertically-scrollable view. This used for the
-                                 Windows Metro "cross-slide" gesture. */
-    CROSS_SLIDING_Y,          /* as above for Y axis */
-
-    PINCHING,                 /* nth touch-start, where n > 1. this mode allows pan and zoom */
-    ANIMATING_ZOOM,           /* animated zoom to a new rect */
-    WAITING_CONTENT_RESPONSE, /* a state halfway between NOTHING and TOUCHING - the user has
-                                 put a finger down, but we don't yet know if a touch listener has
-                                 prevented the default actions yet and the allowed touch behavior
-                                 was not set yet. we still need to abort animations. */
-    SNAP_BACK,                /* snap-back animation to relieve overscroll */
-  };
-
   // State related to a single touch block. Does not persist across touch blocks.
   struct TouchBlockState {
 
     TouchBlockState()
       :  mAllowedTouchBehaviorSet(false),
          mPreventDefault(false),
          mPreventDefaultSet(false),
          mSingleTapOccurred(false)
@@ -685,16 +685,20 @@ protected:
   mutable ReentrantMonitor mMonitor;
 
   // Specifies whether we should use touch-action css property. Initialized from
   // the preferences. This property (in comparison with the global one) simplifies
   // testing apzc with (and without) touch-action property enabled concurrently
   // (e.g. with the gtest framework).
   bool mTouchActionPropertyEnabled;
 
+  // Stores the state of panning and zooming this frame. This is protected by
+  // |mMonitor|; that is, it should be held whenever this is updated.
+  PanZoomState mState;
+
 private:
   // Metrics of the container layer corresponding to this APZC. This is
   // stored here so that it is accessible from the UI/controller thread.
   // These are the metrics at last content paint, the most recent
   // values we were notified of in NotifyLayersUpdate(). Since it represents
   // the Gecko state, it should be used as a basis for untransformation when
   // sending messages back to Gecko.
   FrameMetrics mLastContentPaintMetrics;
@@ -727,20 +731,16 @@ private:
   // The last time the compositor has sampled the content transform for this
   // frame.
   TimeStamp mLastSampleTime;
 
   // Stores the previous focus point if there is a pinch gesture happening. Used
   // to allow panning by moving multiple fingers (thus moving the focus point).
   ParentLayerPoint mLastZoomFocus;
 
-  // Stores the state of panning and zooming this frame. This is protected by
-  // |mMonitor|; that is, it should be held whenever this is updated.
-  PanZoomState mState;
-
   // The last time and offset we fire the mozbrowserasyncscroll event when
   // compositor has sampled the content transform for this frame.
   TimeStamp mLastAsyncScrollTime;
   CSSPoint mLastAsyncScrollOffset;
 
   // The current offset drawn on the screen, it may not be sent since we have
   // throttling policy for mozbrowserasyncscroll event.
   CSSPoint mCurrentAsyncScrollOffset;
--- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp
+++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp
@@ -134,16 +134,21 @@ public:
     ReentrantMonitorAutoEnter lock(mMonitor);
     mFrameMetrics = metrics;
   }
 
   FrameMetrics GetFrameMetrics() {
     ReentrantMonitorAutoEnter lock(mMonitor);
     return mFrameMetrics;
   }
+
+  void AssertStateIsReset() {
+    ReentrantMonitorAutoEnter lock(mMonitor);
+    EXPECT_EQ(NOTHING, mState);
+  }
 };
 
 class TestAPZCTreeManager : public APZCTreeManager {
 public:
   // Expose these so test code can call it directly.
   void BuildOverscrollHandoffChain(AsyncPanZoomController* aApzc) {
     APZCTreeManager::BuildOverscrollHandoffChain(aApzc);
   }
@@ -836,16 +841,17 @@ TEST_F(AsyncPanZoomControllerTester, Sho
 
   // This verifies that the single tap notification is sent after the
   // touchdown is fully processed. The ordering here is important.
   mcc->CheckHasDelayedTask();
 
   EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
   mcc->RunDelayedTask();
 
+  apzc->AssertStateIsReset();
   apzc->Destroy();
 }
 
 TEST_F(AsyncPanZoomControllerTester, MediumPress) {
   nsRefPtr<MockContentControllerDelayed> mcc = new NiceMock<MockContentControllerDelayed>();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
     0, mcc, tm, AsyncPanZoomController::USE_GESTURE_DETECTOR);
@@ -860,16 +866,17 @@ TEST_F(AsyncPanZoomControllerTester, Med
 
   // This verifies that the single tap notification is sent after the
   // touchdown is fully processed. The ordering here is important.
   mcc->CheckHasDelayedTask();
 
   EXPECT_CALL(*mcc, HandleSingleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1);
   mcc->RunDelayedTask();
 
+  apzc->AssertStateIsReset();
   apzc->Destroy();
 }
 
 void
 DoLongPressTest(bool aShouldUseTouchAction, uint32_t aBehavior) {
   nsRefPtr<MockContentControllerDelayed> mcc = new MockContentControllerDelayed();
   nsRefPtr<TestAPZCTreeManager> tm = new TestAPZCTreeManager();
   nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(
@@ -929,16 +936,17 @@ DoLongPressTest(bool aShouldUseTouchActi
 
   // To get a LongTapUp event, we must kick APZC to flush its event queue. This
   // would normally happen if we had a (Tab|RenderFrame)(Parent|Child)
   // mechanism.
   check.Call("preHandleLongTapUp");
   apzc->ContentReceivedTouch(false);
   check.Call("postHandleLongTapUp");
 
+  apzc->AssertStateIsReset();
   apzc->Destroy();
 }
 
 void
 DoLongPressPreventDefaultTest(bool aShouldUseTouchAction, uint32_t aBehavior) {
   // We have to initialize both an integer time and TimeStamp time because
   // TimeStamp doesn't have any ToXXX() functions for converting back to
   // primitives.
@@ -1015,16 +1023,17 @@ DoLongPressPreventDefaultTest(bool aShou
 
   ScreenPoint pointOut;
   ViewTransform viewTransformOut;
   apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
 
   EXPECT_EQ(ScreenPoint(), pointOut);
   EXPECT_EQ(ViewTransform(), viewTransformOut);
 
+  apzc->AssertStateIsReset();
   apzc->Destroy();
 }
 
 TEST_F(AsyncPanZoomControllerTester, LongPress) {
   DoLongPressTest(false, mozilla::layers::AllowedTouchBehavior::NONE);
 }
 
 TEST_F(AsyncPanZoomControllerTester, LongPressWithTouchAction) {
--- a/ipc/chromium/src/chrome/common/x11_util.h
+++ b/ipc/chromium/src/chrome/common/x11_util.h
@@ -6,87 +6,12 @@
 #define CHROME_COMMON_X11_UTIL_H_
 
 // This file declares utility functions for X11 (Linux only).
 //
 // These functions do not require the Xlib headers to be included (which is why
 // we use a void* for Visual*). The Xlib headers are highly polluting so we try
 // hard to limit their spread into the rest of the code.
 
-#if (MOZ_WIDGET_GTK == 2)
-typedef struct _GdkDrawable GdkWindow;
-#else
-typedef struct _GdkWindow GdkWindow;
-#endif
-typedef struct _GtkWidget GtkWidget;
 typedef unsigned long XID;
 typedef struct _XDisplay Display;
 
-namespace base {
-class Thread;
-}
-namespace x11_util {
-
-// These functions use the GDK default display and this /must/ be called from
-// the UI thread. Thus, they don't support multiple displays.
-
-// These functions cache their results.
-
-// Return an X11 connection for the current, primary display.
-Display* GetXDisplay();
-// Return true iff the connection supports X shared memory
-bool QuerySharedMemorySupport(Display* dpy);
-// Return true iff the display supports Xrender
-bool QueryRenderSupport(Display* dpy);
-// Return the default screen number for the display
-int GetDefaultScreen(Display* display);
-
-// These functions do not cache their results
-
-// Get the X window id for the default root window
-XID GetX11RootWindow();
-// Get the X window id for the given GTK widget.
-XID GetX11WindowFromGtkWidget(GtkWidget*);
-XID GetX11WindowFromGdkWindow(GdkWindow*);
-// Get a Visual from the given widget. Since we don't include the Xlib
-// headers, this is returned as a void*.
-void* GetVisualFromGtkWidget(GtkWidget*);
-// Return the number of bits-per-pixel for a pixmap of the given depth
-int BitsPerPixelForPixmapDepth(Display*, int depth);
-
-// Return a handle to a server side pixmap. |shared_memory_key| is a SysV
-// IPC key. The shared memory region must contain 32-bit pixels.
-XID AttachSharedMemory(Display* display, int shared_memory_support);
-void DetachSharedMemory(Display* display, XID shmseg);
-
-// Return a handle to an XRender picture where |pixmap| is a handle to a
-// pixmap containing Skia ARGB data.
-XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap);
-
-void FreePicture(Display* display, XID picture);
-void FreePixmap(Display* display, XID pixmap);
-
-// These functions are for performing X opertions outside of the UI thread.
-
-// Return the Display for the secondary X connection. We keep a second
-// connection around for making X requests outside of the UI thread.
-// This function may only be called from the BACKGROUND_X11 thread.
-Display* GetSecondaryDisplay();
-
-// Since one cannot include both WebKit header and Xlib headers in the same
-// file (due to collisions), we wrap all the Xlib functions that we need here.
-// These functions must be called on the BACKGROUND_X11 thread since they
-// reference GetSecondaryDisplay().
-
-// Get the position of the given window in screen coordinates as well as its
-// current size.
-bool GetWindowGeometry(int* x, int* y, unsigned* width, unsigned* height,
-                       XID window);
-
-// Find the immediate parent of an X window.
-//
-// parent_window: (output) the parent window of |window|, or 0.
-// parent_is_root: (output) true iff the parent of |window| is the root window.
-bool GetWindowParent(XID* parent_window, bool* parent_is_root, XID window);
-
-}  // namespace x11_util
-
 #endif  // CHROME_COMMON_X11_UTIL_H_
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -569,16 +569,32 @@ GeckoChildProcessHost::PerformAsyncLaunc
       if (ld_library_path && *ld_library_path) {
           new_ld_lib_path.Assign(path.get());
           new_ld_lib_path.Append(':');
           new_ld_lib_path.Append(ld_library_path);
           newEnvVars["LD_LIBRARY_PATH"] = new_ld_lib_path.get();
       } else {
           newEnvVars["LD_LIBRARY_PATH"] = path.get();
       }
+
+#  if (MOZ_WIDGET_GTK == 3)
+      const char *ld_preload = PR_GetEnv("LD_PRELOAD");
+      nsCString new_ld_preload;
+
+      new_ld_preload.Assign(path.get());
+      new_ld_preload.AppendLiteral("/" DLL_PREFIX "mozgtk2" DLL_SUFFIX);
+
+      if (ld_preload && *ld_preload) {
+          new_ld_preload.AppendLiteral(":");
+          new_ld_preload.Append(ld_preload);
+      }
+      newEnvVars["LD_PRELOAD"] = new_ld_preload.get();
+#  endif // MOZ_WIDGET_GTK
+
+
 # elif OS_MACOSX
       newEnvVars["DYLD_LIBRARY_PATH"] = path.get();
       // XXX DYLD_INSERT_LIBRARIES should only be set when launching a plugin
       //     process, and has no effect on other subprocesses (the hooks in
       //     libplugin_child_interpose.dylib become noops).  But currently it
       //     gets set when launching any kind of subprocess.
       //
       // Trigger "dyld interposing" for the dylib that contains
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -135,17 +135,18 @@ IPDL_SOURCES = [
 LOCAL_INCLUDES += [
     '/xpcom/threads',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
-for var in ('MOZ_CHILD_PROCESS_NAME', 'MOZ_CHILD_PROCESS_BUNDLE'):
+for var in ('MOZ_CHILD_PROCESS_NAME', 'MOZ_CHILD_PROCESS_BUNDLE',
+            'DLL_PREFIX', 'DLL_SUFFIX'):
     DEFINES[var] = '"%s"' % CONFIG[var]
 
 LOCAL_INCLUDES += [
     '/toolkit/crashreporter',
 ]
 
 if CONFIG['MOZ_CONTENT_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
     LOCAL_INCLUDES += [
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1568,21 +1568,21 @@ Neuter(JSContext *cx, unsigned argc, jsv
     if (!JS_NeuterArrayBuffer(cx, obj, changeData))
         return false;
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
-WorkerThreadCount(JSContext *cx, unsigned argc, jsval *vp)
+HelperThreadCount(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 #ifdef JS_THREADSAFE
-    args.rval().setInt32(WorkerThreadState().threadCount);
+    args.rval().setInt32(HelperThreadState().threadCount);
 #else
     args.rval().setInt32(0);
 #endif
     return true;
 }
 
 static bool
 TimesAccessed(JSContext *cx, unsigned argc, jsval *vp)
@@ -1900,19 +1900,19 @@ static const JSFunctionSpecWithHelp Test
 
     JS_FN_HELP("neuter", Neuter, 1, 0,
 "neuter(buffer, \"change-data\"|\"same-data\")",
 "  Neuter the given ArrayBuffer object as if it had been transferred to a\n"
 "  WebWorker. \"change-data\" will update the internal data pointer.\n"
 "  \"same-data\" will leave it set to its original value, to mimic eg\n"
 "  asm.js ArrayBuffer neutering."),
 
-    JS_FN_HELP("workerThreadCount", WorkerThreadCount, 0, 0,
-"workerThreadCount()",
-"  Returns the number of worker threads available for off-main-thread tasks."),
+    JS_FN_HELP("helperThreadCount", HelperThreadCount, 0, 0,
+"helperThreadCount()",
+"  Returns the number of helper threads available for off-main-thread tasks."),
 
     JS_FN_HELP("startTraceLogger", EnableTraceLogger, 0, 0,
 "startTraceLogger()",
 "  Start logging the mainThread.\n"
 "  Note: tracelogging starts automatically. Disable it by setting environment variable\n"
 "  TLOPTIONS=disableMainThread"),
 
     JS_FN_HELP("stopTraceLogger", DisableTraceLogger, 0, 0,
--- a/js/src/jit-test/tests/basic/offThreadCompileScript-01.js
+++ b/js/src/jit-test/tests/basic/offThreadCompileScript-01.js
@@ -1,16 +1,16 @@
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 
 // Test off-thread parsing.
 
 load(libdir + 'asserts.js');
 
-if (workerThreadCount() === 0)
+if (helperThreadCount() === 0)
   quit(0);
 
 offThreadCompileScript('Math.sin(Math.PI/2)');
 assertEq(runOffThreadScript(), 1);
 
 offThreadCompileScript('a string which cannot be reduced to the start symbol');
 assertThrowsInstanceOf(runOffThreadScript, SyntaxError);
 
--- a/js/src/jit-test/tests/debug/onNewScript-off-main-thread.js
+++ b/js/src/jit-test/tests/debug/onNewScript-off-main-thread.js
@@ -1,11 +1,11 @@
 // We still get onNewScript notifications for code compiled off the main thread.
 
-if (workerThreadCount() === 0)
+if (helperThreadCount() === 0)
   quit(0);
 
 var g = newGlobal();
 var dbg = new Debugger(g);
 
 var log;
 dbg.onNewScript = function (s) {
   log += 's';
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -5566,47 +5566,47 @@ CheckFunctionsSequential(ModuleCompiler 
 
     return true;
 }
 
 #ifdef JS_THREADSAFE
 
 // Currently, only one asm.js parallel compilation is allowed at a time.
 // This RAII class attempts to claim this parallel compilation using atomic ops
-// on rt->workerThreadState->asmJSCompilationInProgress.
+// on the helper thread state's asmJSCompilationInProgress.
 class ParallelCompilationGuard
 {
     bool parallelState_;
   public:
     ParallelCompilationGuard() : parallelState_(false) {}
     ~ParallelCompilationGuard() {
         if (parallelState_) {
-            JS_ASSERT(WorkerThreadState().asmJSCompilationInProgress == true);
-            WorkerThreadState().asmJSCompilationInProgress = false;
+            JS_ASSERT(HelperThreadState().asmJSCompilationInProgress == true);
+            HelperThreadState().asmJSCompilationInProgress = false;
         }
     }
     bool claim() {
         JS_ASSERT(!parallelState_);
-        if (!WorkerThreadState().asmJSCompilationInProgress.compareExchange(false, true))
+        if (!HelperThreadState().asmJSCompilationInProgress.compareExchange(false, true))
             return false;
         parallelState_ = true;
         return true;
     }
 };
 
 static bool
 ParallelCompilationEnabled(ExclusiveContext *cx)
 {
     // If 'cx' isn't a JSContext, then we are already off the main thread so
     // off-thread compilation must be enabled. However, since there are a fixed
-    // number of worker threads and one is already being consumed by this
+    // number of helper threads and one is already being consumed by this
     // parsing task, ensure that there another free thread to avoid deadlock.
     // (Note: there is at most one thread used for parsing so we don't have to
     // worry about general dining philosophers.)
-    if (WorkerThreadState().threadCount <= 1)
+    if (HelperThreadState().threadCount <= 1)
         return false;
 
     if (!cx->isJSContext())
         return true;
     return cx->asJSContext()->runtime()->canUseParallelIonCompilation();
 }
 
 // State of compilation as tracked and updated by the main thread.
@@ -5616,28 +5616,28 @@ struct ParallelGroupState
     int32_t outstandingJobs; // Good work, jobs!
     uint32_t compiledJobs;
 
     explicit ParallelGroupState(js::Vector<AsmJSParallelTask> &tasks)
       : tasks(tasks), outstandingJobs(0), compiledJobs(0)
     { }
 };
 
-// Block until a worker-assigned LifoAlloc becomes finished.
+// Block until a helper-assigned LifoAlloc becomes finished.
 static AsmJSParallelTask *
 GetFinishedCompilation(ModuleCompiler &m, ParallelGroupState &group)
 {
-    AutoLockWorkerThreadState lock;
-
-    while (!WorkerThreadState().asmJSWorkerFailed()) {
-        if (!WorkerThreadState().asmJSFinishedList().empty()) {
+    AutoLockHelperThreadState lock;
+
+    while (!HelperThreadState().asmJSFailed()) {
+        if (!HelperThreadState().asmJSFinishedList().empty()) {
             group.outstandingJobs--;
-            return WorkerThreadState().asmJSFinishedList().popCopy();
+            return HelperThreadState().asmJSFinishedList().popCopy();
         }
-        WorkerThreadState().wait(GlobalWorkerThreadState::CONSUMER);
+        HelperThreadState().wait(GlobalHelperThreadState::CONSUMER);
     }
 
     return nullptr;
 }
 
 static bool
 GenerateCodeForFinishedJob(ModuleCompiler &m, ParallelGroupState &group, AsmJSParallelTask **outTask)
 {
@@ -5653,168 +5653,168 @@ GenerateCodeForFinishedJob(ModuleCompile
         // Perform code generation on the main thread.
         IonContext ionContext(m.cx(), &task->mir->alloc());
         if (!GenerateCode(m, func, *task->mir, *task->lir))
             return false;
     }
 
     group.compiledJobs++;
 
-    // Clear the LifoAlloc for use by another worker.
+    // Clear the LifoAlloc for use by another helper.
     TempAllocator &tempAlloc = task->mir->alloc();
     tempAlloc.TempAllocator::~TempAllocator();
     task->lifo.releaseAll();
 
     *outTask = task;
     return true;
 }
 
 static inline bool
 GetUnusedTask(ParallelGroupState &group, uint32_t i, AsmJSParallelTask **outTask)
 {
     // Since functions are dispatched in order, if fewer than |numLifos| functions
     // have been generated, then the |i'th| LifoAlloc must never have been
-    // assigned to a worker thread.
+    // assigned to a helper thread.
     if (i >= group.tasks.length())
         return false;
     *outTask = &group.tasks[i];
     return true;
 }
 
 static bool
 CheckFunctionsParallelImpl(ModuleCompiler &m, ParallelGroupState &group)
 {
 #ifdef DEBUG
     {
-        AutoLockWorkerThreadState lock;
-        JS_ASSERT(WorkerThreadState().asmJSWorklist().empty());
-        JS_ASSERT(WorkerThreadState().asmJSFinishedList().empty());
+        AutoLockHelperThreadState lock;
+        JS_ASSERT(HelperThreadState().asmJSWorklist().empty());
+        JS_ASSERT(HelperThreadState().asmJSFinishedList().empty());
     }
 #endif
-    WorkerThreadState().resetAsmJSFailureState();
+    HelperThreadState().resetAsmJSFailureState();
 
     for (unsigned i = 0; PeekToken(m.parser()) == TOK_FUNCTION; i++) {
         // Get exclusive access to an empty LifoAlloc from the thread group's pool.
         AsmJSParallelTask *task = nullptr;
         if (!GetUnusedTask(group, i, &task) && !GenerateCodeForFinishedJob(m, group, &task))
             return false;
 
         // Generate MIR into the LifoAlloc on the main thread.
         MIRGenerator *mir;
         ModuleCompiler::Func *func;
         if (!CheckFunction(m, task->lifo, &mir, &func))
             return false;
 
-        // Perform optimizations and LIR generation on a worker thread.
+        // Perform optimizations and LIR generation on a helper thread.
         task->init(m.cx()->compartment()->runtimeFromAnyThread(), func, mir);
         if (!StartOffThreadAsmJSCompile(m.cx(), task))
             return false;
 
         group.outstandingJobs++;
     }
 
-    // Block for all outstanding workers to complete.
+    // Block for all outstanding helpers to complete.
     while (group.outstandingJobs > 0) {
         AsmJSParallelTask *ignored = nullptr;
         if (!GenerateCodeForFinishedJob(m, group, &ignored))
             return false;
     }
 
     if (!CheckAllFunctionsDefined(m))
         return false;
 
     JS_ASSERT(group.outstandingJobs == 0);
     JS_ASSERT(group.compiledJobs == m.numFunctions());
 #ifdef DEBUG
     {
-        AutoLockWorkerThreadState lock;
-        JS_ASSERT(WorkerThreadState().asmJSWorklist().empty());
-        JS_ASSERT(WorkerThreadState().asmJSFinishedList().empty());
+        AutoLockHelperThreadState lock;
+        JS_ASSERT(HelperThreadState().asmJSWorklist().empty());
+        JS_ASSERT(HelperThreadState().asmJSFinishedList().empty());
     }
 #endif
-    JS_ASSERT(!WorkerThreadState().asmJSWorkerFailed());
+    JS_ASSERT(!HelperThreadState().asmJSFailed());
     return true;
 }
 
 static void
 CancelOutstandingJobs(ModuleCompiler &m, ParallelGroupState &group)
 {
     // This is failure-handling code, so it's not allowed to fail.
     // The problem is that all memory for compilation is stored in LifoAllocs
     // maintained in the scope of CheckFunctionsParallel() -- so in order
     // for that function to safely return, and thereby remove the LifoAllocs,
-    // none of that memory can be in use or reachable by workers.
+    // none of that memory can be in use or reachable by helpers.
 
     JS_ASSERT(group.outstandingJobs >= 0);
     if (!group.outstandingJobs)
         return;
 
-    AutoLockWorkerThreadState lock;
-
-    // From the compiling tasks, eliminate those waiting for worker assignation.
-    group.outstandingJobs -= WorkerThreadState().asmJSWorklist().length();
-    WorkerThreadState().asmJSWorklist().clear();
+    AutoLockHelperThreadState lock;
+
+    // From the compiling tasks, eliminate those waiting for helper assignation.
+    group.outstandingJobs -= HelperThreadState().asmJSWorklist().length();
+    HelperThreadState().asmJSWorklist().clear();
 
     // From the compiling tasks, eliminate those waiting for codegen.
-    group.outstandingJobs -= WorkerThreadState().asmJSFinishedList().length();
-    WorkerThreadState().asmJSFinishedList().clear();
+    group.outstandingJobs -= HelperThreadState().asmJSFinishedList().length();
+    HelperThreadState().asmJSFinishedList().clear();
 
     // Eliminate tasks that failed without adding to the finished list.
-    group.outstandingJobs -= WorkerThreadState().harvestFailedAsmJSJobs();
+    group.outstandingJobs -= HelperThreadState().harvestFailedAsmJSJobs();
 
     // Any remaining tasks are therefore undergoing active compilation.
     JS_ASSERT(group.outstandingJobs >= 0);
     while (group.outstandingJobs > 0) {
-        WorkerThreadState().wait(GlobalWorkerThreadState::CONSUMER);
-
-        group.outstandingJobs -= WorkerThreadState().harvestFailedAsmJSJobs();
-        group.outstandingJobs -= WorkerThreadState().asmJSFinishedList().length();
-        WorkerThreadState().asmJSFinishedList().clear();
+        HelperThreadState().wait(GlobalHelperThreadState::CONSUMER);
+
+        group.outstandingJobs -= HelperThreadState().harvestFailedAsmJSJobs();
+        group.outstandingJobs -= HelperThreadState().asmJSFinishedList().length();
+        HelperThreadState().asmJSFinishedList().clear();
     }
 
     JS_ASSERT(group.outstandingJobs == 0);
-    JS_ASSERT(WorkerThreadState().asmJSWorklist().empty());
-    JS_ASSERT(WorkerThreadState().asmJSFinishedList().empty());
+    JS_ASSERT(HelperThreadState().asmJSWorklist().empty());
+    JS_ASSERT(HelperThreadState().asmJSFinishedList().empty());
 }
 
 static const size_t LIFO_ALLOC_PARALLEL_CHUNK_SIZE = 1 << 12;
 
 static bool
 CheckFunctionsParallel(ModuleCompiler &m)
 {
     // If parallel compilation isn't enabled (not enough cores, disabled by
     // 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
+    // constraint by hoisting asmJS* state out of HelperThreadState 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;
+    // Saturate all helper threads plus the main thread.
+    size_t numParallelJobs = HelperThreadState().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;
 
     for (size_t i = 0; i < numParallelJobs; i++)
         tasks.infallibleAppend(LIFO_ALLOC_PARALLEL_CHUNK_SIZE);
 
-    // With compilation memory in-scope, dispatch worker threads.
+    // With compilation memory in-scope, dispatch helper threads.
     ParallelGroupState group(tasks);
     if (!CheckFunctionsParallelImpl(m, group)) {
         CancelOutstandingJobs(m, group);
 
-        // If failure was triggered by a worker thread, report error.
-        if (void *maybeFunc = WorkerThreadState().maybeAsmJSFailedFunction()) {
+        // If failure was triggered by a helper thread, report error.
+        if (void *maybeFunc = HelperThreadState().maybeAsmJSFailedFunction()) {
             ModuleCompiler::Func *func = reinterpret_cast<ModuleCompiler::Func *>(maybeFunc);
             return m.failOffset(func->srcOffset(), "allocation failure during compilation");
         }
 
         // Otherwise, the error occurred on the main thread and was already reported.
         return false;
     }
     return true;
@@ -7068,17 +7068,17 @@ EstablishPreconditions(ExclusiveContext 
     if (parser.pc->isGenerator())
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by generator context");
 
     if (parser.pc->isArrowFunction())
         return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by arrow function context");
 
 #ifdef JS_THREADSAFE
     if (ParallelCompilationEnabled(cx))
-        EnsureWorkerThreadsInitialized(cx);
+        EnsureHelperThreadsInitialized(cx);
 #endif
 
     return true;
 }
 
 static bool
 NoExceptionPending(ExclusiveContext *cx)
 {
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -20,16 +20,17 @@
 #include "builtin/TypedObject.h"
 #ifdef JSGC_GENERATIONAL
 # include "gc/Nursery.h"
 #endif
 #include "jit/IonCaches.h"
 #include "jit/IonLinker.h"
 #include "jit/IonOptimizationLevels.h"
 #include "jit/IonSpewer.h"
+#include "jit/Lowering.h"
 #include "jit/MIRGenerator.h"
 #include "jit/MoveEmitter.h"
 #include "jit/ParallelFunctions.h"
 #include "jit/ParallelSafetyAnalysis.h"
 #include "jit/RangeAnalysis.h"
 #include "vm/ForkJoin.h"
 #include "vm/TraceLogging.h"
 
@@ -1219,16 +1220,19 @@ class OutOfLineInterruptCheckImplicit : 
       : block(block), lir(lir)
     { }
 
     bool accept(CodeGenerator *codegen) {
         return codegen->visitOutOfLineInterruptCheckImplicit(this);
     }
 };
 
+typedef bool (*InterruptCheckFn)(JSContext *);
+static const VMFunction InterruptCheckInfo = FunctionInfo<InterruptCheckFn>(InterruptCheck);
+
 bool
 CodeGenerator::visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit *ool)
 {
 #ifdef CHECK_OSIPOINT_REGISTERS
     // This is path is entered from the patched back-edge of the loop. This
     // means that the JitAtivation flags used for checking the validity of the
     // OSI points are not reseted by the path generated by generateBody, so we
     // have to reset it here.
@@ -1560,24 +1564,67 @@ bool
 CodeGenerator::visitSlots(LSlots *lir)
 {
     Address slots(ToRegister(lir->object()), JSObject::offsetOfSlots());
     masm.loadPtr(slots, ToRegister(lir->output()));
     return true;
 }
 
 bool
-CodeGenerator::visitStoreSlotV(LStoreSlotV *store)
-{
-    Register base = ToRegister(store->slots());
-    int32_t offset = store->mir()->slot() * sizeof(Value);
-
-    const ValueOperand value = ToValue(store, LStoreSlotV::Value);
-
-    if (store->mir()->needsBarrier())
+CodeGenerator::visitLoadSlotT(LLoadSlotT *lir)
+{
+    Register base = ToRegister(lir->slots());
+    int32_t offset = lir->mir()->slot() * sizeof(js::Value);
+    AnyRegister result = ToAnyRegister(lir->output());
+
+    masm.loadUnboxedValue(Address(base, offset), lir->mir()->type(), result);
+    return true;
+}
+
+bool
+CodeGenerator::visitLoadSlotV(LLoadSlotV *lir)
+{
+    ValueOperand dest = ToOutValue(lir);
+    Register base = ToRegister(lir->input());
+    int32_t offset = lir->mir()->slot() * sizeof(js::Value);
+
+    masm.loadValue(Address(base, offset), dest);
+    return true;
+}
+
+bool
+CodeGenerator::visitStoreSlotT(LStoreSlotT *lir)
+{
+    Register base = ToRegister(lir->slots());
+    int32_t offset = lir->mir()->slot() * sizeof(js::Value);
+    Address dest(base, offset);
+
+    if (lir->mir()->needsBarrier())
+        emitPreBarrier(dest, lir->mir()->slotType());
+
+    MIRType valueType = lir->mir()->value()->type();
+    ConstantOrRegister value;
+    if (lir->value()->isConstant())
+        value = ConstantOrRegister(*lir->value()->toConstant());
+    else
+        value = TypedOrValueRegister(valueType, ToAnyRegister(lir->value()));
+
+    masm.storeUnboxedValue(value, valueType, dest, lir->mir()->slotType());
+    return true;
+}
+
+bool
+CodeGenerator::visitStoreSlotV(LStoreSlotV *lir)
+{
+    Register base = ToRegister(lir->slots());
+    int32_t offset = lir->mir()->slot() * sizeof(Value);
+
+    const ValueOperand value = ToValue(lir, LStoreSlotV::Value);
+
+    if (lir->mir()->needsBarrier())
        emitPreBarrier(Address(base, offset), MIRType_Value);
 
     masm.storeValue(value, Address(base, offset));
     return true;
 }
 
 bool
 CodeGenerator::emitGetPropertyPolymorphic(LInstruction *ins, Register obj, Register scratch,
@@ -5628,30 +5675,49 @@ CodeGenerator::emitStoreHoleCheck(Regist
                              Address(elements, ToInt32(index) * sizeof(js::Value)), &bail);
     } else {
         masm.branchTestMagic(Assembler::Equal,
                              BaseIndex(elements, ToRegister(index), TimesEight), &bail);
     }
     return bailoutFrom(&bail, snapshot);
 }
 
+void
+CodeGenerator::emitStoreElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
+                                     Register elements, const LAllocation *index)
+{
+    ConstantOrRegister v;
+    if (value->isConstant())
+        v = ConstantOrRegister(*value->toConstant());
+    else
+        v = TypedOrValueRegister(valueType, ToAnyRegister(value));
+
+    if (index->isConstant()) {
+        Address dest(elements, ToInt32(index) * sizeof(js::Value));
+        masm.storeUnboxedValue(v, valueType, dest, elementType);
+    } else {
+        BaseIndex dest(elements, ToRegister(index), TimesEight);
+        masm.storeUnboxedValue(v, valueType, dest, elementType);
+    }
+}
+
 bool
 CodeGenerator::visitStoreElementT(LStoreElementT *store)
 {
     Register elements = ToRegister(store->elements());
     const LAllocation *index = store->index();
 
     if (store->mir()->needsBarrier())
        emitPreBarrier(elements, index, store->mir()->elementType());
 
     if (store->mir()->needsHoleCheck() && !emitStoreHoleCheck(elements, index, store->snapshot()))
         return false;
 
-    storeElementTyped(store->value(), store->mir()->value()->type(), store->mir()->elementType(),
-                      elements, index);
+    emitStoreElementTyped(store->value(), store->mir()->value()->type(), store->mir()->elementType(),
+                          elements, index);
     return true;
 }
 
 bool
 CodeGenerator::visitStoreElementV(LStoreElementV *lir)
 {
     const ValueOperand value = ToValue(lir, LStoreElementV::Value);
     Register elements = ToRegister(lir->elements());
@@ -5683,18 +5749,18 @@ CodeGenerator::visitStoreElementHoleT(LS
     // OOL path if index >= initializedLength.
     Address initLength(elements, ObjectElements::offsetOfInitializedLength());
     masm.branchKey(Assembler::BelowOrEqual, initLength, ToInt32Key(index), ool->entry());
 
     if (lir->mir()->needsBarrier())
         emitPreBarrier(elements, index, lir->mir()->elementType());
 
     masm.bind(ool->rejoinStore());
-    storeElementTyped(lir->value(), lir->mir()->value()->type(), lir->mir()->elementType(),
-                      elements, index);
+    emitStoreElementTyped(lir->value(), lir->mir()->value()->type(), lir->mir()->elementType(),
+                          elements, index);
 
     masm.bind(ool->rejoin());
     return true;
 }
 
 bool
 CodeGenerator::visitStoreElementHoleV(LStoreElementHoleV *lir)
 {
@@ -5789,18 +5855,18 @@ CodeGenerator::visitOutOfLineStoreElemen
     masm.bind(&dontUpdate);
 
     masm.bumpKey(&key, -1);
 
     if (ins->isStoreElementHoleT() && valueType != MIRType_Double) {
         // The inline path for StoreElementHoleT does not always store the type tag,
         // so we do the store on the OOL path. We use MIRType_None for the element type
         // so that storeElementTyped will always store the type tag.
-        storeElementTyped(ins->toStoreElementHoleT()->value(), valueType, MIRType_None, elements,
-                          index);
+        emitStoreElementTyped(ins->toStoreElementHoleT()->value(), valueType, MIRType_None,
+                              elements, index);
         masm.jump(ool->rejoin());
     } else {
         // Jump to the inline path where we will store the value.
         masm.jump(ool->rejoinStore());
     }
 
     masm.bind(&callStub);
     saveLive(ins);
@@ -7661,16 +7727,48 @@ CodeGenerator::visitToIdV(LToIdV *lir)
     masm.unboxDouble(index, temp);
     masm.convertDoubleToInt32(temp, out.scratchReg(), ool->entry(), true);
     masm.tagValue(JSVAL_TYPE_INT32, out.scratchReg(), out);
 
     masm.bind(ool->rejoin());
     return true;
 }
 
+template<typename T>
+bool
+CodeGenerator::emitLoadElementT(LLoadElementT *lir, const T &source)
+{
+    if (LIRGenerator::allowTypedElementHoleCheck()) {
+        if (lir->mir()->needsHoleCheck()) {
+            Assembler::Condition cond = masm.testMagic(Assembler::Equal, source);
+            if (!bailoutIf(cond, lir->snapshot()))
+                return false;
+        }
+    } else {
+        MOZ_ASSERT(!lir->mir()->needsHoleCheck());
+    }
+
+    AnyRegister output = ToAnyRegister(lir->output());
+    if (lir->mir()->loadDoubles())
+        masm.loadDouble(source, output.fpu());
+    else
+        masm.loadUnboxedValue(source, lir->mir()->type(), output);
+    return true;
+}
+
+bool
+CodeGenerator::visitLoadElementT(LLoadElementT *lir)
+{
+    Register elements = ToRegister(lir->elements());
+    const LAllocation *index = lir->index();
+    if (index->isConstant())
+        return emitLoadElementT(lir, Address(elements, ToInt32(index) * sizeof(js::Value)));
+    return emitLoadElementT(lir, BaseIndex(elements, ToRegister(index), TimesEight));
+}
+
 bool
 CodeGenerator::visitLoadElementV(LLoadElementV *load)
 {
     Register elements = ToRegister(load->elements());
     const ValueOperand out = ToOutValue(load);
 
     if (load->index()->isConstant())
         masm.loadValue(Address(elements, ToInt32(load->index()) * sizeof(Value)), out);
@@ -8686,16 +8784,29 @@ CodeGenerator::visitAssertRangeV(LAssert
         masm.bind(&isNotDouble);
     }
 
     masm.assumeUnreachable("Incorrect range for Value.");
     masm.bind(&done);
     return true;
 }
 
+bool
+CodeGenerator::visitInterruptCheck(LInterruptCheck *lir)
+{
+    OutOfLineCode *ool = oolCallVM(InterruptCheckInfo, lir, (ArgList()), StoreNothing());
+    if (!ool)
+        return false;
+
+    AbsoluteAddress interruptAddr(GetIonContext()->runtime->addressOfInterrupt());
+    masm.branch32(Assembler::NotEqual, interruptAddr, Imm32(0), ool->entry());
+    masm.bind(ool->rejoin());
+    return true;
+}
+
 typedef bool (*RecompileFn)(JSContext *);
 static const VMFunction RecompileFnInfo = FunctionInfo<RecompileFn>(Recompile);
 
 bool
 CodeGenerator::visitRecompileCheck(LRecompileCheck *ins)
 {
     Label done;
     Register tmp = ToRegister(ins->scratch());
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -101,17 +101,20 @@ class CodeGenerator : public CodeGenerat
     bool visitRegExpReplace(LRegExpReplace *lir);
     bool visitStringReplace(LStringReplace *lir);
     bool visitLambda(LLambda *lir);
     bool visitLambdaArrow(LLambdaArrow *lir);
     bool visitLambdaForSingleton(LLambdaForSingleton *lir);
     bool visitLambdaPar(LLambdaPar *lir);
     bool visitPointer(LPointer *lir);
     bool visitSlots(LSlots *lir);
-    bool visitStoreSlotV(LStoreSlotV *store);
+    bool visitLoadSlotT(LLoadSlotT *lir);
+    bool visitLoadSlotV(LLoadSlotV *lir);
+    bool visitStoreSlotT(LStoreSlotT *lir);
+    bool visitStoreSlotV(LStoreSlotV *lir);
     bool visitElements(LElements *lir);
     bool visitConvertElementsToDoubles(LConvertElementsToDoubles *lir);
     bool visitMaybeToDoubleElement(LMaybeToDoubleElement *lir);
     bool visitGuardObjectIdentity(LGuardObjectIdentity *guard);
     bool visitGuardShapePolymorphic(LGuardShapePolymorphic *lir);
     bool visitTypeBarrierV(LTypeBarrierV *lir);
     bool visitTypeBarrierO(LTypeBarrierO *lir);
     bool visitMonitorTypes(LMonitorTypes *lir);
@@ -223,16 +226,18 @@ class CodeGenerator : public CodeGenerat
     bool visitCallGetProperty(LCallGetProperty *lir);
     bool visitCallGetElement(LCallGetElement *lir);
     bool visitCallSetElement(LCallSetElement *lir);
     bool visitCallInitElementArray(LCallInitElementArray *lir);
     bool visitThrow(LThrow *lir);
     bool visitTypeOfV(LTypeOfV *lir);
     bool visitOutOfLineTypeOfV(OutOfLineTypeOfV *ool);
     bool visitToIdV(LToIdV *lir);
+    template<typename T> bool emitLoadElementT(LLoadElementT *lir, const T &source);
+    bool visitLoadElementT(LLoadElementT *lir);
     bool visitLoadElementV(LLoadElementV *load);
     bool visitLoadElementHole(LLoadElementHole *lir);
     bool visitStoreElementT(LStoreElementT *lir);
     bool visitStoreElementV(LStoreElementV *lir);
     bool visitStoreElementHoleT(LStoreElementHoleT *lir);
     bool visitStoreElementHoleV(LStoreElementHoleV *lir);
     bool emitArrayPopShift(LInstruction *lir, const MArrayPopShift *mir, Register obj,
                            Register elementsTemp, Register lengthTemp, TypedOrValueRegister out);
@@ -341,16 +346,17 @@ class CodeGenerator : public CodeGenerat
     bool visitNameIC(OutOfLineUpdateCache *ool, DataPtr<NameIC> &ic);
     bool visitCallsiteCloneIC(OutOfLineUpdateCache *ool, DataPtr<CallsiteCloneIC> &ic);
 
     bool visitAssertRangeI(LAssertRangeI *ins);
     bool visitAssertRangeD(LAssertRangeD *ins);
     bool visitAssertRangeF(LAssertRangeF *ins);
     bool visitAssertRangeV(LAssertRangeV *ins);
 
+    bool visitInterruptCheck(LInterruptCheck *lir);
     bool visitRecompileCheck(LRecompileCheck *ins);
 
   private:
     bool addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
                              PropertyName *name, TypedOrValueRegister output,
                              bool monitoredResult, jsbytecode *profilerLeavePc);
     bool addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index,
                             TypedOrValueRegister output, bool monitoredResult,
@@ -430,16 +436,19 @@ class CodeGenerator : public CodeGenerat
                                      Label *ifEmulatesUndefined,
                                      Label *ifDoesntEmulateUndefined,
                                      Register scratch, OutOfLineTestObject *ool);
 
     // Get a label for the start of block which can be used for jumping, in
     // place of jumpToBlock.
     Label *getJumpLabelForBranch(MBasicBlock *block);
 
+    void emitStoreElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
+                               Register elements, const LAllocation *index);
+
     // Bailout if an element about to be written to is a hole.
     bool emitStoreHoleCheck(Register elements, const LAllocation *index, LSnapshot *snapshot);
 
     bool emitAssertRangeI(const Range *r, Register input);
     bool emitAssertRangeD(const Range *r, FloatRegister input, FloatRegister temp);
 
     Vector<CodeOffsetLabel, 0, IonAllocPolicy> ionScriptLabels_;
 #ifdef DEBUG
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -559,24 +559,24 @@ jit::FinishOffThreadBuilder(IonBuilder *
     js_delete(builder->backgroundCodegen());
     js_delete(builder->alloc().lifoAlloc());
 }
 
 static inline void
 FinishAllOffThreadCompilations(JSCompartment *comp)
 {
 #ifdef JS_THREADSAFE
-    AutoLockWorkerThreadState lock;
-    GlobalWorkerThreadState::IonBuilderVector &finished = WorkerThreadState().ionFinishedList();
+    AutoLockHelperThreadState lock;
+    GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
 
     for (size_t i = 0; i < finished.length(); i++) {
         IonBuilder *builder = finished[i];
         if (builder->compartment == CompileCompartment::get(comp)) {
             FinishOffThreadBuilder(builder);
-            WorkerThreadState().remove(finished, &i);
+            HelperThreadState().remove(finished, &i);
         }
     }
 #endif
 }
 
 /* static */ void
 JitRuntime::Mark(JSTracer *trc)
 {
@@ -602,17 +602,17 @@ JitCompartment::mark(JSTracer *trc, JSCo
     trc->runtime()->jitRuntime()->freeOsrTempData();
 
     // Mark scripts with parallel IonScripts if we should preserve them.
     if (activeParallelEntryScripts_) {
         for (ScriptSet::Enum e(*activeParallelEntryScripts_); !e.empty(); e.popFront()) {
             JSScript *script = e.front();
 
             // If the script has since been invalidated or was attached by an
-            // off-thread worker too late (i.e., the ForkJoin finished with
+            // off-thread helper too late (i.e., the ForkJoin finished with
             // warmup doing all the work), remove it.
             if (!script->hasParallelIonScript() ||
                 !script->parallelIonScript()->isParallelEntryScript())
             {
                 e.removeFront();
                 continue;
             }
 
@@ -1673,33 +1673,33 @@ void
 AttachFinishedCompilations(JSContext *cx)
 {
 #ifdef JS_THREADSAFE
     JitCompartment *ion = cx->compartment()->jitCompartment();
     if (!ion)
         return;
 
     types::AutoEnterAnalysis enterTypes(cx);
-    AutoLockWorkerThreadState lock;
-
-    GlobalWorkerThreadState::IonBuilderVector &finished = WorkerThreadState().ionFinishedList();
+    AutoLockHelperThreadState lock;
+
+    GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
 
     TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
 
     // Incorporate any off thread compilations for the compartment which have
     // finished, failed or have been cancelled.
     while (true) {
         IonBuilder *builder = nullptr;
 
         // Find a finished builder for the compartment.
         for (size_t i = 0; i < finished.length(); i++) {
             IonBuilder *testBuilder = finished[i];
             if (testBuilder->compartment == CompileCompartment::get(cx->compartment())) {
                 builder = testBuilder;
-                WorkerThreadState().remove(finished, &i);
+                HelperThreadState().remove(finished, &i);
                 break;
             }
         }
         if (!builder)
             break;
 
         if (CodeGenerator *codegen = builder->backgroundCodegen()) {
             RootedScript script(cx, builder->script());
@@ -1709,19 +1709,19 @@ AttachFinishedCompilations(JSContext *cx
 
             // Root the assembler until the builder is finished below. As it
             // was constructed off thread, the assembler has not been rooted
             // previously, though any GC activity would discard the builder.
             codegen->masm.constructRoot(cx);
 
             bool success;
             {
-                // Release the worker thread lock and root the compiler for GC.
+                // Release the helper thread lock and root the compiler for GC.
                 AutoTempAllocatorRooter root(cx, &builder->alloc());
-                AutoUnlockWorkerThreadState unlock;
+                AutoUnlockHelperThreadState unlock;
                 success = codegen->link(cx, builder->constraints());
             }
 
             if (!success) {
                 // Silently ignore OOM during code generation. The caller is
                 // InvokeInterruptCallback, which always runs at a
                 // nondeterministic time. It's not OK to throw a catchable
                 // exception from there.
@@ -1746,17 +1746,17 @@ OffThreadCompilationAvailable(JSContext 
     //
     // Require cpuCount > 1 so that Ion compilation jobs and main-thread
     // execution are not competing for the same resources.
     //
     // Skip off thread compilation if PC count profiling is enabled, as
     // CodeGenerator::maybeCreateScriptCounts will not attach script profiles
     // when running off thread.
     return cx->runtime()->canUseParallelIonCompilation()
-        && WorkerThreadState().cpuCount > 1
+        && HelperThreadState().cpuCount > 1
         && cx->runtime()->gc.incrementalState == gc::NO_INCREMENTAL
         && !cx->runtime()->profilingScripts;
 #else
     return false;
 #endif
 }
 
 static void
@@ -1800,17 +1800,17 @@ IonCompile(JSContext *cx, JSScript *scri
 {
     TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
     AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, script));
     AutoTraceLog logCompile(logger, TraceLogger::IonCompilation);
 
     JS_ASSERT(optimizationLevel > Optimization_DontCompile);
 
     // Make sure the script's canonical function isn't lazy. We can't de-lazify
-    // it in a worker thread.
+    // it in a helper thread.
     script->ensureNonLazyCanonicalFunction(cx);
 
     TrackPropertiesForSingletonScopes(cx, script, baselineFrame);
 
     LifoAlloc *alloc = cx->new_<LifoAlloc>(BUILDER_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
     if (!alloc)
         return AbortReason_Alloc;
 
@@ -1976,17 +1976,17 @@ CheckScriptSize(JSContext *cx, JSScript*
     }
 
     uint32_t numLocalsAndArgs = NumLocalsAndArgs(script);
 
     if (script->length() > MAX_MAIN_THREAD_SCRIPT_SIZE ||
         numLocalsAndArgs > MAX_MAIN_THREAD_LOCALS_AND_ARGS)
     {
 #ifdef JS_THREADSAFE
-        size_t cpuCount = WorkerThreadState().cpuCount;
+        size_t cpuCount = HelperThreadState().cpuCount;
 #else
         size_t cpuCount = 1;
 #endif
         if (cx->runtime()->canUseParallelIonCompilation() && cpuCount > 1) {
             // Even if off thread compilation is enabled, there are cases where
             // compilation must still occur on the main thread. Don't compile
             // in these cases (except when profiling scripts, as compilations
             // occurring with profiling should reflect those without), but do
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -1268,20 +1268,18 @@ jit::BuildPhiReverseMapping(MIRGraph &gr
     //             loop continuation. The continue itself has exactly one
     //             successor.
     //   * An if. Each branch as exactly one predecessor.
     //   * A switch. Each branch has exactly one predecessor.
     //   * Loop tail. A new block is always created for the exit, and if a
     //             break statement is present, the exit block will forward
     //             directly to the break block.
     for (MBasicBlockIterator block(graph.begin()); block != graph.end(); block++) {
-        if (block->numPredecessors() < 2) {
-            JS_ASSERT(block->phisEmpty());
+        if (block->phisEmpty())
             continue;
-        }
 
         // Assert on the above.
         for (size_t j = 0; j < block->numPredecessors(); j++) {
             MBasicBlock *pred = block->getPredecessor(j);
 
 #ifdef DEBUG
             size_t numSuccessorsWithPhis = 0;
             for (size_t k = 0; k < pred->numSuccessors(); k++) {
@@ -1518,23 +1516,17 @@ jit::AssertExtendedGraphCoherency(MIRGra
         }
 
         uint32_t successorWithPhis = 0;
         for (size_t i = 0; i < block->numSuccessors(); i++)
             if (!block->getSuccessor(i)->phisEmpty())
                 successorWithPhis++;
 
         JS_ASSERT(successorWithPhis <= 1);
-        JS_ASSERT_IF(successorWithPhis, block->successorWithPhis() != nullptr);
-
-        // I'd like to assert this, but it's not necc. true.  Sometimes we set this
-        // flag to non-nullptr just because a successor has multiple preds, even if it
-        // does not actually have any phis.
-        //
-        // JS_ASSERT_IF(!successorWithPhis, block->successorWithPhis() == nullptr);
+        JS_ASSERT((successorWithPhis != 0) == (block->successorWithPhis() != nullptr));
     }
 
     AssertDominatorTree(graph);
 #endif
 }
 
 
 struct BoundsCheckInfo
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -3498,34 +3498,16 @@ class LLambdaPar : public LInstructionHe
     const LDefinition *getTemp0() {
         return getTemp(0);
     }
     const LDefinition *getTemp1() {
         return getTemp(1);
     }
 };
 
-// Determines the implicit |this| value for function calls.
-class LImplicitThis : public LInstructionHelper<BOX_PIECES, 1, 0>
-{
-  public:
-    LIR_HEADER(ImplicitThis)
-
-    explicit LImplicitThis(const LAllocation &callee) {
-        setOperand(0, callee);
-    }
-
-    const MImplicitThis *mir() const {
-        return mir_->toImplicitThis();
-    }
-    const LAllocation *callee() {
-        return getOperand(0);
-    }
-};
-
 // Load the "slots" member out of a JSObject.
 //   Input: JSObject pointer
 //   Output: slots pointer
 class LSlots : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(Slots)
 
@@ -4716,18 +4698,24 @@ class LLoadSlotV : public LInstructionHe
 // Load a typed value from an object's dslots or a slots vector. Unlike
 // LLoadSlotV, this can bypass extracting a type tag, directly retrieving a
 // pointer, integer, or double.
 class LLoadSlotT : public LInstructionHelper<1, 1, 0>
 {
   public:
     LIR_HEADER(LoadSlotT)
 
-    explicit LLoadSlotT(const LAllocation &in) {
-        setOperand(0, in);
+    explicit LLoadSlotT(const LAllocation &slots) {
+        setOperand(0, slots);
+    }
+    const LAllocation *slots() {
+        return getOperand(0);
+    }
+    const LDefinition *output() {
+        return this->getDef(0);
     }
     const MLoadSlot *mir() const {
         return mir_->toLoadSlot();
     }
 };
 
 // Store a value to an object's dslots or a slots vector.
 class LStoreSlotV : public LInstructionHelper<0, 1 + BOX_PIECES, 0>
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -158,17 +158,16 @@
     _(RegExpExec)                   \
     _(RegExpTest)                   \
     _(RegExpReplace)                \
     _(StringReplace)                \
     _(Lambda)                       \
     _(LambdaArrow)                  \
     _(LambdaForSingleton)           \
     _(LambdaPar)                    \
-    _(ImplicitThis)                 \
     _(Slots)                        \
     _(Elements)                     \
     _(ConvertElementsToDoubles)     \
     _(MaybeToDoubleElement)         \
     _(LoadSlotV)                    \
     _(LoadSlotT)                    \
     _(StoreSlotV)                   \
     _(StoreSlotT)                   \
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2093,25 +2093,16 @@ LIRGenerator::visitLambdaPar(MLambdaPar 
     JS_ASSERT(!ins->info().useNewTypeForClone);
     LLambdaPar *lir = new(alloc()) LLambdaPar(useRegister(ins->forkJoinContext()),
                                               useRegister(ins->scopeChain()),
                                               temp(), temp());
     return define(lir, ins);
 }
 
 bool
-LIRGenerator::visitImplicitThis(MImplicitThis *ins)
-{
-    JS_ASSERT(ins->callee()->type() == MIRType_Object);
-
-    LImplicitThis *lir = new(alloc()) LImplicitThis(useRegister(ins->callee()));
-    return assignSnapshot(lir) && defineBox(lir, ins);
-}
-
-bool
 LIRGenerator::visitSlots(MSlots *ins)
 {
     return define(new(alloc()) LSlots(useRegisterAtStart(ins->object())), ins);
 }
 
 bool
 LIRGenerator::visitElements(MElements *ins)
 {
@@ -2548,29 +2539,29 @@ LIRGenerator::visitLoadElement(MLoadElem
 {
     JS_ASSERT(ins->elements()->type() == MIRType_Elements);
     JS_ASSERT(ins->index()->type() == MIRType_Int32);
 
     switch (ins->type()) {
       case MIRType_Value:
       {
         LLoadElementV *lir = new(alloc()) LLoadElementV(useRegister(ins->elements()),
-                                               useRegisterOrConstant(ins->index()));
+                                                        useRegisterOrConstant(ins->index()));
         if (ins->fallible() && !assignSnapshot(lir))
             return false;
         return defineBox(lir, ins);
       }
       case MIRType_Undefined:
       case MIRType_Null:
         MOZ_ASSUME_UNREACHABLE("typed load must have a payload");
 
       default:
       {
         LLoadElementT *lir = new(alloc()) LLoadElementT(useRegister(ins->elements()),
-                                               useRegisterOrConstant(ins->index()));
+                                                        useRegisterOrConstant(ins->index()));
         if (ins->fallible() && !assignSnapshot(lir))
             return false;
         return define(lir, ins);
       }
     }
 }
 
 bool
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -155,17 +155,16 @@ class LIRGenerator : public LIRGenerator
     bool visitRegExp(MRegExp *ins);
     bool visitRegExpExec(MRegExpExec *ins);
     bool visitRegExpTest(MRegExpTest *ins);
     bool visitRegExpReplace(MRegExpReplace *ins);
     bool visitStringReplace(MStringReplace *ins);
     bool visitLambda(MLambda *ins);
     bool visitLambdaArrow(MLambdaArrow *ins);
     bool visitLambdaPar(MLambdaPar *ins);
-    bool visitImplicitThis(MImplicitThis *ins);
     bool visitSlots(MSlots *ins);
     bool visitElements(MElements *ins);
     bool visitConstantElements(MConstantElements *ins);
     bool visitConvertElementsToDoubles(MConvertElementsToDoubles *ins);
     bool visitMaybeToDoubleElement(MMaybeToDoubleElement *ins);
     bool visitLoadSlot(MLoadSlot *ins);
     bool visitFunctionEnvironment(MFunctionEnvironment *ins);
     bool visitForkJoinContext(MForkJoinContext *ins);
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -915,17 +915,16 @@ MTypeBarrier::printOpcode(FILE *fp) cons
     fprintf(fp, " ");
     getOperand(0)->printName(fp);
 }
 
 void
 MPhi::removeOperand(size_t index)
 {
     JS_ASSERT(index < numOperands());
-    JS_ASSERT(numOperands() > 1);
     JS_ASSERT(getUseFor(index)->index() == index);
     JS_ASSERT(getUseFor(index)->consumer() == this);
 
     // If we have phi(..., a, b, c, d, ..., z) and we plan
     // on removing a, then first shift downward so that we have
     // phi(..., b, c, d, ..., z, z):
     size_t length = inputs_.length();
     for (size_t i = index; i < length - 1; i++)
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -5539,46 +5539,16 @@ class MLambdaPar
         return this;
     }
 
     const LambdaFunctionInfo &info() const {
         return info_;
     }
 };
 
-// Determines the implicit |this| value for function calls.
-class MImplicitThis
-  : public MUnaryInstruction,
-    public SingleObjectPolicy
-{
-    explicit MImplicitThis(MDefinition *callee)
-      : MUnaryInstruction(callee)
-    {
-        setResultType(MIRType_Value);
-        setMovable();
-    }
-
-  public:
-    INSTRUCTION_HEADER(ImplicitThis)
-
-    static MImplicitThis *New(TempAllocator &alloc, MDefinition *callee) {
-        return new(alloc) MImplicitThis(callee);
-    }
-
-    TypePolicy *typePolicy() {
-        return this;
-    }
-    MDefinition *callee() const {
-        return getOperand(0);
-    }
-    AliasSet getAliasSet() const {
-        return AliasSet::None();
-    }
-};
-
 // Returns obj->slots.
 class MSlots
   : public MUnaryInstruction,
     public SingleObjectPolicy
 {
     explicit MSlots(MDefinition *object)
       : MUnaryInstruction(object)
     {
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -104,17 +104,16 @@ namespace jit {
     _(LimitedTruncate)                                                      \
     _(RegExp)                                                               \
     _(RegExpExec)                                                           \
     _(RegExpTest)                                                           \
     _(RegExpReplace)                                                        \
     _(StringReplace)                                                        \
     _(Lambda)                                                               \
     _(LambdaArrow)                                                          \
-    _(ImplicitThis)                                                         \
     _(Slots)                                                                \
     _(Elements)                                                             \
     _(ConstantElements)                                                     \
     _(ConvertElementsToDoubles)                                             \
     _(MaybeToDoubleElement)                                                 \
     _(LoadSlot)                                                             \
     _(StoreSlot)                                                            \
     _(FunctionEnvironment)                                                  \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -193,17 +193,16 @@ class ParallelSafetyVisitor : public MIn
     UNSAFE_OP(InitPropGetterSetter)
     SAFE_OP(Start)
     UNSAFE_OP(OsrEntry)
     SAFE_OP(Nop)
     SAFE_OP(LimitedTruncate)
     UNSAFE_OP(RegExp)
     CUSTOM_OP(Lambda)
     UNSAFE_OP(LambdaArrow)
-    UNSAFE_OP(ImplicitThis)
     SAFE_OP(Slots)
     SAFE_OP(Elements)
     SAFE_OP(ConstantElements)
     SAFE_OP(LoadSlot)
     WRITE_GUARDED_OP(StoreSlot, slots)
     SAFE_OP(FunctionEnvironment) // just a load of func env ptr
     SAFE_OP(FilterTypeSet)
     SAFE_OP(TypeBarrier) // causes a bailout if the type is not found: a-ok with us
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1723,142 +1723,16 @@ CodeGeneratorARM::visitNotF(LNotF *ins)
         masm.ma_mov(Imm32(0), dest);
         masm.ma_mov(Imm32(1), dest, NoSetCond, Assembler::Equal);
         masm.ma_mov(Imm32(1), dest, NoSetCond, Assembler::Overflow);
     }
     return true;
 }
 
 bool
-CodeGeneratorARM::visitLoadSlotV(LLoadSlotV *load)
-{
-    const ValueOperand out = ToOutValue(load);
-    Register base = ToRegister(load->input());
-    int32_t offset = load->mir()->slot() * sizeof(js::Value);
-
-    masm.loadValue(Address(base, offset), out);
-    return true;
-}
-
-bool
-CodeGeneratorARM::visitLoadSlotT(LLoadSlotT *load)
-{
-    Register base = ToRegister(load->input());
-    int32_t offset = load->mir()->slot() * sizeof(js::Value);
-
-    if (load->mir()->type() == MIRType_Double)
-        masm.loadInt32OrDouble(Operand(base, offset), ToFloatRegister(load->output()));
-    else
-        masm.ma_ldr(Operand(base, offset + NUNBOX32_PAYLOAD_OFFSET), ToRegister(load->output()));
-    return true;
-}
-
-bool
-CodeGeneratorARM::visitStoreSlotT(LStoreSlotT *store)
-{
-
-    Register base = ToRegister(store->slots());
-    int32_t offset = store->mir()->slot() * sizeof(js::Value);
-
-    const LAllocation *value = store->value();
-    MIRType valueType = store->mir()->value()->type();
-
-    if (store->mir()->needsBarrier())
-        emitPreBarrier(Address(base, offset), store->mir()->slotType());
-
-    if (valueType == MIRType_Double) {
-        masm.ma_vstr(ToFloatRegister(value), Operand(base, offset));
-        return true;
-    }
-
-    // Store the type tag if needed.
-    if (valueType != store->mir()->slotType())
-        masm.storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), Operand(base, offset));
-
-    // Store the payload.
-    if (value->isConstant())
-        masm.storePayload(*value->toConstant(), Operand(base, offset));
-    else
-        masm.storePayload(ToRegister(value), Operand(base, offset));
-
-    return true;
-}
-
-bool
-CodeGeneratorARM::visitLoadElementT(LLoadElementT *load)
-{
-    Register base = ToRegister(load->elements());
-    if (load->mir()->type() == MIRType_Double) {
-        FloatRegister fpreg = ToFloatRegister(load->output());
-        if (load->index()->isConstant()) {
-            Address source(base, ToInt32(load->index()) * sizeof(Value));
-            if (load->mir()->loadDoubles())
-                masm.loadDouble(source, fpreg);
-            else
-                masm.loadInt32OrDouble(source, fpreg);
-        } else {
-            Register index = ToRegister(load->index());
-            if (load->mir()->loadDoubles())
-                masm.loadDouble(BaseIndex(base, index, TimesEight), fpreg);
-            else
-                masm.loadInt32OrDouble(base, index, fpreg);
-        }
-    } else {
-        if (load->index()->isConstant()) {
-            Address source(base, ToInt32(load->index()) * sizeof(Value));
-            masm.load32(source, ToRegister(load->output()));
-        } else {
-            masm.ma_ldr(DTRAddr(base, DtrRegImmShift(ToRegister(load->index()), LSL, 3)),
-                        ToRegister(load->output()));
-        }
-    }
-    JS_ASSERT(!load->mir()->needsHoleCheck());
-    return true;
-}
-
-void
-CodeGeneratorARM::storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
-                                    Register elements, const LAllocation *index)
-{
-    if (index->isConstant()) {
-        Address dest = Address(elements, ToInt32(index) * sizeof(Value));
-        if (valueType == MIRType_Double) {
-            masm.ma_vstr(ToFloatRegister(value), Operand(dest));
-            return;
-        }
-
-        // Store the type tag if needed.
-        if (valueType != elementType)
-            masm.storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), dest);
-
-        // Store the payload.
-        if (value->isConstant())
-            masm.storePayload(*value->toConstant(), dest);
-        else
-            masm.storePayload(ToRegister(value), dest);
-    } else {
-        Register indexReg = ToRegister(index);
-        if (valueType == MIRType_Double) {
-            masm.ma_vstr(ToFloatRegister(value), elements, indexReg);
-            return;
-        }
-
-        // Store the type tag if needed.
-        if (valueType != elementType)
-            masm.storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), elements, indexReg);
-
-        // Store the payload.
-        if (value->isConstant())
-            masm.storePayload(*value->toConstant(), elements, indexReg);
-        else
-            masm.storePayload(ToRegister(value), elements, indexReg);
-    }
-}
-
-bool
 CodeGeneratorARM::visitGuardShape(LGuardShape *guard)
 {
     Register obj = ToRegister(guard->input());
     Register tmp = ToRegister(guard->tempInt());
 
     masm.ma_ldr(DTRAddr(obj, DtrOffImm(JSObject::offsetOfShape())), tmp);
     masm.ma_cmp(tmp, ImmGCPtr(guard->mir()->shape()));
 
@@ -1888,50 +1762,16 @@ CodeGeneratorARM::visitGuardClass(LGuard
     masm.loadObjClass(obj, tmp);
     masm.ma_cmp(tmp, Imm32((uint32_t)guard->mir()->getClass()));
     if (!bailoutIf(Assembler::NotEqual, guard->snapshot()))
         return false;
     return true;
 }
 
 bool
-CodeGeneratorARM::visitImplicitThis(LImplicitThis *lir)
-{
-    Register callee = ToRegister(lir->callee());
-    const ValueOperand out = ToOutValue(lir);
-
-    // The implicit |this| is always |undefined| if the function's environment
-    // is the current global.
-    masm.ma_ldr(DTRAddr(callee, DtrOffImm(JSFunction::offsetOfEnvironment())), out.typeReg());
-    masm.ma_cmp(out.typeReg(), ImmGCPtr(&gen->info().script()->global()));
-
-    // TODO: OOL stub path.
-    if (!bailoutIf(Assembler::NotEqual, lir->snapshot()))
-        return false;
-
-    masm.moveValue(UndefinedValue(), out);
-    return true;
-}
-
-bool
-CodeGeneratorARM::visitInterruptCheck(LInterruptCheck *lir)
-{
-    OutOfLineCode *ool = oolCallVM(InterruptCheckInfo, lir, (ArgList()), StoreNothing());
-    if (!ool)
-        return false;
-
-    void *interrupt = (void*)GetIonContext()->runtime->addressOfInterrupt();
-    masm.load32(AbsoluteAddress(interrupt), lr);
-    masm.ma_cmp(lr, Imm32(0));
-    masm.ma_b(ool->entry(), Assembler::NonZero);
-    masm.bind(ool->rejoin());
-    return true;
-}
-
-bool
 CodeGeneratorARM::generateInvalidateEpilogue()
 {
     // Ensure that there is enough space in the buffer for the OsiPoint
     // patching to occur. Otherwise, we could overwrite the invalidation
     // epilogue.
     for (size_t i = 0; i < sizeof(void *); i+= Assembler::nopSize())
         masm.nop();
 
--- a/js/src/jit/arm/CodeGenerator-arm.h
+++ b/js/src/jit/arm/CodeGenerator-arm.h
@@ -159,47 +159,35 @@ class CodeGeneratorARM : public CodeGene
   protected:
     ValueOperand ToValue(LInstruction *ins, size_t pos);
     ValueOperand ToOutValue(LInstruction *ins);
     ValueOperand ToTempValue(LInstruction *ins, size_t pos);
 
     // Functions for LTestVAndBranch.
     Register splitTagForTest(const ValueOperand &value);
 
-    void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
-                           Register elements, const LAllocation *index);
-
     bool divICommon(MDiv *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot,
                     Label &done);
     bool modICommon(MMod *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot,
                     Label &done);
 
   public:
     CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
 
   public:
     bool visitBox(LBox *box);
     bool visitBoxFloatingPoint(LBoxFloatingPoint *box);
     bool visitUnbox(LUnbox *unbox);
     bool visitValue(LValue *value);
     bool visitDouble(LDouble *ins);
     bool visitFloat32(LFloat32 *ins);
 
-    bool visitLoadSlotV(LLoadSlotV *load);
-    bool visitLoadSlotT(LLoadSlotT *load);
-    bool visitStoreSlotT(LStoreSlotT *load);
-
-    bool visitLoadElementT(LLoadElementT *load);
-
     bool visitGuardShape(LGuardShape *guard);
     bool visitGuardObjectType(LGuardObjectType *guard);
     bool visitGuardClass(LGuardClass *guard);
-    bool visitImplicitThis(LImplicitThis *lir);
-
-    bool visitInterruptCheck(LInterruptCheck *lir);
 
     bool visitNegI(LNegI *lir);
     bool visitNegD(LNegD *lir);
     bool visitNegF(LNegF *lir);
     bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins);
     bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins);
     bool visitAsmJSLoadHeap(LAsmJSLoadHeap *ins);
     bool visitAsmJSStoreHeap(LAsmJSStoreHeap *ins);
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -3277,16 +3277,45 @@ MacroAssemblerARMCompat::extractTag(cons
 
 Register
 MacroAssemblerARMCompat::extractTag(const BaseIndex &address, Register scratch)
 {
     ma_alu(address.base, lsl(address.index, address.scale), scratch, op_add, NoSetCond);
     return extractTag(Address(scratch, address.offset), scratch);
 }
 
+template <typename T>
+void
+MacroAssemblerARMCompat::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T &dest,
+                                           MIRType slotType)
+{
+    if (valueType == MIRType_Double) {
+        storeDouble(value.reg().typedReg().fpu(), dest);
+        return;
+    }
+
+    // Store the type tag if needed.
+    if (valueType != slotType)
+        storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), dest);
+
+    // Store the payload.
+    if (value.constant())
+        storePayload(value.value(), dest);
+    else
+        storePayload(value.reg().typedReg().gpr(), dest);
+}
+
+template void
+MacroAssemblerARMCompat::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const Address &dest,
+                                           MIRType slotType);
+
+template void
+MacroAssemblerARMCompat::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const BaseIndex &dest,
+                                           MIRType slotType);
+
 void
 MacroAssemblerARMCompat::moveValue(const Value &val, Register type, Register data)
 {
     jsval_layout jv = JSVAL_TO_IMPL(val);
     ma_mov(Imm32(jv.s.tag), type);
     if (val.isMarkable())
         ma_mov(ImmGCPtr(reinterpret_cast<gc::Cell *>(val.toGCThing())), data);
     else
@@ -3463,56 +3492,73 @@ MacroAssemblerARMCompat::storePayload(Re
         ma_str(src, ToPayload(dest));
         return;
     }
     MOZ_ASSUME_UNREACHABLE("why do we do all of these things?");
 
 }
 
 void
-MacroAssemblerARMCompat::storePayload(const Value &val, Register base, Register index, int32_t shift)
-{
+MacroAssemblerARMCompat::storePayload(const Value &val, const BaseIndex &dest)
+{
+    unsigned shift = ScaleToShift(dest.scale);
+    MOZ_ASSERT(dest.offset == 0);
+
     jsval_layout jv = JSVAL_TO_IMPL(val);
     if (val.isMarkable())
         ma_mov(ImmGCPtr((gc::Cell *)jv.s.payload.ptr), ScratchRegister);
     else
         ma_mov(Imm32(jv.s.payload.i32), ScratchRegister);
-    JS_STATIC_ASSERT(NUNBOX32_PAYLOAD_OFFSET == 0);
-    // If NUNBOX32_PAYLOAD_OFFSET is not zero, the memory operand [base + index << shift + imm]
-    // cannot be encoded into a single instruction, and cannot be integrated into the as_dtr call.
-    as_dtr(IsStore, 32, Offset, ScratchRegister, DTRAddr(base, DtrRegImmShift(index, LSL, shift)));
-}
-void
-MacroAssemblerARMCompat::storePayload(Register src, Register base, Register index, int32_t shift)
-{
-    JS_ASSERT((shift < 32) && (shift >= 0));
+
     // If NUNBOX32_PAYLOAD_OFFSET is not zero, the memory operand [base + index << shift + imm]
     // cannot be encoded into a single instruction, and cannot be integrated into the as_dtr call.
     JS_STATIC_ASSERT(NUNBOX32_PAYLOAD_OFFSET == 0);
+
+    as_dtr(IsStore, 32, Offset, ScratchRegister,
+           DTRAddr(dest.base, DtrRegImmShift(dest.index, LSL, shift)));
+}
+
+void
+MacroAssemblerARMCompat::storePayload(Register src, const BaseIndex &dest)
+{
+    unsigned shift = ScaleToShift(dest.scale);
+    MOZ_ASSERT(shift < 32 && shift >= 0);
+    MOZ_ASSERT(dest.offset == 0);
+
+    // If NUNBOX32_PAYLOAD_OFFSET is not zero, the memory operand [base + index << shift + imm]
+    // cannot be encoded into a single instruction, and cannot be integrated into the as_dtr call.
+    JS_STATIC_ASSERT(NUNBOX32_PAYLOAD_OFFSET == 0);
+
     // Technically, shift > -32 can be handle by changing LSL to ASR, but should never come up,
     // and this is one less code path to get wrong.
-    as_dtr(IsStore, 32, Offset, src, DTRAddr(base, DtrRegImmShift(index, LSL, shift)));
+    as_dtr(IsStore, 32, Offset, src, DTRAddr(dest.base, DtrRegImmShift(dest.index, LSL, shift)));
 }
 
 void
 MacroAssemblerARMCompat::storeTypeTag(ImmTag tag, Operand dest) {
     if (dest.getTag() == Operand::MEM) {
         ma_mov(tag, secondScratchReg_);
         ma_str(secondScratchReg_, ToType(dest));
         return;
     }
 
     MOZ_ASSUME_UNREACHABLE("why do we do all of these things?");
 
 }
 
 void
-MacroAssemblerARMCompat::storeTypeTag(ImmTag tag, Register base, Register index, int32_t shift) {
-    JS_ASSERT(base != ScratchRegister);
-    JS_ASSERT(index != ScratchRegister);
+MacroAssemblerARMCompat::storeTypeTag(ImmTag tag, const BaseIndex &dest)
+{
+    Register base = dest.base;
+    Register index = dest.index;
+    unsigned shift = ScaleToShift(dest.scale);
+    MOZ_ASSERT(dest.offset == 0);
+    MOZ_ASSERT(base != ScratchRegister);
+    MOZ_ASSERT(index != ScratchRegister);
+
     // A value needs to be store a value int base + index << shift + 4.
     // Arm cannot handle this in a single operand, so a temp register is required.
     // However, the scratch register is presently in use to hold the immediate that
     // is being stored into said memory location. Work around this by modifying
     // the base so the valid [base + index << shift] format can be used, then
     // restore it.
     ma_add(base, Imm32(NUNBOX32_TYPE_OFFSET), base);
     ma_mov(tag, ScratchRegister);
--- a/js/src/jit/arm/MacroAssembler-arm.h
+++ b/js/src/jit/arm/MacroAssembler-arm.h
@@ -1086,16 +1086,20 @@ class MacroAssemblerARMCompat : public M
 
     void loadUnboxedValue(BaseIndex address, MIRType type, AnyRegister dest) {
         if (dest.isFloat())
             loadInt32OrDouble(address.base, address.index, dest.fpu(), address.scale);
         else
             load32(address, dest.gpr());
     }
 
+    template <typename T>
+    void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T &dest,
+                           MIRType slotType);
+
     void moveValue(const Value &val, const ValueOperand &dest);
 
     void moveValue(const ValueOperand &src, const ValueOperand &dest) {
         Register s0 = src.typeReg(), d0 = dest.typeReg(),
                  s1 = src.payloadReg(), d1 = dest.payloadReg();
 
         // Either one or both of the source registers could be the same as a
         // destination register.
@@ -1180,20 +1184,20 @@ class MacroAssemblerARMCompat : public M
         framePushed_ += sizeof(Value);
     }
     void Pop(const ValueOperand &val) {
         popValue(val);
         framePushed_ -= sizeof(Value);
     }
     void storePayload(const Value &val, Operand dest);
     void storePayload(Register src, Operand dest);
-    void storePayload(const Value &val, Register base, Register index, int32_t shift = defaultShift);
-    void storePayload(Register src, Register base, Register index, int32_t shift = defaultShift);
+    void storePayload(const Value &val, const BaseIndex &dest);
+    void storePayload(Register src, const BaseIndex &dest);
     void storeTypeTag(ImmTag tag, Operand dest);
-    void storeTypeTag(ImmTag tag, Register base, Register index, int32_t shift = defaultShift);
+    void storeTypeTag(ImmTag tag, const BaseIndex &dest);
 
     void makeFrameDescriptor(Register frameSizeReg, FrameType type) {
         ma_lsl(Imm32(FRAMESIZE_SHIFT), frameSizeReg, frameSizeReg);
         ma_orr(Imm32(type), frameSizeReg);
     }
 
     void handleFailureWithHandler(void *handler);
     void handleFailureWithHandlerTail();
--- a/js/src/jit/mips/CodeGenerator-mips.cpp
+++ b/js/src/jit/mips/CodeGenerator-mips.cpp
@@ -1750,142 +1750,16 @@ CodeGeneratorMIPS::visitNotF(LNotF *ins)
     masm.bind(&falsey);
     masm.move32(Imm32(1), dest);
 
     masm.bind(&done);
     return true;
 }
 
 bool
-CodeGeneratorMIPS::visitLoadSlotV(LLoadSlotV *load)
-{
-    const ValueOperand out = ToOutValue(load);
-    Register base = ToRegister(load->input());
-    int32_t offset = load->mir()->slot() * sizeof(js::Value);
-
-    masm.loadValue(Address(base, offset), out);
-    return true;
-}
-
-bool
-CodeGeneratorMIPS::visitLoadSlotT(LLoadSlotT *load)
-{
-    Register base = ToRegister(load->input());
-    int32_t offset = load->mir()->slot() * sizeof(js::Value);
-
-    if (load->mir()->type() == MIRType_Double)
-        masm.loadInt32OrDouble(Address(base, offset), ToFloatRegister(load->output()));
-    else
-        masm.load32(Address(base, offset + NUNBOX32_PAYLOAD_OFFSET), ToRegister(load->output()));
-    return true;
-}
-
-bool
-CodeGeneratorMIPS::visitStoreSlotT(LStoreSlotT *store)
-{
-    Register base = ToRegister(store->slots());
-    int32_t offset = store->mir()->slot() * sizeof(js::Value);
-
-    const LAllocation *value = store->value();
-    MIRType valueType = store->mir()->value()->type();
-
-    if (store->mir()->needsBarrier())
-        emitPreBarrier(Address(base, offset), store->mir()->slotType());
-
-    if (valueType == MIRType_Double) {
-        masm.storeDouble(ToFloatRegister(value), Address(base, offset));
-        return true;
-    }
-
-    // Store the type tag if needed.
-    if (valueType != store->mir()->slotType())
-        masm.storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), Address(base, offset));
-
-    // Store the payload.
-    if (value->isConstant())
-        masm.storePayload(*value->toConstant(), Address(base, offset));
-    else
-        masm.storePayload(ToRegister(value), Address(base, offset));
-
-    return true;
-}
-
-bool
-CodeGeneratorMIPS::visitLoadElementT(LLoadElementT *load)
-{
-    Register base = ToRegister(load->elements());
-    if (load->mir()->type() == MIRType_Double) {
-        FloatRegister fpreg = ToFloatRegister(load->output());
-        if (load->index()->isConstant()) {
-            Address source(base, ToInt32(load->index()) * sizeof(Value));
-            if (load->mir()->loadDoubles())
-                masm.loadDouble(source, fpreg);
-            else
-                masm.loadInt32OrDouble(source, fpreg);
-        } else {
-            Register index = ToRegister(load->index());
-            if (load->mir()->loadDoubles())
-                masm.loadDouble(BaseIndex(base, index, TimesEight), fpreg);
-            else
-                masm.loadInt32OrDouble(base, index, fpreg);
-        }
-    } else {
-        if (load->index()->isConstant()) {
-            Address source(base, ToInt32(load->index()) * sizeof(Value));
-            masm.load32(source, ToRegister(load->output()));
-        } else {
-            BaseIndex source(base, ToRegister(load->index()), TimesEight);
-            masm.load32(source, ToRegister(load->output()));
-        }
-    }
-    MOZ_ASSERT(!load->mir()->needsHoleCheck());
-    return true;
-}
-
-void
-CodeGeneratorMIPS::storeElementTyped(const LAllocation *value, MIRType valueType,
-                                     MIRType elementType, Register elements,
-                                     const LAllocation *index)
-{
-    if (index->isConstant()) {
-        Address dest = Address(elements, ToInt32(index) * sizeof(Value));
-        if (valueType == MIRType_Double) {
-            masm.storeDouble(ToFloatRegister(value), Address(dest.base, dest.offset));
-            return;
-        }
-
-        // Store the type tag if needed.
-        if (valueType != elementType)
-            masm.storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), dest);
-
-        // Store the payload.
-        if (value->isConstant())
-            masm.storePayload(*value->toConstant(), dest);
-        else
-            masm.storePayload(ToRegister(value), dest);
-    } else {
-        Register indexReg = ToRegister(index);
-        if (valueType == MIRType_Double) {
-            masm.storeDouble(ToFloatRegister(value), BaseIndex(elements, indexReg, TimesEight));
-            return;
-        }
-
-        // Store the type tag if needed.
-        if (valueType != elementType)
-            masm.storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), elements, indexReg);
-
-        // Store the payload.
-        if (value->isConstant())
-            masm.storePayload(*value->toConstant(), elements, indexReg);
-        else
-            masm.storePayload(ToRegister(value), elements, indexReg);
-    }
-}
-
-bool
 CodeGeneratorMIPS::visitGuardShape(LGuardShape *guard)
 {
     Register obj = ToRegister(guard->input());
     Register tmp = ToRegister(guard->tempInt());
 
     masm.loadPtr(Address(obj, JSObject::offsetOfShape()), tmp);
     return bailoutCmpPtr(Assembler::NotEqual, tmp, ImmGCPtr(guard->mir()->shape()),
                          guard->snapshot());
@@ -1913,49 +1787,16 @@ CodeGeneratorMIPS::visitGuardClass(LGuar
     masm.loadObjClass(obj, tmp);
     if (!bailoutCmpPtr(Assembler::NotEqual, tmp, Imm32((uint32_t)guard->mir()->getClass()),
                        guard->snapshot()))
         return false;
     return true;
 }
 
 bool
-CodeGeneratorMIPS::visitImplicitThis(LImplicitThis *lir)
-{
-    Register callee = ToRegister(lir->callee());
-    const ValueOperand out = ToOutValue(lir);
-
-    // The implicit |this| is always |undefined| if the function's environment
-    // is the current global.
-    masm.loadPtr(Address(callee, JSFunction::offsetOfEnvironment()), out.typeReg());
-    GlobalObject *global = &gen->info().script()->global();
-
-    // TODO: OOL stub path.
-    if (!bailoutCmpPtr(Assembler::NotEqual, out.typeReg(), ImmGCPtr(global), lir->snapshot()))
-        return false;
-
-    masm.moveValue(UndefinedValue(), out);
-    return true;
-}
-
-bool
-CodeGeneratorMIPS::visitInterruptCheck(LInterruptCheck *lir)
-{
-    OutOfLineCode *ool = oolCallVM(InterruptCheckInfo, lir, (ArgList()), StoreNothing());
-    if (!ool)
-        return false;
-
-    masm.branch32(Assembler::NotEqual,
-                  AbsoluteAddress(GetIonContext()->runtime->addressOfInterrupt()), Imm32(0),
-                  ool->entry());
-    masm.bind(ool->rejoin());
-    return true;
-}
-
-bool
 CodeGeneratorMIPS::generateInvalidateEpilogue()
 {
     // Ensure that there is enough space in the buffer for the OsiPoint
     // patching to occur. Otherwise, we could overwrite the invalidation
     // epilogue.
     for (size_t i = 0; i < sizeof(void *); i += Assembler::nopSize())
         masm.nop();
 
--- a/js/src/jit/mips/CodeGenerator-mips.h
+++ b/js/src/jit/mips/CodeGenerator-mips.h
@@ -224,42 +224,30 @@ class CodeGeneratorMIPS : public CodeGen
   protected:
     ValueOperand ToValue(LInstruction *ins, size_t pos);
     ValueOperand ToOutValue(LInstruction *ins);
     ValueOperand ToTempValue(LInstruction *ins, size_t pos);
 
     // Functions for LTestVAndBranch.
     Register splitTagForTest(const ValueOperand &value);
 
-    void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
-                           Register elements, const LAllocation *index);
-
   public:
     CodeGeneratorMIPS(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
 
   public:
     bool visitBox(LBox *box);
     bool visitBoxFloatingPoint(LBoxFloatingPoint *box);
     bool visitUnbox(LUnbox *unbox);
     bool visitValue(LValue *value);
     bool visitDouble(LDouble *ins);
     bool visitFloat32(LFloat32 *ins);
 
-    bool visitLoadSlotV(LLoadSlotV *load);
-    bool visitLoadSlotT(LLoadSlotT *load);
-    bool visitStoreSlotT(LStoreSlotT *load);
-
-    bool visitLoadElementT(LLoadElementT *load);
-
     bool visitGuardShape(LGuardShape *guard);
     bool visitGuardObjectType(LGuardObjectType *guard);
     bool visitGuardClass(LGuardClass *guard);
-    bool visitImplicitThis(LImplicitThis *lir);
-
-    bool visitInterruptCheck(LInterruptCheck *lir);
 
     bool visitNegI(LNegI *lir);
     bool visitNegD(LNegD *lir);
     bool visitNegF(LNegF *lir);
     bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins);
     bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins);
     bool visitAsmJSLoadHeap(LAsmJSLoadHeap *ins);
     bool visitAsmJSStoreHeap(LAsmJSStoreHeap *ins);
--- a/js/src/jit/shared/CodeGenerator-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-shared.cpp
@@ -940,19 +940,16 @@ CodeGeneratorShared::callTraceLIR(uint32
     masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, TraceLIR));
 
     masm.freeStack(sizeof(IonLIRTraceData));
     masm.PopRegsInMask(RegisterSet::Volatile());
 
     return true;
 }
 
-typedef bool (*InterruptCheckFn)(JSContext *);
-const VMFunction InterruptCheckInfo = FunctionInfo<InterruptCheckFn>(InterruptCheck);
-
 Label *
 CodeGeneratorShared::labelForBackedgeWithImplicitCheck(MBasicBlock *mir)
 {
     // If this is a loop backedge to a loop header with an implicit interrupt
     // check, use a patchable jump. Skip this search if compiling without a
     // script for asm.js, as there will be no interrupt check instruction.
     // Due to critical edge unsplitting there may no longer be unique loop
     // backedges, so just look for any edge going to an earlier block in RPO.
--- a/js/src/jit/shared/CodeGenerator-shared.h
+++ b/js/src/jit/shared/CodeGenerator-shared.h
@@ -807,14 +807,12 @@ class OutOfLinePropagateAbortPar : publi
       : lir_(lir)
     { }
 
     LInstruction *lir() { return lir_; }
 
     bool generate(CodeGeneratorShared *codegen);
 };
 
-extern const VMFunction InterruptCheckInfo;
-
 } // namespace jit
 } // namespace js
 
 #endif /* jit_shared_CodeGenerator_shared_h */
--- a/js/src/jit/shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.cpp
@@ -2011,24 +2011,16 @@ CodeGeneratorX86Shared::visitEffectiveAd
     const MEffectiveAddress *mir = ins->mir();
     Register base = ToRegister(ins->base());
     Register index = ToRegister(ins->index());
     Register output = ToRegister(ins->output());
     masm.leal(Operand(base, index, mir->scale(), mir->displacement()), output);
     return true;
 }
 
-Operand
-CodeGeneratorX86Shared::createArrayElementOperand(Register elements, const LAllocation *index)
-{
-    if (index->isConstant())
-        return Operand(elements, ToInt32(index) * sizeof(js::Value));
-
-    return Operand(elements, ToRegister(index), TimesEight);
-}
 bool
 CodeGeneratorX86Shared::generateInvalidateEpilogue()
 {
     // Ensure that there is enough space in the buffer for the OsiPoint
     // patching to occur. Otherwise, we could overwrite the invalidation
     // epilogue.
     for (size_t i = 0; i < sizeof(void *); i+= Assembler::nopSize())
         masm.nop();
--- a/js/src/jit/shared/CodeGenerator-x86-shared.h
+++ b/js/src/jit/shared/CodeGenerator-x86-shared.h
@@ -92,18 +92,16 @@ class CodeGeneratorX86Shared : public Co
     }
 
   protected:
     bool generatePrologue();
     bool generateAsmJSPrologue(Label *stackOverflowLabe);
     bool generateEpilogue();
     bool generateOutOfLineCode();
 
-    Operand createArrayElementOperand(Register elements, const LAllocation *index);
-
     void emitCompare(MCompare::CompareType type, const LAllocation *left, const LAllocation *right);
 
     // Emits a branch that directs control flow to the true block if |cond| is
     // true, and the false block if |cond| is false.
     void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse,
                     Assembler::NaNCond ifNaN = Assembler::NaN_HandledByCond);
     void emitBranch(Assembler::DoubleCondition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse);
 
--- a/js/src/jit/x64/CodeGenerator-x64.cpp
+++ b/js/src/jit/x64/CodeGenerator-x64.cpp
@@ -129,170 +129,16 @@ CodeGeneratorX64::visitUnbox(LUnbox *unb
       default:
         MOZ_ASSUME_UNREACHABLE("Given MIRType cannot be unboxed.");
     }
 
     return true;
 }
 
 bool
-CodeGeneratorX64::visitLoadSlotV(LLoadSlotV *load)
-{
-    ValueOperand dest = ToOutValue(load);
-    Register base = ToRegister(load->input());
-    int32_t offset = load->mir()->slot() * sizeof(js::Value);
-
-    masm.loadValue(Address(base, offset), dest);
-    return true;
-}
-
-void
-CodeGeneratorX64::loadUnboxedValue(Operand source, MIRType type, const LDefinition *dest)
-{
-    switch (type) {
-      case MIRType_Double:
-        masm.loadInt32OrDouble(source, ToFloatRegister(dest));
-        break;
-
-      case MIRType_Object:
-      case MIRType_String:
-        masm.unboxObject(source, ToRegister(dest));
-        break;
-
-      case MIRType_Int32:
-      case MIRType_Boolean:
-        masm.movl(source, ToRegister(dest));
-        break;
-
-      default:
-        MOZ_ASSUME_UNREACHABLE("unexpected type");
-    }
-}
-
-bool
-CodeGeneratorX64::visitLoadSlotT(LLoadSlotT *load)
-{
-    Register base = ToRegister(load->input());
-    int32_t offset = load->mir()->slot() * sizeof(js::Value);
-
-    loadUnboxedValue(Operand(base, offset), load->mir()->type(), load->output());
-
-    return true;
-}
-
-void
-CodeGeneratorX64::storeUnboxedValue(const LAllocation *value, MIRType valueType,
-                                    Operand dest, MIRType slotType)
-{
-    if (valueType == MIRType_Double) {
-        masm.storeDouble(ToFloatRegister(value), dest);
-        return;
-    }
-
-    // For known integers and booleans, we can just store the unboxed value if
-    // the slot has the same type.
-    if ((valueType == MIRType_Int32 || valueType == MIRType_Boolean) && slotType == valueType) {
-        if (value->isConstant()) {
-            Value val = *value->toConstant();
-            if (valueType == MIRType_Int32)
-                masm.movl(Imm32(val.toInt32()), dest);
-            else
-                masm.movl(Imm32(val.toBoolean() ? 1 : 0), dest);
-        } else {
-            masm.movl(ToRegister(value), dest);
-        }
-        return;
-    }
-
-    if (value->isConstant()) {
-        masm.moveValue(*value->toConstant(), ScratchReg);
-        masm.movq(ScratchReg, dest);
-    } else {
-        masm.storeValue(ValueTypeFromMIRType(valueType), ToRegister(value), dest);
-    }
-}
-
-bool
-CodeGeneratorX64::visitStoreSlotT(LStoreSlotT *store)
-{
-    Register base = ToRegister(store->slots());
-    int32_t offset = store->mir()->slot() * sizeof(js::Value);
-
-    const LAllocation *value = store->value();
-    MIRType valueType = store->mir()->value()->type();
-    MIRType slotType = store->mir()->slotType();
-
-    if (store->mir()->needsBarrier())
-        emitPreBarrier(Address(base, offset), slotType);
-
-    storeUnboxedValue(value, valueType, Operand(base, offset), slotType);
-    return true;
-}
-
-bool
-CodeGeneratorX64::visitLoadElementT(LLoadElementT *load)
-{
-    Operand source = createArrayElementOperand(ToRegister(load->elements()), load->index());
-
-    if (load->mir()->loadDoubles()) {
-        FloatRegister fpreg = ToFloatRegister(load->output());
-        if (source.kind() == Operand::MEM_REG_DISP)
-            masm.loadDouble(source.toAddress(), fpreg);
-        else
-            masm.loadDouble(source.toBaseIndex(), fpreg);
-    } else {
-        loadUnboxedValue(source, load->mir()->type(), load->output());
-    }
-
-    JS_ASSERT(!load->mir()->needsHoleCheck());
-    return true;
-}
-
-
-void
-CodeGeneratorX64::storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
-                                    Register elements, const LAllocation *index)
-{
-    Operand dest = createArrayElementOperand(elements, index);
-    storeUnboxedValue(value, valueType, dest, elementType);
-}
-
-bool
-CodeGeneratorX64::visitImplicitThis(LImplicitThis *lir)
-{
-    Register callee = ToRegister(lir->callee());
-
-    // The implicit |this| is always |undefined| if the function's environment
-    // is the current global.
-    GlobalObject *global = &gen->info().script()->global();
-    masm.cmpPtr(Operand(callee, JSFunction::offsetOfEnvironment()), ImmGCPtr(global));
-
-    // TODO: OOL stub path.
-    if (!bailoutIf(Assembler::NotEqual, lir->snapshot()))
-        return false;
-
-    masm.moveValue(UndefinedValue(), ToOutValue(lir));
-    return true;
-}
-
-bool
-CodeGeneratorX64::visitInterruptCheck(LInterruptCheck *lir)
-{
-    OutOfLineCode *ool = oolCallVM(InterruptCheckInfo, lir, (ArgList()), StoreNothing());
-    if (!ool)
-        return false;
-
-    masm.branch32(Assembler::NotEqual,
-                  AbsoluteAddress(GetIonContext()->runtime->addressOfInterrupt()), Imm32(0),
-                  ool->entry());
-    masm.bind(ool->rejoin());
-    return true;
-}
-
-bool
 CodeGeneratorX64::visitCompareB(LCompareB *lir)
 {
     MCompare *mir = lir->mir();
 
     const ValueOperand lhs = ToValue(lir, LCompareB::Lhs);
     const LAllocation *rhs = lir->rhs();
     const Register output = ToRegister(lir->output());
 
--- a/js/src/jit/x64/CodeGenerator-x64.h
+++ b/js/src/jit/x64/CodeGenerator-x64.h
@@ -18,37 +18,26 @@ class CodeGeneratorX64 : public CodeGene
         return this;
     }
 
   protected:
     ValueOperand ToValue(LInstruction *ins, size_t pos);
     ValueOperand ToOutValue(LInstruction *ins);
     ValueOperand ToTempValue(LInstruction *ins, size_t pos);
 
-
-    void loadUnboxedValue(Operand source, MIRType type, const LDefinition *dest);
     void storeUnboxedValue(const LAllocation *value, MIRType valueType,
                            Operand dest, MIRType slotType);
 
-    void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
-                           Register elements, const LAllocation *index);
-
   public:
     CodeGeneratorX64(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
 
   public:
     bool visitValue(LValue *value);
     bool visitBox(LBox *box);
     bool visitUnbox(LUnbox *unbox);
-    bool visitLoadSlotV(LLoadSlotV *ins);
-    bool visitLoadSlotT(LLoadSlotT *load);
-    bool visitStoreSlotT(LStoreSlotT *store);
-    bool visitLoadElementT(LLoadElementT *load);
-    bool visitImplicitThis(LImplicitThis *lir);
-    bool visitInterruptCheck(LInterruptCheck *lir);
     bool visitCompareB(LCompareB *lir);
     bool visitCompareBAndBranch(LCompareBAndBranch *lir);
     bool visitCompareV(LCompareV *lir);
     bool visitCompareVAndBranch(LCompareVAndBranch *lir);
     bool visitTruncateDToInt32(LTruncateDToInt32 *ins);
     bool visitTruncateFToInt32(LTruncateFToInt32 *ins);
     bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins);
     bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins);
--- a/js/src/jit/x64/MacroAssembler-x64.cpp
+++ b/js/src/jit/x64/MacroAssembler-x64.cpp
@@ -362,16 +362,55 @@ MacroAssemblerX64::handleFailureWithHand
     // If we are bailing out to baseline to handle an exception, jump to
     // the bailout tail stub.
     bind(&bailout);
     loadPtr(Address(esp, offsetof(ResumeFromException, bailoutInfo)), r9);
     mov(ImmWord(BAILOUT_RETURN_OK), rax);
     jmp(Operand(rsp, offsetof(ResumeFromException, target)));
 }
 
+template <typename T>
+void
+MacroAssemblerX64::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T &dest,
+                                     MIRType slotType)
+{
+    if (valueType == MIRType_Double) {
+        storeDouble(value.reg().typedReg().fpu(), dest);
+        return;
+    }
+
+    // For known integers and booleans, we can just store the unboxed value if
+    // the slot has the same type.
+    if ((valueType == MIRType_Int32 || valueType == MIRType_Boolean) && slotType == valueType) {
+        if (value.constant()) {
+            Value val = value.value();
+            if (valueType == MIRType_Int32)
+                store32(Imm32(val.toInt32()), dest);
+            else
+                store32(Imm32(val.toBoolean() ? 1 : 0), dest);
+        } else {
+            store32(value.reg().typedReg().gpr(), dest);
+        }
+        return;
+    }
+
+    if (value.constant())
+        storeValue(value.value(), dest);
+    else
+        storeValue(ValueTypeFromMIRType(valueType), value.reg().typedReg().gpr(), dest);
+}
+
+template void
+MacroAssemblerX64::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const Address &dest,
+                                     MIRType slotType);
+
+template void
+MacroAssemblerX64::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const BaseIndex &dest,
+                                     MIRType slotType);
+
 #ifdef JSGC_GENERATIONAL
 
 void
 MacroAssemblerX64::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label)
 {
     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
     JS_ASSERT(ptr != temp);
     JS_ASSERT(ptr != ScratchReg);
--- a/js/src/jit/x64/MacroAssembler-x64.h
+++ b/js/src/jit/x64/MacroAssembler-x64.h
@@ -1232,16 +1232,19 @@ class MacroAssemblerX64 : public MacroAs
         if (dest.isFloat())
             loadInt32OrDouble(Operand(src), dest.fpu());
         else if (type == MIRType_Int32 || type == MIRType_Boolean)
             movl(Operand(src), dest.gpr());
         else
             unboxNonDouble(Operand(src), dest.gpr());
     }
 
+    template <typename T>
+    void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T &dest, MIRType slotType);
+
     void loadInstructionPointerAfterCall(Register dest) {
         loadPtr(Address(StackPointer, 0x0), dest);
     }
 
     void convertUInt32ToDouble(Register src, FloatRegister dest) {
         cvtsq2sd(src, dest);
     }
 
--- a/js/src/jit/x86/CodeGenerator-x86.cpp
+++ b/js/src/jit/x86/CodeGenerator-x86.cpp
@@ -133,152 +133,16 @@ CodeGeneratorX86::visitUnbox(LUnbox *unb
         masm.cmpl(ToOperand(unbox->type()), Imm32(MIRTypeToTag(mir->type())));
         if (!bailoutIf(Assembler::NotEqual, unbox->snapshot()))
             return false;
     }
     return true;
 }
 
 bool
-CodeGeneratorX86::visitLoadSlotV(LLoadSlotV *load)
-{
-    const ValueOperand out = ToOutValue(load);
-    Register base = ToRegister(load->input());
-    int32_t offset = load->mir()->slot() * sizeof(js::Value);
-
-    masm.loadValue(Address(base, offset), out);
-    return true;
-}
-
-bool
-CodeGeneratorX86::visitLoadSlotT(LLoadSlotT *load)
-{
-    Register base = ToRegister(load->input());
-    int32_t offset = load->mir()->slot() * sizeof(js::Value);
-
-    if (load->mir()->type() == MIRType_Double)
-        masm.loadInt32OrDouble(Operand(base, offset), ToFloatRegister(load->output()));
-    else
-        masm.load32(Address(base, offset + NUNBOX32_PAYLOAD_OFFSET), ToRegister(load->output()));
-    return true;
-}
-
-bool
-CodeGeneratorX86::visitStoreSlotT(LStoreSlotT *store)
-{
-    Register base = ToRegister(store->slots());
-    int32_t offset = store->mir()->slot() * sizeof(js::Value);
-
-    const LAllocation *value = store->value();
-    MIRType valueType = store->mir()->value()->type();
-
-    if (store->mir()->needsBarrier())
-        emitPreBarrier(Address(base, offset), store->mir()->slotType());
-
-    if (valueType == MIRType_Double) {
-        masm.storeDouble(ToFloatRegister(value), Operand(base, offset));
-        return true;
-    }
-
-    // Store the type tag if needed.
-    if (valueType != store->mir()->slotType())
-        masm.storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), Operand(base, offset));
-
-    // Store the payload.
-    if (value->isConstant())
-        masm.storePayload(*value->toConstant(), Operand(base, offset));
-    else
-        masm.storePayload(ToRegister(value), Operand(base, offset));
-
-    return true;
-}
-
-bool
-CodeGeneratorX86::visitLoadElementT(LLoadElementT *load)
-{
-    Operand source = createArrayElementOperand(ToRegister(load->elements()), load->index());
-
-    if (load->mir()->needsHoleCheck()) {
-        Assembler::Condition cond = masm.testMagic(Assembler::Equal, source);
-        if (!bailoutIf(cond, load->snapshot()))
-            return false;
-    }
-
-    if (load->mir()->type() == MIRType_Double) {
-        FloatRegister fpreg = ToFloatRegister(load->output());
-        if (load->mir()->loadDoubles()) {
-            if (source.kind() == Operand::MEM_REG_DISP)
-                masm.loadDouble(source.toAddress(), fpreg);
-            else
-                masm.loadDouble(source.toBaseIndex(), fpreg);
-        } else {
-            masm.loadInt32OrDouble(source, fpreg);
-        }
-    } else {
-        masm.movl(masm.ToPayload(source), ToRegister(load->output()));
-    }
-
-    return true;
-}
-
-void
-CodeGeneratorX86::storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
-                                    Register elements, const LAllocation *index)
-{
-    Operand dest = createArrayElementOperand(elements, index);
-
-    if (valueType == MIRType_Double) {
-        masm.storeDouble(ToFloatRegister(value), dest);
-        return;
-    }
-
-    // Store the type tag if needed.
-    if (valueType != elementType)
-        masm.storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), dest);
-
-    // Store the payload.
-    if (value->isConstant())
-        masm.storePayload(*value->toConstant(), dest);
-    else
-        masm.storePayload(ToRegister(value), dest);
-}
-
-bool
-CodeGeneratorX86::visitImplicitThis(LImplicitThis *lir)
-{
-    Register callee = ToRegister(lir->callee());
-    const ValueOperand out = ToOutValue(lir);
-
-    // The implicit |this| is always |undefined| if the function's environment
-    // is the current global.
-    GlobalObject *global = &gen->info().script()->global();
-    masm.cmpPtr(Operand(callee, JSFunction::offsetOfEnvironment()), ImmGCPtr(global));
-
-    // TODO: OOL stub path.
-    if (!bailoutIf(Assembler::NotEqual, lir->snapshot()))
-        return false;
-
-    masm.moveValue(UndefinedValue(), out);
-    return true;
-}
-
-bool
-CodeGeneratorX86::visitInterruptCheck(LInterruptCheck *lir)
-{
-    OutOfLineCode *ool = oolCallVM(InterruptCheckInfo, lir, (ArgList()), StoreNothing());
-    if (!ool)
-        return false;
-
-    masm.cmpl(Operand(AbsoluteAddress(GetIonContext()->runtime->addressOfInterrupt())), Imm32(0));
-    masm.j(Assembler::NonZero, ool->entry());
-    masm.bind(ool->rejoin());
-    return true;
-}
-
-bool
 CodeGeneratorX86::visitCompareB(LCompareB *lir)
 {
     MCompare *mir = lir->mir();
 
     const ValueOperand lhs = ToValue(lir, LCompareB::Lhs);
     const LAllocation *rhs = lir->rhs();
     const Register output = ToRegister(lir->output());
 
--- a/js/src/jit/x86/CodeGenerator-x86.h
+++ b/js/src/jit/x86/CodeGenerator-x86.h
@@ -36,33 +36,24 @@ class CodeGeneratorX86 : public CodeGene
     void loadViewTypeElement(ArrayBufferView::ViewType vt, const T &srcAddr,
                                        const LDefinition *out);
     template<typename T>
     bool storeAndNoteViewTypeElement(ArrayBufferView::ViewType vt, const LAllocation *value,
                               const T &dstAddr);
     template<typename T>
     void storeViewTypeElement(ArrayBufferView::ViewType vt, const LAllocation *value,
                                         const T &dstAddr);
-    void storeElementTyped(const LAllocation *value, MIRType valueType, MIRType elementType,
-                           Register elements, const LAllocation *index);
-
   public:
     CodeGeneratorX86(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
 
   public:
     bool visitBox(LBox *box);
     bool visitBoxFloatingPoint(LBoxFloatingPoint *box);
     bool visitUnbox(LUnbox *unbox);
     bool visitValue(LValue *value);
-    bool visitLoadSlotV(LLoadSlotV *load);
-    bool visitLoadSlotT(LLoadSlotT *load);
-    bool visitStoreSlotT(LStoreSlotT *store);
-    bool visitLoadElementT(LLoadElementT *load);
-    bool visitImplicitThis(LImplicitThis *lir);
-    bool visitInterruptCheck(LInterruptCheck *lir);
     bool visitCompareB(LCompareB *lir);
     bool visitCompareBAndBranch(LCompareBAndBranch *lir);
     bool visitCompareV(LCompareV *lir);
     bool visitCompareVAndBranch(LCompareVAndBranch *lir);
     bool visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir);
     bool visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir);
     bool visitTruncateDToInt32(LTruncateDToInt32 *ins);
     bool visitTruncateFToInt32(LTruncateFToInt32 *ins);
--- a/js/src/jit/x86/MacroAssembler-x86.cpp
+++ b/js/src/jit/x86/MacroAssembler-x86.cpp
@@ -382,16 +382,45 @@ MacroAssemblerX86::branchTestValue(Condi
         JS_ASSERT(cond == NotEqual);
         j(NotEqual, label);
 
         cmpl(value.typeReg(), Imm32(jv.s.tag));
         j(NotEqual, label);
     }
 }
 
+template <typename T>
+void
+MacroAssemblerX86::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T &dest,
+                                     MIRType slotType)
+{
+    if (valueType == MIRType_Double) {
+        storeDouble(value.reg().typedReg().fpu(), dest);
+        return;
+    }
+
+    // Store the type tag if needed.
+    if (valueType != slotType)
+        storeTypeTag(ImmType(ValueTypeFromMIRType(valueType)), Operand(dest));
+
+    // Store the payload.
+    if (value.constant())
+        storePayload(value.value(), Operand(dest));
+    else
+        storePayload(value.reg().typedReg().gpr(), Operand(dest));
+}
+
+template void
+MacroAssemblerX86::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const Address &dest,
+                                     MIRType slotType);
+
+template void
+MacroAssemblerX86::storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const BaseIndex &dest,
+                                     MIRType slotType);
+
 #ifdef JSGC_GENERATIONAL
 
 void
 MacroAssemblerX86::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
                                            Label *label)
 {
     JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
     JS_ASSERT(ptr != temp);
--- a/js/src/jit/x86/MacroAssembler-x86.h
+++ b/js/src/jit/x86/MacroAssembler-x86.h
@@ -973,16 +973,20 @@ class MacroAssemblerX86 : public MacroAs
     template <typename T>
     void loadUnboxedValue(const T &src, MIRType type, AnyRegister dest) {
         if (dest.isFloat())
             loadInt32OrDouble(Operand(src), dest.fpu());
         else
             movl(Operand(src), dest.gpr());
     }
 
+    template <typename T>
+    void storeUnboxedValue(ConstantOrRegister value, MIRType valueType, const T &dest,
+                           MIRType slotType);
+
     void rshiftPtr(Imm32 imm, Register dest) {
         shrl(imm, dest);
     }
     void rshiftPtrArithmetic(Imm32 imm, Register dest) {
         sarl(imm, dest);
     }
     void lshiftPtr(Imm32 imm, Register dest) {
         shll(imm, dest);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -605,17 +605,17 @@ JS_ShutDown(void)
         fprintf(stderr,
                 "WARNING: YOU ARE LEAKING THE WORLD (at least one JSRuntime "
                 "and everything alive inside it, that is) AT JS_ShutDown "
                 "TIME.  FIX THIS!\n");
     }
 #endif
 
 #ifdef JS_THREADSAFE
-    WorkerThreadState().finish();
+    HelperThreadState().finish();
 #endif
 
     PRMJ_NowShutdown();
 
 #if EXPOSE_INTL_API
     u_cleanup();
 #endif // EXPOSE_INTL_API
 
@@ -4727,17 +4727,17 @@ JS::FinishOffThreadScript(JSContext *may
 {
 #ifdef JS_THREADSAFE
     JS_ASSERT(CurrentThreadCanAccessRuntime(rt));
 
     Maybe<AutoLastFrameCheck> lfc;
     if (maybecx)
         lfc.construct(maybecx);
 
-    return WorkerThreadState().finishParseTask(maybecx, rt, token);
+    return HelperThreadState().finishParseTask(maybecx, rt, token);
 #else
     MOZ_ASSUME_UNREACHABLE("Off thread compilation is not available.");
 #endif
 }
 
 JS_PUBLIC_API(JSScript *)
 JS_CompileScript(JSContext *cx, JS::HandleObject obj, const char *ascii,
                  size_t length, const JS::CompileOptions &options)
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -293,35 +293,35 @@ struct ThreadSafeContext : ContextFriend
     bool jitSupportsFloatingPoint() const { return runtime_->jitSupportsFloatingPoint; }
 
     // Thread local data that may be accessed freely.
     DtoaState *dtoaState() {
         return perThreadData->dtoaState;
     }
 };
 
-struct WorkerThread;
+struct HelperThread;
 
 class ExclusiveContext : public ThreadSafeContext
 {
     friend class gc::ArenaLists;
     friend class AutoCompartment;
     friend class AutoLockForExclusiveAccess;
     friend struct StackBaseShape;
     friend void JSScript::initCompartment(ExclusiveContext *cx);
     friend class jit::IonContext;
 
-    // The worker on which this context is running, if this is not a JSContext.
-    WorkerThread *workerThread_;
+    // The thread on which this context is running, if this is not a JSContext.
+    HelperThread *helperThread_;
 
   public:
 
     ExclusiveContext(JSRuntime *rt, PerThreadData *pt, ContextKind kind)
       : ThreadSafeContext(rt, pt, kind),
-        workerThread_(nullptr),
+        helperThread_(nullptr),
         enterCompartmentDepth_(0)
     {}
 
     /*
      * "Entering" a compartment changes cx->compartment (which changes
      * cx->global). Note that this does not push any InterpreterFrame which means
      * that it is possible for cx->fp()->compartment() != cx->compartment.
      * This is not a problem since, in general, most places in the VM cannot
@@ -347,18 +347,18 @@ class ExclusiveContext : public ThreadSa
         return enterCompartmentDepth_;
     }
 #endif
 
     inline void enterCompartment(JSCompartment *c);
     inline void enterNullCompartment();
     inline void leaveCompartment(JSCompartment *oldCompartment);
 
-    void setWorkerThread(WorkerThread *workerThread);
-    WorkerThread *workerThread() const { return workerThread_; }
+    void setHelperThread(HelperThread *helperThread);
+    HelperThread *helperThread() const { return helperThread_; }
 
     // Threads with an ExclusiveContext may freely access any data in their
     // compartment and zone.
     JSCompartment *compartment() const {
         JS_ASSERT_IF(runtime_->isAtomsCompartment(compartment_),
                      runtime_->currentThreadHasExclusiveAccess());
         return compartment_;
     }
@@ -386,17 +386,17 @@ class ExclusiveContext : public ThreadSa
     }
     JSCompartment *atomsCompartment() {
         return runtime_->atomsCompartment();
     }
     ScriptDataTable &scriptDataTable() {
         return runtime_->scriptDataTable();
     }
 
-    // Methods specific to any WorkerThread for the context.
+    // Methods specific to any HelperThread for the context.
     frontend::CompileError &addPendingCompileError();
     void addPendingOverRecursed();
 };
 
 } /* namespace js */
 
 struct JSContext : public js::ExclusiveContext,
                    public mozilla::LinkedListElement<JSContext>
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -979,17 +979,17 @@ class js::gc::AutoMaybeStartBackgroundAl
     }
 
     void tryToStartBackgroundAllocation(JSRuntime *rt) {
         runtime = rt;
     }
 
     ~AutoMaybeStartBackgroundAllocation() {
         if (runtime && !runtime->currentThreadOwnsInterruptLock()) {
-            AutoLockWorkerThreadState workerLock;
+            AutoLockHelperThreadState helperLock;
             AutoLockGC lock(runtime);
             runtime->gc.startBackgroundAllocationIfIdle();
         }
     }
 };
 
 /* The caller must hold the GC lock. */
 Chunk *
@@ -1916,26 +1916,26 @@ ArenaLists::refillFreeList(ThreadSafeCon
 
                 cx->asJSContext()->runtime()->gc.waitBackgroundSweepEnd();
             }
         } else {
 #ifdef JS_THREADSAFE
             /*
              * If we're off the main thread, we try to allocate once and
              * return whatever value we get. If we aren't in a ForkJoin
-             * session (i.e. we are in a worker thread async with the main
+             * session (i.e. we are in a helper thread async with the main
              * thread), we need to first ensure the main thread is not in a GC
              * session.
              */
-            mozilla::Maybe<AutoLockWorkerThreadState> lock;
+            mozilla::Maybe<AutoLockHelperThreadState> lock;
             JSRuntime *rt = zone->runtimeFromAnyThread();
             if (rt->exclusiveThreadsPresent()) {
                 lock.construct();
                 while (rt->isHeapBusy())
-                    WorkerThreadState().wait(GlobalWorkerThreadState::PRODUCER);
+                    HelperThreadState().wait(GlobalHelperThreadState::PRODUCER);
             }
 
             void *thing = cx->allocator()->arenas.allocateFromArenaInline(zone, thingKind,
                                                                           maybeStartBackgroundAllocation);
             if (thing)
                 return thing;
 #else
             MOZ_CRASH();
@@ -2349,17 +2349,17 @@ bool
 GCHelperState::init()
 {
 #ifdef JS_THREADSAFE
     if (!(done = PR_NewCondVar(rt->gc.lock)))
         return false;
 
     backgroundAllocation = (GetCPUCount() >= 2);
 
-    WorkerThreadState().ensureInitialized();
+    HelperThreadState().ensureInitialized();
 #else
     backgroundAllocation = false;
 #endif /* JS_THREADSAFE */
 
     return true;
 }
 
 void
@@ -2397,19 +2397,19 @@ GCHelperState::setState(State state)
 
 void
 GCHelperState::startBackgroundThread(State newState)
 {
 #ifdef JS_THREADSAFE
     JS_ASSERT(!thread && state() == IDLE && newState != IDLE);
     setState(newState);
 
-    if (!WorkerThreadState().gcHelperWorklist().append(this))
+    if (!HelperThreadState().gcHelperWorklist().append(this))
         CrashAtUnhandlableOOM("Could not add to pending GC helpers list");
-    WorkerThreadState().notifyAll(GlobalWorkerThreadState::PRODUCER);
+    HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
 #else
     MOZ_CRASH();
 #endif
 }
 
 void
 GCHelperState::waitForBackgroundThread()
 {
@@ -2488,17 +2488,17 @@ GCHelperState::work()
     MOZ_CRASH();
 #endif
 }
 
 void
 GCHelperState::startBackgroundSweep(bool shouldShrink)
 {
 #ifdef JS_THREADSAFE
-    AutoLockWorkerThreadState workerLock;
+    AutoLockHelperThreadState helperLock;
     AutoLockGC lock(rt);
     JS_ASSERT(state() == IDLE);
     JS_ASSERT(!sweepFlag);
     sweepFlag = true;
     shrinkFlag = shouldShrink;
     startBackgroundThread(SWEEPING);
 #endif /* JS_THREADSAFE */
 }
@@ -4263,40 +4263,40 @@ AutoTraceSession::AutoTraceSession(JSRun
 
     // Threads with an exclusive context can hit refillFreeList while holding
     // the exclusive access lock. To avoid deadlocking when we try to acquire
     // this lock during GC and the other thread is waiting, make sure we hold
     // the exclusive access lock during GC sessions.
     JS_ASSERT(rt->currentThreadHasExclusiveAccess());
 
     if (rt->exclusiveThreadsPresent()) {
-        // Lock the worker thread state when changing the heap state in the
+        // Lock the helper thread state when changing the heap state in the
         // presence of exclusive threads, to avoid racing with refillFreeList.
 #ifdef JS_THREADSAFE
-        AutoLockWorkerThreadState lock;
+        AutoLockHelperThreadState lock;
         rt->gc.heapState = heapState;
 #else
         MOZ_CRASH();
 #endif
     } else {
         rt->gc.heapState = heapState;
     }
 }
 
 AutoTraceSession::~AutoTraceSession()
 {
     JS_ASSERT(runtime->isHeapBusy());
 
     if (runtime->exclusiveThreadsPresent()) {
 #ifdef JS_THREADSAFE
-        AutoLockWorkerThreadState lock;
+        AutoLockHelperThreadState lock;
         runtime->gc.heapState = prevState;
 
-        // Notify any worker threads waiting for the trace session to end.
-        WorkerThreadState().notifyAll(GlobalWorkerThreadState::PRODUCER);
+        // Notify any helper threads waiting for the trace session to end.
+        HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
 #else
         MOZ_CRASH();
 #endif
     } else {
         runtime->gc.heapState = prevState;
     }
 }
 
@@ -4963,17 +4963,17 @@ js::PrepareForDebugGC(JSRuntime *rt)
 {
     if (!ZonesSelected(rt))
         JS::PrepareForFullGC(rt);
 }
 
 JS_FRIEND_API(void)
 JS::ShrinkGCBuffers(JSRuntime *rt)
 {
-    AutoLockWorkerThreadState workerLock;
+    AutoLockHelperThreadState helperLock;
     AutoLockGC lock(rt);
     JS_ASSERT(!rt->isHeapBusy());
 
 #ifdef JS_THREADSAFE
     rt->gc.startBackgroundShrink();
 #else
     ExpireChunksAndArenas(rt, true);
 #endif
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1606,29 +1606,29 @@ ScriptSource::setSourceCopy(ExclusiveCon
     //    increase latency.
     //  - If there is only one core, then compression will contend with JS
     //    execution (which hurts benchmarketing).
     //  - If the source contains a giant string, then parsing will finish much
     //    faster than compression which increases latency (this case is handled
     //    in Parser::stringLiteral).
     //
     // Lastly, since the parsing thread will eventually perform a blocking wait
-    // on the compresion task's worker thread, require that there are at least 2
-    // worker threads:
-    //  - If we are on a worker thread, there must be another worker thread to
+    // on the compression task's thread, require that there are at least 2
+    // helper threads:
+    //  - If we are on a helper thread, there must be another helper thread to
     //    execute our compression task.
-    //  - If we are on the main thread, there must be at least two worker
-    //    threads since at most one worker thread can be blocking on the main
-    //    thread (see WorkerThreadState::canStartParseTask) which would cause a
-    //    deadlock if there wasn't a second worker thread that could make
+    //  - If we are on the main thread, there must be at least two helper
+    //    threads since at most one helper thread can be blocking on the main
+    //    thread (see HelperThreadState::canStartParseTask) which would cause a
+    //    deadlock if there wasn't a second helper thread that could make
     //    progress on our compression task.
 #if defined(JS_THREADSAFE) && defined(USE_ZLIB)
     bool canCompressOffThread =
-        WorkerThreadState().cpuCount > 1 &&
-        WorkerThreadState().threadCount >= 2;
+        HelperThreadState().cpuCount > 1 &&
+        HelperThreadState().threadCount >= 2;
 #else
     bool canCompressOffThread = false;
 #endif
     const size_t TINY_SCRIPT = 256;
     const size_t HUGE_SCRIPT = 5 * 1024 * 1024;
     if (TINY_SCRIPT <= srcBuf.length() && srcBuf.length() < HUGE_SCRIPT && canCompressOffThread) {
         task->ss = this;
         if (!StartOffThreadCompression(cx, task))
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -25,92 +25,92 @@
 
 using namespace js;
 
 using mozilla::ArrayLength;
 using mozilla::DebugOnly;
 
 namespace js {
 
-GlobalWorkerThreadState gWorkerThreadState;
+GlobalHelperThreadState gHelperThreadState;
 
 } // namespace js
 
 void
-js::EnsureWorkerThreadsInitialized(ExclusiveContext *cx)
+js::EnsureHelperThreadsInitialized(ExclusiveContext *cx)
 {
     // If 'cx' is not a JSContext, we are already off the main thread and the
-    // worker threads would have already been initialized.
+    // helper threads would have already been initialized.
     if (!cx->isJSContext())
         return;
 
-    WorkerThreadState().ensureInitialized();
+    HelperThreadState().ensureInitialized();
 }
 
 static size_t
 ThreadCountForCPUCount(size_t cpuCount)
 {
     return Max(cpuCount, (size_t)2);
 }
 
 void
 js::SetFakeCPUCount(size_t count)
 {
     // This must be called before the threads have been initialized.
-    JS_ASSERT(!WorkerThreadState().threads);
+    JS_ASSERT(!HelperThreadState().threads);
 
-    WorkerThreadState().cpuCount = count;
-    WorkerThreadState().threadCount = ThreadCountForCPUCount(count);
+    HelperThreadState().cpuCount = count;
+    HelperThreadState().threadCount = ThreadCountForCPUCount(count);
 }
 
 #ifdef JS_ION
 
 bool
 js::StartOffThreadAsmJSCompile(ExclusiveContext *cx, AsmJSParallelTask *asmData)
 {
     // Threads already initialized by the AsmJS compiler.
     JS_ASSERT(asmData->mir);
     JS_ASSERT(asmData->lir == nullptr);
 
-    AutoLockWorkerThreadState lock;
+    AutoLockHelperThreadState lock;
 
     // Don't append this task if another failed.
-    if (WorkerThreadState().asmJSWorkerFailed())
+    if (HelperThreadState().asmJSFailed())
         return false;
 
-    if (!WorkerThreadState().asmJSWorklist().append(asmData))
+    if (!HelperThreadState().asmJSWorklist().append(asmData))
         return false;
 
-    WorkerThreadState().notifyOne(GlobalWorkerThreadState::PRODUCER);
+    HelperThreadState().notifyOne(GlobalHelperThreadState::PRODUCER);
     return true;
 }
 
 bool
 js::StartOffThreadIonCompile(JSContext *cx, jit::IonBuilder *builder)
 {
-    EnsureWorkerThreadsInitialized(cx);
+    EnsureHelperThreadsInitialized(cx);
 
-    AutoLockWorkerThreadState lock;
+    AutoLockHelperThreadState lock;
 
-    if (!WorkerThreadState().ionWorklist().append(builder))
+    if (!HelperThreadState().ionWorklist().append(builder))
         return false;
 
-    WorkerThreadState().notifyOne(GlobalWorkerThreadState::PRODUCER);
+    HelperThreadState().notifyOne(GlobalHelperThreadState::PRODUCER);
     return true;
 }
 
 /*
  * Move an IonBuilder for which compilation has either finished, failed, or
  * been cancelled into the global finished compilation list. All off thread
  * compilations which are started must eventually be finished.
  */
 static void
 FinishOffThreadIonCompile(jit::IonBuilder *builder)
 {
-    WorkerThreadState().ionFinishedList().append(builder);
+    HelperThreadState().ionFinishedList().append(builder);
 }
 
 #endif // JS_ION
 
 static inline bool
 CompiledScriptMatches(JSCompartment *compartment, JSScript *script, JSScript *target)
 {
     if (script)
@@ -121,56 +121,56 @@ CompiledScriptMatches(JSCompartment *com
 void
 js::CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script)
 {
 #ifdef JS_ION
     jit::JitCompartment *jitComp = compartment->jitCompartment();
     if (!jitComp)
         return;
 
-    AutoLockWorkerThreadState lock;
+    AutoLockHelperThreadState lock;
 
-    if (!WorkerThreadState().threads)
+    if (!HelperThreadState().threads)
         return;
 
     /* Cancel any pending entries for which processing hasn't started. */
-    GlobalWorkerThreadState::IonBuilderVector &worklist = WorkerThreadState().ionWorklist();
+    GlobalHelperThreadState::IonBuilderVector &worklist = HelperThreadState().ionWorklist();
     for (size_t i = 0; i < worklist.length(); i++) {
         jit::IonBuilder *builder = worklist[i];
         if (CompiledScriptMatches(compartment, script, builder->script())) {
             FinishOffThreadIonCompile(builder);
-            WorkerThreadState().remove(worklist, &i);
+            HelperThreadState().remove(worklist, &i);
         }
     }
 
     /* Wait for in progress entries to finish up. */
-    for (size_t i = 0; i < WorkerThreadState().threadCount; i++) {
-        const WorkerThread &helper = WorkerThreadState().threads[i];
+    for (size_t i = 0; i < HelperThreadState().threadCount; i++) {
+        const HelperThread &helper = HelperThreadState().threads[i];
         while (helper.ionBuilder &&
                CompiledScriptMatches(compartment, script, helper.ionBuilder->script()))
         {
             helper.ionBuilder->cancel();
-            WorkerThreadState().wait(GlobalWorkerThreadState::CONSUMER);
+            HelperThreadState().wait(GlobalHelperThreadState::CONSUMER);
         }
     }
 
     /* Cancel code generation for any completed entries. */
-    GlobalWorkerThreadState::IonBuilderVector &finished = WorkerThreadState().ionFinishedList();
+    GlobalHelperThreadState::IonBuilderVector &finished = HelperThreadState().ionFinishedList();
     for (size_t i = 0; i < finished.length(); i++) {
         jit::IonBuilder *builder = finished[i];
         if (CompiledScriptMatches(compartment, script, builder->script())) {
             jit::FinishOffThreadBuilder(builder);
-            WorkerThreadState().remove(finished, &i);
+            HelperThreadState().remove(finished, &i);
         }
     }
 #endif // JS_ION
 }
 
-static const JSClass workerGlobalClass = {
-    "internal-worker-global", JSCLASS_GLOBAL_FLAGS,
+static const JSClass parseTaskGlobalClass = {
+    "internal-parse-task-global", JSCLASS_GLOBAL_FLAGS,
     JS_PropertyStub,  JS_DeletePropertyStub,
     JS_PropertyStub,  JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub,
     JS_ConvertStub,   nullptr,
     nullptr, nullptr, nullptr,
     JS_GlobalObjectTraceHook
 };
 
@@ -227,55 +227,55 @@ ParseTask::~ParseTask()
 
     for (size_t i = 0; i < errors.length(); i++)
         js_delete(errors[i]);
 }
 
 void
 js::CancelOffThreadParses(JSRuntime *rt)
 {
-    AutoLockWorkerThreadState lock;
+    AutoLockHelperThreadState lock;
 
-    if (!WorkerThreadState().threads)
+    if (!HelperThreadState().threads)
         return;
 
     // Instead of forcibly canceling pending parse tasks, just wait for all scheduled
     // and in progress ones to complete. Otherwise the final GC may not collect
     // everything due to zones being used off thread.
     while (true) {
         bool pending = false;
-        GlobalWorkerThreadState::ParseTaskVector &worklist = WorkerThreadState().parseWorklist();
+        GlobalHelperThreadState::ParseTaskVector &worklist = HelperThreadState().parseWorklist();
         for (size_t i = 0; i < worklist.length(); i++) {
             ParseTask *task = worklist[i];
             if (task->runtimeMatches(rt))
                 pending = true;
         }
         if (!pending) {
             bool inProgress = false;
-            for (size_t i = 0; i < WorkerThreadState().threadCount; i++) {
-                ParseTask *task = WorkerThreadState().threads[i].parseTask;
+            for (size_t i = 0; i < HelperThreadState().threadCount; i++) {
+                ParseTask *task = HelperThreadState().threads[i].parseTask;
                 if (task && task->runtimeMatches(rt))
                     inProgress = true;
             }
             if (!inProgress)
                 break;
         }
-        WorkerThreadState().wait(GlobalWorkerThreadState::CONSUMER);
+        HelperThreadState().wait(GlobalHelperThreadState::CONSUMER);
     }
 
     // Clean up any parse tasks which haven't been finished by the main thread.
-    GlobalWorkerThreadState::ParseTaskVector &finished = WorkerThreadState().parseFinishedList();
+    GlobalHelperThreadState::ParseTaskVector &finished = HelperThreadState().parseFinishedList();
     while (true) {
         bool found = false;
         for (size_t i = 0; i < finished.length(); i++) {
             ParseTask *task = finished[i];
             if (task->runtimeMatches(rt)) {
                 found = true;
-                AutoUnlockWorkerThreadState unlock;
-                WorkerThreadState().finishParseTask(/* maybecx = */ nullptr, rt, task);
+                AutoUnlockHelperThreadState unlock;
+                HelperThreadState().finishParseTask(/* maybecx = */ nullptr, rt, task);
             }
         }
         if (!found)
             break;
     }
 }
 
 bool
@@ -297,27 +297,27 @@ js::StartOffThreadParseScript(JSContext 
 {
     // Suppress GC so that calls below do not trigger a new incremental GC
     // which could require barriers on the atoms compartment.
     gc::AutoSuppressGC suppress(cx);
 
     SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::NoOwnership);
     frontend::MaybeCallSourceHandler(cx, options, srcBuf);
 
-    EnsureWorkerThreadsInitialized(cx);
+    EnsureHelperThreadsInitialized(cx);
 
     JS::CompartmentOptions compartmentOptions(cx->compartment()->options());
     compartmentOptions.setZone(JS::FreshZone);
     compartmentOptions.setInvisibleToDebugger(true);
     compartmentOptions.setMergeable(true);
 
     // Don't falsely inherit the host's global trace hook.
     compartmentOptions.setTrace(nullptr);
 
-    JSObject *global = JS_NewGlobalObject(cx, &workerGlobalClass, nullptr,
+    JSObject *global = JS_NewGlobalObject(cx, &parseTaskGlobalClass, nullptr,
                                           JS::FireOnNewGlobalHook, compartmentOptions);
     if (!global)
         return false;
 
     JS_SetCompartmentPrincipals(global->compartment(), cx->compartment()->principals);
 
     RootedObject obj(cx);
 
@@ -337,254 +337,254 @@ js::StartOffThreadParseScript(JSContext 
             !GetBuiltinConstructor(cx, JSProto_Array, &obj) ||
             !GetBuiltinConstructor(cx, JSProto_RegExp, &obj) ||
             !GetBuiltinConstructor(cx, JSProto_Iterator, &obj))
         {
             return false;
         }
     }
 
-    ScopedJSDeletePtr<ExclusiveContext> workercx(
+    ScopedJSDeletePtr<ExclusiveContext> helpercx(
         cx->new_<ExclusiveContext>(cx->runtime(), (PerThreadData *) nullptr,
                                    ThreadSafeContext::Context_Exclusive));
-    if (!workercx)
+    if (!helpercx)
         return false;
 
     ScopedJSDeletePtr<ParseTask> task(
-        cx->new_<ParseTask>(workercx.get(), global, cx, chars, length,
+        cx->new_<ParseTask>(helpercx.get(), global, cx, chars, length,
                             callback, callbackData));
     if (!task)
         return false;
 
-    workercx.forget();
+    helpercx.forget();
 
     if (!task->init(cx, options))
         return false;
 
     if (OffThreadParsingMustWaitForGC(cx->runtime())) {
-        AutoLockWorkerThreadState lock;
-        if (!WorkerThreadState().parseWaitingOnGC().append(task.get()))
+        AutoLockHelperThreadState lock;
+        if (!HelperThreadState().parseWaitingOnGC().append(task.get()))
             return false;
     } else {
         task->activate(cx->runtime());
 
-        AutoLockWorkerThreadState lock;
+        AutoLockHelperThreadState lock;
 
-        if (!WorkerThreadState().parseWorklist().append(task.get()))
+        if (!HelperThreadState().parseWorklist().append(task.get()))
             return false;
 
-        WorkerThreadState().notifyOne(GlobalWorkerThreadState::PRODUCER);
+        HelperThreadState().notifyOne(GlobalHelperThreadState::PRODUCER);
     }
 
     task.forget();
 
     return true;
 }
 
 void
 js::EnqueuePendingParseTasksAfterGC(JSRuntime *rt)
 {
     JS_ASSERT(!OffThreadParsingMustWaitForGC(rt));
 
-    GlobalWorkerThreadState::ParseTaskVector newTasks;
+    GlobalHelperThreadState::ParseTaskVector newTasks;
     {
-        AutoLockWorkerThreadState lock;
-        GlobalWorkerThreadState::ParseTaskVector &waiting = WorkerThreadState().parseWaitingOnGC();
+        AutoLockHelperThreadState lock;
+        GlobalHelperThreadState::ParseTaskVector &waiting = HelperThreadState().parseWaitingOnGC();
 
         for (size_t i = 0; i < waiting.length(); i++) {
             ParseTask *task = waiting[i];
             if (task->runtimeMatches(rt)) {
                 newTasks.append(task);
-                WorkerThreadState().remove(waiting, &i);
+                HelperThreadState().remove(waiting, &i);
             }
         }
     }
 
     if (newTasks.empty())
         return;
 
     // This logic should mirror the contents of the !activeGCInAtomsZone()
     // branch in StartOffThreadParseScript:
 
     for (size_t i = 0; i < newTasks.length(); i++)
         newTasks[i]->activate(rt);
 
-    AutoLockWorkerThreadState lock;
+    AutoLockHelperThreadState lock;
 
     for (size_t i = 0; i < newTasks.length(); i++)
-        WorkerThreadState().parseWorklist().append(newTasks[i]);
+        HelperThreadState().parseWorklist().append(newTasks[i]);
 
-    WorkerThreadState().notifyAll(GlobalWorkerThreadState::PRODUCER);
+    HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
 }
 
-static const uint32_t WORKER_STACK_SIZE = 512 * 1024;
-static const uint32_t WORKER_STACK_QUOTA = 450 * 1024;
+static const uint32_t HELPER_STACK_SIZE = 512 * 1024;
+static const uint32_t HELPER_STACK_QUOTA = 450 * 1024;
 
 void
-GlobalWorkerThreadState::ensureInitialized()
+GlobalHelperThreadState::ensureInitialized()
 {
-    JS_ASSERT(this == &WorkerThreadState());
-    AutoLockWorkerThreadState lock;
+    JS_ASSERT(this == &HelperThreadState());
+    AutoLockHelperThreadState lock;
 
     if (threads)
         return;
 
-    threads = js_pod_calloc<WorkerThread>(threadCount);
+    threads = js_pod_calloc<HelperThread>(threadCount);
     if (!threads)
-        CrashAtUnhandlableOOM("GlobalWorkerThreadState::ensureInitialized");
+        CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
 
     for (size_t i = 0; i < threadCount; i++) {
-        WorkerThread &helper = threads[i];
+        HelperThread &helper = threads[i];
         helper.threadData.construct(static_cast<JSRuntime *>(nullptr));
         helper.thread = PR_CreateThread(PR_USER_THREAD,
-                                        WorkerThread::ThreadMain, &helper,
-                                        PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, WORKER_STACK_SIZE);
+                                        HelperThread::ThreadMain, &helper,
+                                        PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, HELPER_STACK_SIZE);
         if (!helper.thread || !helper.threadData.ref().init())
-            CrashAtUnhandlableOOM("GlobalWorkerThreadState::ensureInitialized");
+            CrashAtUnhandlableOOM("GlobalHelperThreadState::ensureInitialized");
     }
 
     resetAsmJSFailureState();
 }
 
-GlobalWorkerThreadState::GlobalWorkerThreadState()
+GlobalHelperThreadState::GlobalHelperThreadState()
 {
     mozilla::PodZero(this);
 
     cpuCount = GetCPUCount();
     threadCount = ThreadCountForCPUCount(cpuCount);
 
     MOZ_ASSERT(cpuCount > 0, "GetCPUCount() seems broken");
 
-    workerLock = PR_NewLock();
-    consumerWakeup = PR_NewCondVar(workerLock);
-    producerWakeup = PR_NewCondVar(workerLock);
+    helperLock = PR_NewLock();
+    consumerWakeup = PR_NewCondVar(helperLock);
+    producerWakeup = PR_NewCondVar(helperLock);
 }
 
 void
-GlobalWorkerThreadState::finish()
+GlobalHelperThreadState::finish()
 {
     if (threads) {
         for (size_t i = 0; i < threadCount; i++)
             threads[i].destroy();
         js_free(threads);
     }
 
     PR_DestroyCondVar(consumerWakeup);
     PR_DestroyCondVar(producerWakeup);
-    PR_DestroyLock(workerLock);
+    PR_DestroyLock(helperLock);
 }
 
 void
-GlobalWorkerThreadState::lock()
+GlobalHelperThreadState::lock()
 {
     JS_ASSERT(!isLocked());
-    AssertCurrentThreadCanLock(WorkerThreadStateLock);
-    PR_Lock(workerLock);
+    AssertCurrentThreadCanLock(HelperThreadStateLock);
+    PR_Lock(helperLock);
 #ifdef DEBUG
     lockOwner = PR_GetCurrentThread();
 #endif
 }
 
 void
-GlobalWorkerThreadState::unlock()
+GlobalHelperThreadState::unlock()
 {
     JS_ASSERT(isLocked());
 #ifdef DEBUG
     lockOwner = nullptr;
 #endif
-    PR_Unlock(workerLock);
+    PR_Unlock(helperLock);
 }
 
 #ifdef DEBUG
 bool
-GlobalWorkerThreadState::isLocked()
+GlobalHelperThreadState::isLocked()
 {
     return lockOwner == PR_GetCurrentThread();
 }
 #endif
 
 void
-GlobalWorkerThreadState::wait(CondVar which, uint32_t millis)
+GlobalHelperThreadState::wait(CondVar which, uint32_t millis)
 {
     JS_ASSERT(isLocked());
 #ifdef DEBUG
     lockOwner = nullptr;
 #endif
     DebugOnly<PRStatus> status =
         PR_WaitCondVar((which == CONSUMER) ? consumerWakeup : producerWakeup,
                        millis ? PR_MillisecondsToInterval(millis) : PR_INTERVAL_NO_TIMEOUT);
     JS_ASSERT(status == PR_SUCCESS);
 #ifdef DEBUG
     lockOwner = PR_GetCurrentThread();
 #endif
 }
 
 void
-GlobalWorkerThreadState::notifyAll(CondVar which)
+GlobalHelperThreadState::notifyAll(CondVar which)
 {
     JS_ASSERT(isLocked());
     PR_NotifyAllCondVar((which == CONSUMER) ? consumerWakeup : producerWakeup);
 }
 
 void
-GlobalWorkerThreadState::notifyOne(CondVar which)
+GlobalHelperThreadState::notifyOne(CondVar which)
 {
     JS_ASSERT(isLocked());
     PR_NotifyCondVar((which == CONSUMER) ? consumerWakeup : producerWakeup);
 }
 
 bool
-GlobalWorkerThreadState::canStartAsmJSCompile()
+GlobalHelperThreadState::canStartAsmJSCompile()
 {
     // Don't execute an AsmJS job if an earlier one failed.
     JS_ASSERT(isLocked());
     return !asmJSWorklist().empty() && !numAsmJSFailedJobs;
 }
 
 bool
-GlobalWorkerThreadState::canStartIonCompile()
+GlobalHelperThreadState::canStartIonCompile()
 {
-    // A worker thread can begin an Ion compilation if (a) there is some script
-    // which is waiting to be compiled, and (b) no other worker thread is
+    // A helper thread can begin an Ion compilation if (a) there is some script
+    // which is waiting to be compiled, and (b) no other helper thread is
     // currently compiling a script. The latter condition ensures that two
     // compilations cannot simultaneously occur.
     if (ionWorklist().empty())
         return false;
     for (size_t i = 0; i < threadCount; i++) {
         if (threads[i].ionBuilder)
             return false;
     }
     return true;
 }
 
 bool
-GlobalWorkerThreadState::canStartParseTask()
+GlobalHelperThreadState::canStartParseTask()
 {
     // Don't allow simultaneous off thread parses, to reduce contention on the
     // atoms table. Note that asm.js compilation depends on this to avoid
-    // stalling the worker thread, as off thread parse tasks can trigger and
+    // stalling the helper thread, as off thread parse tasks can trigger and
     // block on other off thread asm.js compilation tasks.
     JS_ASSERT(isLocked());
     if (parseWorklist().empty())
         return false;
     for (size_t i = 0; i < threadCount; i++) {
         if (threads[i].parseTask)
             return false;
     }
     return true;
 }
 
 bool
-GlobalWorkerThreadState::canStartCompressionTask()
+GlobalHelperThreadState::canStartCompressionTask()
 {
     return !compressionWorklist().empty();
 }
 
 bool
-GlobalWorkerThreadState::canStartGCHelperTask()
+GlobalHelperThreadState::canStartGCHelperTask()
 {
     return !gcHelperWorklist().empty();
 }
 
 static void
 CallNewScriptHookForAllScripts(JSContext *cx, HandleScript script)
 {
     // We should never hit this, since nested scripts are also constructed via
@@ -607,24 +607,24 @@ CallNewScriptHookForAllScripts(JSContext
     }
 
     // The global new script hook is called on every script that was compiled.
     RootedFunction function(cx, script->functionNonDelazifying());
     CallNewScriptHook(cx, script, function);
 }
 
 JSScript *
-GlobalWorkerThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *token)
+GlobalHelperThreadState::finishParseTask(JSContext *maybecx, JSRuntime *rt, void *token)
 {
     ScopedJSDeletePtr<ParseTask> parseTask;
 
     // The token is a ParseTask* which should be in the finished list.
     // Find and remove its entry.
     {
-        AutoLockWorkerThreadState lock;
+        AutoLockHelperThreadState lock;
         ParseTaskVector &finished = parseFinishedList();
         for (size_t i = 0; i < finished.length(); i++) {
             if (finished[i] == token) {
                 parseTask = finished[i];
                 remove(finished, &i);
                 break;
             }
         }
@@ -702,25 +702,25 @@ GlobalWorkerThreadState::finishParseTask
         // The NewScript hook needs to be called for all compiled scripts.
         CallNewScriptHookForAllScripts(cx, script);
     }
 
     return script;
 }
 
 void
-WorkerThread::destroy()
+HelperThread::destroy()
 {
     if (thread) {
         {
-            AutoLockWorkerThreadState lock;
+            AutoLockHelperThreadState lock;
             terminate = true;
 
-            /* Notify all workers, to ensure that this thread wakes up. */
-            WorkerThreadState().notifyAll(GlobalWorkerThreadState::PRODUCER);
+            /* Notify all helpers, to ensure that this thread wakes up. */
+            HelperThreadState().notifyAll(GlobalHelperThreadState::PRODUCER);
         }
 
         PR_JoinThread(thread);
     }
 
     if (!threadData.empty())
         threadData.destroy();
 }
@@ -729,43 +729,43 @@ WorkerThread::destroy()
 extern "C" {
 MFBT_API bool IsNuwaProcess();
 MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void *), void *arg);
 }
 #endif
 
 /* static */
 void
-WorkerThread::ThreadMain(void *arg)
+HelperThread::ThreadMain(void *arg)
 {
     PR_SetCurrentThreadName("Analysis Helper");
 
 #ifdef MOZ_NUWA_PROCESS
     if (IsNuwaProcess()) {
         JS_ASSERT(NuwaMarkCurrentThread != nullptr);
         NuwaMarkCurrentThread(nullptr, nullptr);
     }
 #endif
 
-    static_cast<WorkerThread *>(arg)->threadLoop();
+    static_cast<HelperThread *>(arg)->threadLoop();
 }
 
 void
-WorkerThread::handleAsmJSWorkload()
+HelperThread::handleAsmJSWorkload()
 {
 #ifdef JS_ION
-    JS_ASSERT(WorkerThreadState().isLocked());
-    JS_ASSERT(WorkerThreadState().canStartAsmJSCompile());
+    JS_ASSERT(HelperThreadState().isLocked());
+    JS_ASSERT(HelperThreadState().canStartAsmJSCompile());
     JS_ASSERT(idle());
 
-    asmData = WorkerThreadState().asmJSWorklist().popCopy();
+    asmData = HelperThreadState().asmJSWorklist().popCopy();
     bool success = false;
 
     do {
-        AutoUnlockWorkerThreadState unlock;
+        AutoUnlockHelperThreadState unlock;
         PerThreadData::AutoEnterRuntime enter(threadData.addr(), asmData->runtime);
 
         jit::IonContext icx(asmData->mir->compartment->runtime(),
                             asmData->mir->compartment,
                             &asmData->mir->alloc());
 
         int64_t before = PRMJ_Now();
 
@@ -779,43 +779,43 @@ WorkerThread::handleAsmJSWorkload()
         int64_t after = PRMJ_Now();
         asmData->compileTime = (after - before) / PRMJ_USEC_PER_MSEC;
 
         success = true;
     } while(0);
 
     // On failure, signal parent for harvesting in CancelOutstandingJobs().
     if (!success) {
-        WorkerThreadState().noteAsmJSFailure(asmData->func);
-        WorkerThreadState().notifyAll(GlobalWorkerThreadState::CONSUMER);
+        HelperThreadState().noteAsmJSFailure(asmData->func);
+        HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER);
         asmData = nullptr;
         return;
     }
 
     // On success, move work to the finished list.
-    WorkerThreadState().asmJSFinishedList().append(asmData);
+    HelperThreadState().asmJSFinishedList().append(asmData);
     asmData = nullptr;
 
     // Notify the main thread in case it's blocked waiting for a LifoAlloc.
-    WorkerThreadState().notifyAll(GlobalWorkerThreadState::CONSUMER);
+    HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER);
 #else
     MOZ_CRASH();
 #endif // JS_ION
 }
 
 void
-WorkerThread::handleIonWorkload()
+HelperThread::handleIonWorkload()
 {
 #ifdef JS_ION
-    JS_ASSERT(WorkerThreadState().isLocked());
-    JS_ASSERT(WorkerThreadState().canStartIonCompile());
+    JS_ASSERT(HelperThreadState().isLocked());
+    JS_ASSERT(HelperThreadState().canStartIonCompile());
     JS_ASSERT(idle());
 
     // Find the ionBuilder with the script having the highest usecount.
-    GlobalWorkerThreadState::IonBuilderVector &ionWorklist = WorkerThreadState().ionWorklist();
+    GlobalHelperThreadState::IonBuilderVector &ionWorklist = HelperThreadState().ionWorklist();
     size_t highest = 0;
     for (size_t i = 1; i < ionWorklist.length(); i++) {
         if (ionWorklist[i]->script()->getUseCount() >
             ionWorklist[highest]->script()->getUseCount())
         {
             highest = i;
         }
     }
@@ -830,17 +830,17 @@ WorkerThread::handleIonWorkload()
 
     TraceLogger *logger = TraceLoggerForCurrentThread();
     AutoTraceLog logScript(logger, TraceLogCreateTextId(logger, ionBuilder->script()));
     AutoTraceLog logCompile(logger, TraceLogger::IonCompilation);
 
     JSRuntime *rt = ionBuilder->script()->compartment()->runtimeFromAnyThread();
 
     {
-        AutoUnlockWorkerThreadState unlock;
+        AutoUnlockHelperThreadState unlock;
         PerThreadData::AutoEnterRuntime enter(threadData.addr(),
                                               ionBuilder->script()->runtimeFromAnyThread());
         jit::IonContext ictx(jit::CompileRuntime::get(rt),
                              jit::CompileCompartment::get(ionBuilder->script()->compartment()),
                              &ionBuilder->alloc());
         ionBuilder->setBackgroundCodegen(jit::CompileBackEnd(ionBuilder));
     }
 
@@ -849,123 +849,123 @@ WorkerThread::handleIonWorkload()
 
     // Ping the main thread so that the compiled code can be incorporated
     // at the next interrupt callback. Don't interrupt Ion code for this, as
     // this incorporation can be delayed indefinitely without affecting
     // performance as long as the main thread is actually executing Ion code.
     rt->requestInterrupt(JSRuntime::RequestInterruptAnyThreadDontStopIon);
 
     // Notify the main thread in case it is waiting for the compilation to finish.
-    WorkerThreadState().notifyAll(GlobalWorkerThreadState::CONSUMER);
+    HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER);
 #else
     MOZ_CRASH();
 #endif // JS_ION
 }
 
 void
-ExclusiveContext::setWorkerThread(WorkerThread *workerThread)
+ExclusiveContext::setHelperThread(HelperThread *thread)
 {
-    workerThread_ = workerThread;
-    perThreadData = workerThread->threadData.addr();
+    helperThread_ = thread;
+    perThreadData = thread->threadData.addr();
 }
 
 frontend::CompileError &
 ExclusiveContext::addPendingCompileError()
 {
     frontend::CompileError *error = js_new<frontend::CompileError>();
     if (!error)
         MOZ_CRASH();
-    if (!workerThread()->parseTask->errors.append(error))
+    if (!helperThread()->parseTask->errors.append(error))
         MOZ_CRASH();
     return *error;
 }
 
 void
 ExclusiveContext::addPendingOverRecursed()
 {
-    if (workerThread()->parseTask)
-        workerThread()->parseTask->overRecursed = true;
+    if (helperThread()->parseTask)
+        helperThread()->parseTask->overRecursed = true;
 }
 
 void
-WorkerThread::handleParseWorkload()
+HelperThread::handleParseWorkload()
 {
-    JS_ASSERT(WorkerThreadState().isLocked());
-    JS_ASSERT(WorkerThreadState().canStartParseTask());
+    JS_ASSERT(HelperThreadState().isLocked());
+    JS_ASSERT(HelperThreadState().canStartParseTask());
     JS_ASSERT(idle());
 
-    parseTask = WorkerThreadState().parseWorklist().popCopy();
-    parseTask->cx->setWorkerThread(this);
+    parseTask = HelperThreadState().parseWorklist().popCopy();
+    parseTask->cx->setHelperThread(this);
 
     {
-        AutoUnlockWorkerThreadState unlock;
+        AutoUnlockHelperThreadState unlock;
         PerThreadData::AutoEnterRuntime enter(threadData.addr(),
                                               parseTask->exclusiveContextGlobal->runtimeFromAnyThread());
         SourceBufferHolder srcBuf(parseTask->chars, parseTask->length,
                                   SourceBufferHolder::NoOwnership);
         parseTask->script = frontend::CompileScript(parseTask->cx, &parseTask->alloc,
                                                     NullPtr(), NullPtr(),
                                                     parseTask->options,
                                                     srcBuf);
     }
 
     // The callback is invoked while we are still off the main thread.
     parseTask->callback(parseTask, parseTask->callbackData);
 
     // FinishOffThreadScript will need to be called on the script to
     // migrate it into the correct compartment.
-    WorkerThreadState().parseFinishedList().append(parseTask);
+    HelperThreadState().parseFinishedList().append(parseTask);
 
     parseTask = nullptr;
 
     // Notify the main thread in case it is waiting for the parse/emit to finish.
-    WorkerThreadState().notifyAll(GlobalWorkerThreadState::CONSUMER);
+    HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER);
 }
 
 void
-WorkerThread::handleCompressionWorkload()
+HelperThread::handleCompressionWorkload()
 {
-    JS_ASSERT(WorkerThreadState().isLocked());
-    JS_ASSERT(WorkerThreadState().canStartCompressionTask());
+    JS_ASSERT(HelperThreadState().isLocked());
+    JS_ASSERT(HelperThreadState().canStartCompressionTask());
     JS_ASSERT(idle());
 
-    compressionTask = WorkerThreadState().compressionWorklist().popCopy();
-    compressionTask->workerThread = this;
+    compressionTask = HelperThreadState().compressionWorklist().popCopy();
+    compressionTask->helperThread = this;
 
     {
-        AutoUnlockWorkerThreadState unlock;
+        AutoUnlockHelperThreadState unlock;
         compressionTask->result = compressionTask->work();
     }
 
-    compressionTask->workerThread = nullptr;
+    compressionTask->helperThread = nullptr;
     compressionTask = nullptr;
 
     // Notify the main thread in case it is waiting for the compression to finish.
-    WorkerThreadState().notifyAll(GlobalWorkerThreadState::CONSUMER);
+    HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER);
 }
 
 bool
 js::StartOffThreadCompression(ExclusiveContext *cx, SourceCompressionTask *task)
 {
-    EnsureWorkerThreadsInitialized(cx);
+    EnsureHelperThreadsInitialized(cx);
 
-    AutoLockWorkerThreadState lock;
+    AutoLockHelperThreadState lock;
 
-    if (!WorkerThreadState().compressionWorklist().append(task)) {
+    if (!HelperThreadState().compressionWorklist().append(task)) {
         if (JSContext *maybecx = cx->maybeJSContext())
             js_ReportOutOfMemory(maybecx);
         return false;
     }
 
-    WorkerThreadState().notifyOne(GlobalWorkerThreadState::PRODUCER);
+    HelperThreadState().notifyOne(GlobalHelperThreadState::PRODUCER);
     return true;
 }
 
 bool
-GlobalWorkerThreadState::compressionInProgress(SourceCompressionTask *task)
+GlobalHelperThreadState::compressionInProgress(SourceCompressionTask *task)
 {
     JS_ASSERT(isLocked());
     for (size_t i = 0; i < compressionWorklist().length(); i++) {
         if (compressionWorklist()[i] == task)
             return true;
     }
     for (size_t i = 0; i < threadCount; i++) {
         if (threads[i].compressionTask == task)
@@ -978,19 +978,19 @@ bool
 SourceCompressionTask::complete()
 {
     if (!active()) {
         JS_ASSERT(!compressed);
         return true;
     }
 
     {
-        AutoLockWorkerThreadState lock;
-        while (WorkerThreadState().compressionInProgress(this))
-            WorkerThreadState().wait(GlobalWorkerThreadState::CONSUMER);
+        AutoLockHelperThreadState lock;
+        while (HelperThreadState().compressionInProgress(this))
+            HelperThreadState().wait(GlobalHelperThreadState::CONSUMER);
     }
 
     if (result == Success) {
         ss->setCompressedSource(compressed, compressedBytes);
 
         // Update memory accounting.
         cx->updateMallocCounter(ss->computedSizeOfData());
     } else {
@@ -1005,96 +1005,96 @@ SourceCompressionTask::complete()
     ss = nullptr;
     compressed = nullptr;
     JS_ASSERT(!active());
 
     return result != OOM;
 }
 
 SourceCompressionTask *
-GlobalWorkerThreadState::compressionTaskForSource(ScriptSource *ss)
+GlobalHelperThreadState::compressionTaskForSource(ScriptSource *ss)
 {
     JS_ASSERT(isLocked());
     for (size_t i = 0; i < compressionWorklist().length(); i++) {
         SourceCompressionTask *task = compressionWorklist()[i];
         if (task->source() == ss)
             return task;
     }
     for (size_t i = 0; i < threadCount; i++) {
         SourceCompressionTask *task = threads[i].compressionTask;
         if (task && task->source() == ss)
             return task;
     }
     return nullptr;
 }
 
 void
-WorkerThread::handleGCHelperWorkload()
+HelperThread::handleGCHelperWorkload()
 {
-    JS_ASSERT(WorkerThreadState().isLocked());
-    JS_ASSERT(WorkerThreadState().canStartGCHelperTask());
+    JS_ASSERT(HelperThreadState().isLocked());
+    JS_ASSERT(HelperThreadState().canStartGCHelperTask());
     JS_ASSERT(idle());
 
     JS_ASSERT(!gcHelperState);
-    gcHelperState = WorkerThreadState().gcHelperWorklist().popCopy();
+    gcHelperState = HelperThreadState().gcHelperWorklist().popCopy();
 
     {
-        AutoUnlockWorkerThreadState unlock;
+        AutoUnlockHelperThreadState unlock;
         gcHelperState->work();
     }
 
     gcHelperState = nullptr;
 }
 
 void
-WorkerThread::threadLoop()
+HelperThread::threadLoop()
 {
     JS::AutoAssertNoGC nogc;
-    AutoLockWorkerThreadState lock;
+    AutoLockHelperThreadState lock;
 
     js::TlsPerThreadData.set(threadData.addr());
 
     // Compute the thread's stack limit, for over-recursed checks.
     uintptr_t stackLimit = GetNativeStackBase();
 #if JS_STACK_GROWTH_DIRECTION > 0
-    stackLimit += WORKER_STACK_QUOTA;
+    stackLimit += HELPER_STACK_QUOTA;
 #else
-    stackLimit -= WORKER_STACK_QUOTA;
+    stackLimit -= HELPER_STACK_QUOTA;
 #endif
     for (size_t i = 0; i < ArrayLength(threadData.ref().nativeStackLimit); i++)
         threadData.ref().nativeStackLimit[i] = stackLimit;
 
     while (true) {
         JS_ASSERT(!ionBuilder && !asmData);
 
         // Block until a task is available.
         while (true) {
             if (terminate)
                 return;
-            if (WorkerThreadState().canStartIonCompile() ||
-                WorkerThreadState().canStartAsmJSCompile() ||
-                WorkerThreadState().canStartParseTask() ||
-                WorkerThreadState().canStartCompressionTask() ||
-                WorkerThreadState().canStartGCHelperTask())
+            if (HelperThreadState().canStartIonCompile() ||
+                HelperThreadState().canStartAsmJSCompile() ||
+                HelperThreadState().canStartParseTask() ||
+                HelperThreadState().canStartCompressionTask() ||
+                HelperThreadState().canStartGCHelperTask())
             {
                 break;
             }
-            WorkerThreadState().wait(GlobalWorkerThreadState::PRODUCER);
+            HelperThreadState().wait(GlobalHelperThreadState::PRODUCER);
         }
 
         // Dispatch tasks, prioritizing AsmJS work.
-        if (WorkerThreadState().canStartAsmJSCompile())
+        if (HelperThreadState().canStartAsmJSCompile())
             handleAsmJSWorkload();
-        else if (WorkerThreadState().canStartIonCompile())
+        else if (HelperThreadState().canStartIonCompile())
             handleIonWorkload();
-        else if (WorkerThreadState().canStartParseTask())
+        else if (HelperThreadState().canStartParseTask())
             handleParseWorkload();
-        else if (WorkerThreadState().canStartCompressionTask())
+        else if (HelperThreadState().canStartCompressionTask())
             handleCompressionWorkload();
-        else if (WorkerThreadState().canStartGCHelperTask())
+        else if (HelperThreadState().canStartGCHelperTask())
             handleGCHelperWorkload();
         else
             MOZ_ASSUME_UNREACHABLE("No task to perform");
     }
 }
 
 #else /* JS_THREADSAFE */
 
--- a/js/src/jsworkers.h
+++ b/js/src/jsworkers.h
@@ -1,62 +1,62 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*
- * Definitions for managing off-main-thread work using a shared, per runtime
- * worklist. Worklist items are engine internal, and are distinct from e.g.
- * web workers.
+ * Definitions for managing off-main-thread work using a process wide list
+ * of worklist items and pool of threads. Worklist items are engine internal,
+ * and are distinct from e.g. web workers.
  */
 
 #ifndef jsworkers_h
 #define jsworkers_h
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/PodOperations.h"
 
 #include "jscntxt.h"
 #include "jslock.h"
 
 #include "frontend/TokenStream.h"
 #include "jit/Ion.h"
 
 namespace js {
 
-struct WorkerThread;
+struct HelperThread;
 struct AsmJSParallelTask;
 struct ParseTask;
 namespace jit {
   class IonBuilder;
 }
 
 #ifdef JS_THREADSAFE
 
 // Per-process state for off thread work items.
-class GlobalWorkerThreadState
+class GlobalHelperThreadState
 {
   public:
     // Number of CPUs to treat this machine as having when creating threads.
     // May be accessed without locking.
     size_t cpuCount;
 
     // Number of threads to create. May be accessed without locking.
     size_t threadCount;
 
     typedef Vector<jit::IonBuilder*, 0, SystemAllocPolicy> IonBuilderVector;
     typedef Vector<AsmJSParallelTask*, 0, SystemAllocPolicy> AsmJSParallelTaskVector;
     typedef Vector<ParseTask*, 0, SystemAllocPolicy> ParseTaskVector;
     typedef Vector<SourceCompressionTask*, 0, SystemAllocPolicy> SourceCompressionTaskVector;
     typedef Vector<GCHelperState *, 0, SystemAllocPolicy> GCHelperStateVector;
 
     // List of available threads, or null if the thread state has not been initialized.
-    WorkerThread *threads;
+    HelperThread *threads;
 
   private:
     // The lists below are all protected by |lock|.
 
     // Ion compilation worklist and finished jobs.
     IonBuilderVector ionWorklist_, ionFinishedList_;
 
     // AsmJS worklist and finished jobs.
@@ -81,17 +81,17 @@ class GlobalWorkerThreadState
 
     // Source compression worklist.
     SourceCompressionTaskVector compressionWorklist_;
 
     // Runtimes which have sweeping / allocating work to do.
     GCHelperStateVector gcHelperWorklist_;
 
   public:
-    GlobalWorkerThreadState();
+    GlobalHelperThreadState();
 
     void ensureInitialized();
     void finish();
 
     void lock();
     void unlock();
 
 # ifdef DEBUG
@@ -173,17 +173,17 @@ class GlobalWorkerThreadState
     }
     void noteAsmJSFailure(void *func) {
         // Be mindful to signal the main thread after calling this function.
         JS_ASSERT(isLocked());
         if (!asmJSFailedFunction)
             asmJSFailedFunction = func;
         numAsmJSFailedJobs++;
     }
-    bool asmJSWorkerFailed() const {
+    bool asmJSFailed() const {
         return bool(numAsmJSFailedJobs);
     }
     void resetAsmJSFailureState() {
         numAsmJSFailedJobs = 0;
         asmJSFailedFunction = nullptr;
     }
     void *maybeAsmJSFailedFunction() const {
         return asmJSFailedFunction;
@@ -194,48 +194,47 @@ class GlobalWorkerThreadState
     SourceCompressionTask *compressionTaskForSource(ScriptSource *ss);
 
   private:
 
     /*
      * Lock protecting all mutable shared state accessed by helper threads, and
      * used by all condition variables.
      */
-    PRLock *workerLock;
-
+    PRLock *helperLock;
 # ifdef DEBUG
     PRThread *lockOwner;
 # endif
 
     /* Condvars for threads waiting/notifying each other. */
     PRCondVar *consumerWakeup;
     PRCondVar *producerWakeup;
 
     /*
-     * Number of AsmJS workers that encountered failure for the active module.
+     * Number of AsmJS jobs that encountered failure for the active module.
      * Their parent is logically the main thread, and this number serves for harvesting.
      */
     uint32_t numAsmJSFailedJobs;
 
     /*
      * Function index |i| in |Module.function(i)| of first failed AsmJS function.
      * -1 if no function has failed.
      */
     void *asmJSFailedFunction;
 };
 
-static inline GlobalWorkerThreadState &
-WorkerThreadState()
+static inline GlobalHelperThreadState &
+HelperThreadState()
 {
-    extern GlobalWorkerThreadState gWorkerThreadState;
-    return gWorkerThreadState;
+    extern GlobalHelperThreadState gHelperThreadState;
+    return gHelperThreadState;
 }
 
 /* Individual helper thread, one allocated per core. */
-struct WorkerThread
+struct HelperThread
 {
     mozilla::Maybe<PerThreadData> threadData;
     PRThread *thread;
 
     /* Indicate to an idle thread that it should finish executing. */
     bool terminate;
 
     /* Any builder currently being compiled by Ion on this thread. */
@@ -266,21 +265,21 @@ struct WorkerThread
     void handleGCHelperWorkload();
 
     static void ThreadMain(void *arg);
     void threadLoop();
 };
 
 #endif /* JS_THREADSAFE */
 
-/* Methods for interacting with worker threads. */
+/* Methods for interacting with helper threads. */
 
-// Initialize worker threads unless already initialized.
+// Initialize helper threads unless already initialized.
 void
-EnsureWorkerThreadsInitialized(ExclusiveContext *cx);
+EnsureHelperThreadsInitialized(ExclusiveContext *cx);
 
 // This allows the JS shell to override GetCPUCount() when passed the
 // --thread-count=N option.
 void
 SetFakeCPUCount(size_t count);
 
 #ifdef JS_ION
 
@@ -323,70 +322,70 @@ StartOffThreadParseScript(JSContext *cx,
  */
 void
 EnqueuePendingParseTasksAfterGC(JSRuntime *rt);
 
 /* Start a compression job for the specified token. */
 bool
 StartOffThreadCompression(ExclusiveContext *cx, SourceCompressionTask *task);
 
-class AutoLockWorkerThreadState
+class AutoLockHelperThreadState
 {
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
 #ifdef JS_THREADSAFE
   public:
-    AutoLockWorkerThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
+    AutoLockHelperThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
-        WorkerThreadState().lock();
+        HelperThreadState().lock();
     }
 
-    ~AutoLockWorkerThreadState() {
-        WorkerThreadState().unlock();
+    ~AutoLockHelperThreadState() {
+        HelperThreadState().unlock();
     }
 #else
   public:
-    AutoLockWorkerThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
+    AutoLockHelperThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     }
 #endif
 };
 
-class AutoUnlockWorkerThreadState
+class AutoUnlockHelperThreadState
 {
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
   public:
 
-    AutoUnlockWorkerThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
+    AutoUnlockHelperThreadState(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
 #ifdef JS_THREADSAFE
-        WorkerThreadState().unlock();
+        HelperThreadState().unlock();
 #endif
     }
 
-    ~AutoUnlockWorkerThreadState()
+    ~AutoUnlockHelperThreadState()
     {
 #ifdef JS_THREADSAFE
-        WorkerThreadState().lock();
+        HelperThreadState().lock();
 #endif
     }
 };
 
 #ifdef JS_ION
 struct AsmJSParallelTask
 {
     JSRuntime *runtime;     // Associated runtime.
     LifoAlloc lifo;         // Provider of all heap memory used for compilation.
     void *func;             // Really, a ModuleCompiler::Func*
-    jit::MIRGenerator *mir; // Passed from main thread to worker.
-    jit::LIRGraph *lir;     // Passed from worker to main thread.
+    jit::MIRGenerator *mir; // Passed from main thread to helper.
+    jit::LIRGraph *lir;     // Passed from helper to main thread.
     unsigned compileTime;
 
     explicit AsmJSParallelTask(size_t defaultChunkSize)
       : runtime(nullptr), lifo(defaultChunkSize), func(nullptr), mir(nullptr), lir(nullptr), compileTime(0)
     { }
 
     void init(JSRuntime *rt, void *func, jit::MIRGenerator *mir) {
         this->runtime = rt;
@@ -453,30 +452,30 @@ OffThreadParsingMustWaitForGC(JSRuntime 
 #endif
 
 // Compression tasks are allocated on the stack by their triggering thread,
 // which will block on the compression completing as the task goes out of scope
 // to ensure it completes at the required time.
 struct SourceCompressionTask
 {
     friend class ScriptSource;
-    friend class WorkerThread;
+    friend class HelperThread;
 
 #ifdef JS_THREADSAFE
     // Thread performing the compression.
-    WorkerThread *workerThread;
+    HelperThread *helperThread;
 #endif
 
   private:
     // Context from the triggering thread. Don't use this off thread!
     ExclusiveContext *cx;
 
     ScriptSource *ss;
 
-    // Atomic flag to indicate to a worker thread that it should abort
+    // Atomic flag to indicate to a helper thread that it should abort
     // compression on the source.
     mozilla::Atomic<bool, mozilla::Relaxed> abort_;
 
     // Stores the result of the compression.
     enum ResultType {
         OOM,
         Aborted,
         Success
@@ -485,17 +484,17 @@ struct SourceCompressionTask
     size_t compressedBytes;
 
   public:
     explicit SourceCompressionTask(ExclusiveContext *cx)
       : cx(cx), ss(nullptr), abort_(false),
         result(OOM), compressed(nullptr), compressedBytes(0)
     {
 #ifdef JS_THREADSAFE
-        workerThread = nullptr;
+        helperThread = nullptr;
 #endif
     }
 
     ~SourceCompressionTask()
     {
         complete();
     }
 
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -845,18 +845,18 @@ JSRuntime::assertCanLock(RuntimeLock whi
 {
 #ifdef JS_THREADSAFE
     // In the switch below, each case falls through to the one below it. None
     // of the runtime locks are reentrant, and when multiple locks are acquired
     // it must be done in the order below.
     switch (which) {
       case ExclusiveAccessLock:
         JS_ASSERT(exclusiveAccessOwner != PR_GetCurrentThread());
-      case WorkerThreadStateLock:
-        JS_ASSERT(!WorkerThreadState().isLocked());
+      case HelperThreadStateLock:
+        JS_ASSERT(!HelperThreadState().isLocked());
       case InterruptLock:
         JS_ASSERT(!currentThreadOwnsInterruptLock());
       case GCLock:
         gc.assertCanLock();
         break;
       default:
         MOZ_CRASH();
     }
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -427,17 +427,17 @@ AtomStateOffsetToName(const JSAtomState 
     return *reinterpret_cast<js::ImmutablePropertyNamePtr *>((char*)&atomState + offset);
 }
 
 // There are several coarse locks in the enum below. These may be either
 // per-runtime or per-process. When acquiring more than one of these locks,
 // the acquisition must be done in the order below to avoid deadlocks.
 enum RuntimeLock {
     ExclusiveAccessLock,
-    WorkerThreadStateLock,
+    HelperThreadStateLock,
     InterruptLock,
     GCLock
 };
 
 #ifdef DEBUG
 void AssertCurrentThreadCanLock(RuntimeLock which);
 #else
 inline void AssertCurrentThreadCanLock(RuntimeLock which) {}
--- a/js/src/vm/ThreadPool.cpp
+++ b/js/src/vm/ThreadPool.cpp
@@ -285,17 +285,17 @@ ThreadPool::init()
     return true;
 #endif
 }
 
 uint32_t
 ThreadPool::numWorkers() const
 {
 #ifdef JS_THREADSAFE
-    return WorkerThreadState().cpuCount;
+    return HelperThreadState().cpuCount;
 #else
     return 1;
 #endif
 }
 
 bool
 ThreadPool::workStealing() const
 {
--- a/netwerk/protocol/http/HttpBaseChannel.cpp
+++ b/netwerk/protocol/http/HttpBaseChannel.cpp
@@ -10,16 +10,17 @@
 
 #include "mozilla/net/HttpBaseChannel.h"
 
 #include "nsHttpHandler.h"
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
 
 #include "nsICachingChannel.h"
+#include "nsIPrincipal.h"
 #include "nsISeekableStream.h"
 #include "nsITimedChannel.h"
 #include "nsIEncodedChannel.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIMutableArray.h"
 #include "nsEscape.h"
 #include "nsStreamListenerWrapper.h"
 #include "nsISecurityConsoleMessage.h"
@@ -1853,16 +1854,23 @@ HttpBaseChannel::SetupReplacementChannel
 
   // Do not pass along LOAD_CHECK_OFFLINE_CACHE
   newLoadFlags &= ~nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE;
 
   newChannel->SetLoadGroup(mLoadGroup);
   newChannel->SetNotificationCallbacks(mCallbacks);
   newChannel->SetLoadFlags(newLoadFlags);
 
+  // If our owner is a null principal it will have been set as a security
+  // measure, so we want to propagate it to the new channel.
+  nsCOMPtr<nsIPrincipal> ownerPrincipal = do_QueryInterface(mOwner);
+  if (ownerPrincipal && ownerPrincipal->GetIsNullPrincipal()) {
+    newChannel->SetOwner(mOwner);
+  }
+
   // Try to preserve the privacy bit if it has been overridden
   if (mPrivateBrowsingOverriden) {
     nsCOMPtr<nsIPrivateBrowsingChannel> newPBChannel =
       do_QueryInterface(newChannel);
     if (newPBChannel) {
       newPBChannel->SetPrivate(mPrivateBrowsing);
     }
   }
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -1754,24 +1754,21 @@ nsHttpConnection::MakeConnectString(nsAH
     request->SetVersion(gHttpHandler->HttpVersion());
     request->SetRequestURI(result);
     request->SetHeader(nsHttp::User_Agent, gHttpHandler->UserAgent());
 
     // a CONNECT is always persistent
     request->SetHeader(nsHttp::Proxy_Connection, NS_LITERAL_CSTRING("keep-alive"));
     request->SetHeader(nsHttp::Connection, NS_LITERAL_CSTRING("keep-alive"));
 
-    const char *val = trans->RequestHead()->PeekHeader(nsHttp::Host);
-    if (val) {
-        // all HTTP/1.1 requests must include a Host header (even though it
-        // may seem redundant in this case; see bug 82388).
-        request->SetHeader(nsHttp::Host, nsDependentCString(val));
-    }
+    // all HTTP/1.1 requests must include a Host header (even though it
+    // may seem redundant in this case; see bug 82388).
+    request->SetHeader(nsHttp::Host, result);
 
-    val = trans->RequestHead()->PeekHeader(nsHttp::Proxy_Authorization);
+    const char *val = trans->RequestHead()->PeekHeader(nsHttp::Proxy_Authorization);
     if (val) {
         // we don't know for sure if this authorization is intended for the
         // SSL proxy, so we add it just in case.
         request->SetHeader(nsHttp::Proxy_Authorization, nsDependentCString(val));
     }
 
     result.Truncate();
     request->Flatten(result, false);
--- a/security/build/Makefile.in
+++ b/security/build/Makefile.in
@@ -248,36 +248,17 @@ DEFAULT_GMAKE_FLAGS += MODULE_INCLUDES='
 
 # Work around NSS's MAKE_OBJDIR being racy. See bug #836220
 DEFAULT_GMAKE_FLAGS += MAKE_OBJDIR='$$(INSTALL) -D $$(OBJDIR)'
 
 # Work around NSS adding IMPORT_LIBRARY to TARGETS with no rule for
 # it, creating race conditions. See bug #836220
 DEFAULT_GMAKE_FLAGS += TARGETS='$$(LIBRARY) $$(SHARED_LIBRARY) $$(PROGRAM)'
 
-ifdef MOZ_NSS_PATCH
-# If we're applying a patch, we'll copy the NSS source to the objdir
-# and build it from there.
-NSS_SRCDIR = $(CURDIR)/nss
-
-# This will copy and patch the NSS source for every build.
-# Since we "cp -p", it won't force rebuilds for most files, just
-# for patched files, but that's easier than trying to track
-# dependencies for patched files.
-export::
-	rm -rf $(NSS_SRCDIR)
-	$(NSINSTALL) -D $(NSS_SRCDIR)/security
-	cp -Rp $(topsrcdir)/security/nss $(NSS_SRCDIR)/security
-	cp -Rp $(topsrcdir)/security/coreconf $(NSS_SRCDIR)/security
-	cp -Rp $(topsrcdir)/security/dbm $(NSS_SRCDIR)/security
-	cp -Rp $(topsrcdir)/dbm $(NSS_SRCDIR)
-	(cd $(NSS_SRCDIR) && patch -p1 < $(abspath $(MOZ_NSS_PATCH)))
-else
 NSS_SRCDIR = $(topsrcdir)
-endif
 
 NSS_DIRS =
 ifndef MOZ_FOLD_LIBS
 NSS_DIRS += nss/lib
 else
 ifndef NSS_DISABLE_DBM
 NSS_DIRS += nss/lib/dbm
 endif
--- a/security/certverifier/ExtendedValidation.cpp
+++ b/security/certverifier/ExtendedValidation.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ExtendedValidation.h"
 
 #include "cert.h"
 #include "certdb.h"
 #include "base64.h"
+#include "hasht.h"
 #include "pkix/nullptr.h"
 #include "pkix/pkixtypes.h"
 #include "pk11pub.h"
 #include "secerr.h"
 #include "prerror.h"
 #include "prinit.h"
 
 #ifdef PR_LOGGING
@@ -24,17 +25,17 @@ extern PRLogModuleInfo* gPIPNSSLog;
 #define OI(x) { siDEROID, (unsigned char*) x, sizeof x }
 
 struct nsMyTrustedEVInfo
 {
   const char* dotted_oid;
   const char* oid_name; // Set this to null to signal an invalid structure,
                   // (We can't have an empty list, so we'll use a dummy entry)
   SECOidTag oid_tag;
-  const unsigned char ev_root_sha1_fingerprint[20];
+  const unsigned char ev_root_sha256_fingerprint[SHA256_LENGTH];
   const char* issuer_base64;
   const char* serial_base64;
   CERTCertificate* cert;
 };
 
 // HOWTO enable additional CA root certificates for EV:
 //
 // For each combination of "root certificate" and "policy OID",
@@ -46,17 +47,17 @@ struct nsMyTrustedEVInfo
 // use plain text representation, we rather use the original encoding
 // as it can be found in the root certificate (in base64 format).
 //
 // We can use the NSS utility named "pp" to extract the encoding.
 //
 // Build standalone NSS including the NSS tools, then run
 //   pp -t certificate-identity -i the-cert-filename
 //
-// You will need the output from sections "Issuer", "Fingerprint (SHA1)",
+// You will need the output from sections "Issuer", "Fingerprint (SHA-256)",
 // "Issuer DER Base64" and "Serial DER Base64".
 //
 // The new section consists of 8 lines:
 //
 // - a comment that should contain the human readable issuer name
 //   of the certificate, as printed by the pp tool
 // - the EV policy OID that is associated to the EV grant
 // - a text description of the EV policy OID. The array can contain
@@ -65,27 +66,27 @@ struct nsMyTrustedEVInfo
 //   all entries with the same policy OID (use the text search
 //   feature of your text editor to find duplicates).
 //   When adding a new policy OID that is not yet contained in the array,
 //   please make sure that your new description is different from
 //   all the other descriptions (again use the text search feature
 //   to be sure).
 // - the constant SEC_OID_UNKNOWN
 //   (it will be replaced at runtime with another identifier)
-// - the SHA1 fingerprint
+// - the SHA-256 fingerprint
 // - the "Issuer DER Base64" as printed by the pp tool.
 //   Remove all whitespaces. If you use multiple lines, make sure that
 //   only the final line will be followed by a comma.
 // - the "Serial DER Base64" (as printed by pp)
 // - nullptr
 //
 // After adding an entry, test it locally against the test site that
 // has been provided by the CA. Note that you must use a version of NSS
 // where the root certificate has already been added and marked as trusted
-// for issueing SSL server certificates (at least).
+// for issuing SSL server certificates (at least).
 //
 // If you are able to connect to the site without certificate errors,
 // but you don't see the EV status indicator, then most likely the CA
 // has a problem in their infrastructure. The most common problems are
 // related to the CA's OCSP infrastructure, either they use an incorrect
 // OCSP signing certificate, or OCSP for the intermediate certificates
 // isn't working, or OCSP isn't working at all.
 
@@ -102,714 +103,769 @@ static struct nsMyTrustedEVInfo myTruste
   // certs are skipped as these debug EV certs are NOT part of the default trust
   // store.
   {
     // This is the testing EV signature (xpcshell) (RSA)
     // CN=XPCShell EV Testing (untrustworthy) CA,OU=Security Engineering,O=Mozilla - EV debug test CA,L=Mountain View,ST=CA,C=US"
     "1.3.6.1.4.1.13769.666.666.666.1.500.9.1",
     "DEBUGtesting EV OID",
     SEC_OID_UNKNOWN,
-    { 0x9C, 0x62, 0xEF, 0xDB, 0xAE, 0xF9, 0xEB, 0x36, 0x58, 0xFB,
-      0x3B, 0xD3, 0x47, 0x64, 0x93, 0x9D, 0x86, 0x29, 0x6A, 0xE0 },
+    { 0x2D, 0x94, 0x52, 0x70, 0xAA, 0x92, 0x13, 0x0B, 0x1F, 0xB1, 0x24,
+      0x0B, 0x24, 0xB1, 0xEE, 0x4E, 0xFB, 0x7C, 0x43, 0x45, 0x45, 0x7F,
+      0x97, 0x6C, 0x90, 0xBF, 0xD4, 0x8A, 0x04, 0x79, 0xE4, 0x68 },
     "MIGnMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWlu"
     "IFZpZXcxIzAhBgNVBAoMGk1vemlsbGEgLSBFViBkZWJ1ZyB0ZXN0IENBMR0wGwYD"
     "VQQLDBRTZWN1cml0eSBFbmdpbmVlcmluZzEvMC0GA1UEAwwmWFBDU2hlbGwgRVYg"
     "VGVzdGluZyAodW50cnVzdHdvcnRoeSkgQ0E=",
     "At+3zdo=",
     nullptr
   },
 #endif
   {
     // OU=Security Communication EV RootCA1,O="SECOM Trust Systems CO.,LTD.",C=JP
     "1.2.392.200091.100.721.1",
     "SECOM EV OID",
     SEC_OID_UNKNOWN,
-    { 0xFE, 0xB8, 0xC4, 0x32, 0xDC, 0xF9, 0x76, 0x9A, 0xCE, 0xAE,
-      0x3D, 0xD8, 0x90, 0x8F, 0xFD, 0x28, 0x86, 0x65, 0x64, 0x7D },
+    { 0xA2, 0x2D, 0xBA, 0x68, 0x1E, 0x97, 0x37, 0x6E, 0x2D, 0x39, 0x7D,
+      0x72, 0x8A, 0xAE, 0x3A, 0x9B, 0x62, 0x96, 0xB9, 0xFD, 0xBA, 0x60,
+      0xBC, 0x2E, 0x11, 0xF6, 0x47, 0xF2, 0xC6, 0x75, 0xFB, 0x37 },
     "MGAxCzAJBgNVBAYTAkpQMSUwIwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENP"
     "LixMVEQuMSowKAYDVQQLEyFTZWN1cml0eSBDb21tdW5pY2F0aW9uIEVWIFJvb3RD"
     "QTE=",
     "AA==",
     nullptr
   },
   {
     // CN=Cybertrust Global Root,O=Cybertrust, Inc
     "1.3.6.1.4.1.6334.1.100.1",
     "Cybertrust EV OID",
     SEC_OID_UNKNOWN,
-    { 0x5F, 0x43, 0xE5, 0xB1, 0xBF, 0xF8, 0x78, 0x8C, 0xAC, 0x1C,
-      0xC7, 0xCA, 0x4A, 0x9A, 0xC6, 0x22, 0x2B, 0xCC, 0x34, 0xC6 },
+    { 0x96, 0x0A, 0xDF, 0x00, 0x63, 0xE9, 0x63, 0x56, 0x75, 0x0C, 0x29,
+      0x65, 0xDD, 0x0A, 0x08, 0x67, 0xDA, 0x0B, 0x9C, 0xBD, 0x6E, 0x77,
+      0x71, 0x4A, 0xEA, 0xFB, 0x23, 0x49, 0xAB, 0x39, 0x3D, 0xA3 },
     "MDsxGDAWBgNVBAoTD0N5YmVydHJ1c3QsIEluYzEfMB0GA1UEAxMWQ3liZXJ0cnVz"
     "dCBHbG9iYWwgUm9vdA==",
     "BAAAAAABD4WqLUg=",
     nullptr
   },
   {
     // CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH
     "2.16.756.1.89.1.2.1.1",
     "SwissSign EV OID",
     SEC_OID_UNKNOWN,
-    { 0xD8, 0xC5, 0x38, 0x8A, 0xB7, 0x30, 0x1B, 0x1B, 0x6E, 0xD4,
-      0x7A, 0xE6, 0x45, 0x25, 0x3A, 0x6F, 0x9F, 0x1A, 0x27, 0x61 },
+    { 0x62, 0xDD, 0x0B, 0xE9, 0xB9, 0xF5, 0x0A, 0x16, 0x3E, 0xA0, 0xF8,
+      0xE7, 0x5C, 0x05, 0x3B, 0x1E, 0xCA, 0x57, 0xEA, 0x55, 0xC8, 0x68,
+      0x8F, 0x64, 0x7C, 0x68, 0x81, 0xF2, 0xC8, 0x35, 0x7B, 0x95 },
     "MEUxCzAJBgNVBAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMT"
     "FlN3aXNzU2lnbiBHb2xkIENBIC0gRzI=",
     "ALtAHEP1Xk+w",
     nullptr
   },
   {
     // CN=StartCom Certification Authority,OU=Secure Digital Certificate Signing,O=StartCom Ltd.,C=IL
     "1.3.6.1.4.1.23223.1.1.1",
     "StartCom EV OID",
     SEC_OID_UNKNOWN,
-    { 0x3E, 0x2B, 0xF7, 0xF2, 0x03, 0x1B, 0x96, 0xF3, 0x8C, 0xE6,
-      0xC4, 0xD8, 0xA8, 0x5D, 0x3E, 0x2D, 0x58, 0x47, 0x6A, 0x0F },
+    { 0xC7, 0x66, 0xA9, 0xBE, 0xF2, 0xD4, 0x07, 0x1C, 0x86, 0x3A, 0x31,
+      0xAA, 0x49, 0x20, 0xE8, 0x13, 0xB2, 0xD1, 0x98, 0x60, 0x8C, 0xB7,
+      0xB7, 0xCF, 0xE2, 0x11, 0x43, 0xB8, 0x36, 0xDF, 0x09, 0xEA },
     "MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQL"
     "EyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBT"
     "dGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
     "AQ==",
     nullptr
   },
   {
     // CN=StartCom Certification Authority,OU=Secure Digital Certificate Signing,O=StartCom Ltd.,C=IL
     "1.3.6.1.4.1.23223.1.1.1",
     "StartCom EV OID",
     SEC_OID_UNKNOWN,
-    { 0xA3, 0xF1, 0x33, 0x3F, 0xE2, 0x42, 0xBF, 0xCF, 0xC5, 0xD1,
-      0x4E, 0x8F, 0x39, 0x42, 0x98, 0x40, 0x68, 0x10, 0xD1, 0xA0 },
+    { 0xE1, 0x78, 0x90, 0xEE, 0x09, 0xA3, 0xFB, 0xF4, 0xF4, 0x8B, 0x9C,
+      0x41, 0x4A, 0x17, 0xD6, 0x37, 0xB7, 0xA5, 0x06, 0x47, 0xE9, 0xBC,
+      0x75, 0x23, 0x22, 0x72, 0x7F, 0xCC, 0x17, 0x42, 0xA9, 0x11 },
     "MH0xCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSswKQYDVQQL"
     "EyJTZWN1cmUgRGlnaXRhbCBDZXJ0aWZpY2F0ZSBTaWduaW5nMSkwJwYDVQQDEyBT"
     "dGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
     "LQ==",
     nullptr
   },
   {
     // CN=StartCom Certification Authority G2,O=StartCom Ltd.,C=IL
     "1.3.6.1.4.1.23223.1.1.1",
     "StartCom EV OID",
     SEC_OID_UNKNOWN,
-    { 0x31, 0xF1, 0xFD, 0x68, 0x22, 0x63, 0x20, 0xEE, 0xC6, 0x3B,
-      0x3F, 0x9D, 0xEA, 0x4A, 0x3E, 0x53, 0x7C, 0x7C, 0x39, 0x17 },
+    { 0xC7, 0xBA, 0x65, 0x67, 0xDE, 0x93, 0xA7, 0x98, 0xAE, 0x1F, 0xAA,
+      0x79, 0x1E, 0x71, 0x2D, 0x37, 0x8F, 0xAE, 0x1F, 0x93, 0xC4, 0x39,
+      0x7F, 0xEA, 0x44, 0x1B, 0xB7, 0xCB, 0xE6, 0xFD, 0x59, 0x95 },
     "MFMxCzAJBgNVBAYTAklMMRYwFAYDVQQKEw1TdGFydENvbSBMdGQuMSwwKgYDVQQD"
     "EyNTdGFydENvbSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBHMg==",
     "Ow==",
     nullptr
   },
   {
     // CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU="(c) 2006 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
     "2.16.840.1.113733.1.7.23.6",
     "VeriSign EV OID",
     SEC_OID_UNKNOWN,
-    { 0x4E, 0xB6, 0xD5, 0x78, 0x49, 0x9B, 0x1C, 0xCF, 0x5F, 0x58,
-      0x1E, 0xAD, 0x56, 0xBE, 0x3D, 0x9B, 0x67, 0x44, 0xA5, 0xE5 },
+    { 0x9A, 0xCF, 0xAB, 0x7E, 0x43, 0xC8, 0xD8, 0x80, 0xD0, 0x6B, 0x26,
+      0x2A, 0x94, 0xDE, 0xEE, 0xE4, 0xB4, 0x65, 0x99, 0x89, 0xC3, 0xD0,
+      0xCA, 0xF1, 0x9B, 0xAF, 0x64, 0x05, 0xE4, 0x1A, 0xB7, 0xDF },
     "MIHKMQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV"
     "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA2IFZl"
     "cmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMT"
     "PFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBB"
     "dXRob3JpdHkgLSBHNQ==",
     "GNrRniZ96LtKIVjNzGs7Sg==",
     nullptr
   },
   {
     // CN=GeoTrust Primary Certification Authority,O=GeoTrust Inc.,C=US
     "1.3.6.1.4.1.14370.1.6",
     "GeoTrust EV OID",
     SEC_OID_UNKNOWN,
-    { 0x32, 0x3C, 0x11, 0x8E, 0x1B, 0xF7, 0xB8, 0xB6, 0x52, 0x54,
-      0xE2, 0xE2, 0x10, 0x0D, 0xD6, 0x02, 0x90, 0x37, 0xF0, 0x96 },
+    { 0x37, 0xD5, 0x10, 0x06, 0xC5, 0x12, 0xEA, 0xAB, 0x62, 0x64, 0x21,
+      0xF1, 0xEC, 0x8C, 0x92, 0x01, 0x3F, 0xC5, 0xF8, 0x2A, 0xE9, 0x8E,
+      0xE5, 0x33, 0xEB, 0x46, 0x19, 0xB8, 0xDE, 0xB4, 0xD0, 0x6C },
     "MFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQD"
     "EyhHZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
     "GKy1av1pthU6Y2yv2vrEoQ==",
     nullptr
   },
   {
     // CN=thawte Primary Root CA,OU="(c) 2006 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US
     "2.16.840.1.113733.1.7.48.1",
     "Thawte EV OID",
     SEC_OID_UNKNOWN,
-    { 0x91, 0xC6, 0xD6, 0xEE, 0x3E, 0x8A, 0xC8, 0x63, 0x84, 0xE5,
-      0x48, 0xC2, 0x99, 0x29, 0x5C, 0x75, 0x6C, 0x81, 0x7B, 0x81 },
+    { 0x8D, 0x72, 0x2F, 0x81, 0xA9, 0xC1, 0x13, 0xC0, 0x79, 0x1D, 0xF1,
+      0x36, 0xA2, 0x96, 0x6D, 0xB2, 0x6C, 0x95, 0x0A, 0x97, 0x1D, 0xB4,
+      0x6B, 0x41, 0x99, 0xF4, 0xEA, 0x54, 0xB7, 0x8B, 0xFB, 0x9F },
     "MIGpMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQL"
     "Ex9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykg"
     "MjAwNiB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0G"
     "A1UEAxMWdGhhd3RlIFByaW1hcnkgUm9vdCBDQQ==",
     "NE7VVyDV7exJ9C/ON9srbQ==",
     nullptr
   },
   {
     // CN=XRamp Global Certification Authority,O=XRamp Security Services Inc,OU=www.xrampsecurity.com,C=US
     "2.16.840.1.114404.1.1.2.4.1",
     "Trustwave EV OID",
     SEC_OID_UNKNOWN,
-    { 0xB8, 0x01, 0x86, 0xD1, 0xEB, 0x9C, 0x86, 0xA5, 0x41, 0x04,
-      0xCF, 0x30, 0x54, 0xF3, 0x4C, 0x52, 0xB7, 0xE5, 0x58, 0xC6 },
+    { 0xCE, 0xCD, 0xDC, 0x90, 0x50, 0x99, 0xD8, 0xDA, 0xDF, 0xC5, 0xB1,
+      0xD2, 0x09, 0xB7, 0x37, 0xCB, 0xE2, 0xC1, 0x8C, 0xFB, 0x2C, 0x10,
+      0xC0, 0xFF, 0x0B, 0xCF, 0x0D, 0x32, 0x86, 0xFC, 0x1A, 0xA2 },
     "MIGCMQswCQYDVQQGEwJVUzEeMBwGA1UECxMVd3d3LnhyYW1wc2VjdXJpdHkuY29t"
     "MSQwIgYDVQQKExtYUmFtcCBTZWN1cml0eSBTZXJ2aWNlcyBJbmMxLTArBgNVBAMT"
     "JFhSYW1wIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
     "UJRs7Bjq1ZxN1ZfvdY+grQ==",
     nullptr
   },
   {
     // CN=SecureTrust CA,O=SecureTrust Corporation,C=US
     "2.16.840.1.114404.1.1.2.4.1",
     "Trustwave EV OID",
     SEC_OID_UNKNOWN,
-    { 0x87, 0x82, 0xC6, 0xC3, 0x04, 0x35, 0x3B, 0xCF, 0xD2, 0x96,
-      0x92, 0xD2, 0x59, 0x3E, 0x7D, 0x44, 0xD9, 0x34, 0xFF, 0x11 },
+    { 0xF1, 0xC1, 0xB5, 0x0A, 0xE5, 0xA2, 0x0D, 0xD8, 0x03, 0x0E, 0xC9,
+      0xF6, 0xBC, 0x24, 0x82, 0x3D, 0xD3, 0x67, 0xB5, 0x25, 0x57, 0x59,
+      0xB4, 0xE7, 0x1B, 0x61, 0xFC, 0xE9, 0xF7, 0x37, 0x5D, 0x73 },
     "MEgxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlv"
     "bjEXMBUGA1UEAxMOU2VjdXJlVHJ1c3QgQ0E=",
     "DPCOXAgWpa1Cf/DrJxhZ0A==",
     nullptr
   },
   {
     // CN=Secure Global CA,O=SecureTrust Corporation,C=US
     "2.16.840.1.114404.1.1.2.4.1",
     "Trustwave EV OID",
     SEC_OID_UNKNOWN,
-    { 0x3A, 0x44, 0x73, 0x5A, 0xE5, 0x81, 0x90, 0x1F, 0x24, 0x86,
-      0x61, 0x46, 0x1E, 0x3B, 0x9C, 0xC4, 0x5F, 0xF5, 0x3A, 0x1B },
+    { 0x42, 0x00, 0xF5, 0x04, 0x3A, 0xC8, 0x59, 0x0E, 0xBB, 0x52, 0x7D,
+      0x20, 0x9E, 0xD1, 0x50, 0x30, 0x29, 0xFB, 0xCB, 0xD4, 0x1C, 0xA1,
+      0xB5, 0x06, 0xEC, 0x27, 0xF1, 0x5A, 0xDE, 0x7D, 0xAC, 0x69 },
     "MEoxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdTZWN1cmVUcnVzdCBDb3Jwb3JhdGlv"
     "bjEZMBcGA1UEAxMQU2VjdXJlIEdsb2JhbCBDQQ==",
     "B1YipOjUiolN9BPI8PjqpQ==",
     nullptr
   },
   {
     // CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
     "1.3.6.1.4.1.6449.1.2.1.5.1",
     "Comodo EV OID",
     SEC_OID_UNKNOWN,
-    { 0x9F, 0x74, 0x4E, 0x9F, 0x2B, 0x4D, 0xBA, 0xEC, 0x0F, 0x31,
-      0x2C, 0x50, 0xB6, 0x56, 0x3B, 0x8E, 0x2D, 0x93, 0xC3, 0x11 },
+    { 0x17, 0x93, 0x92, 0x7A, 0x06, 0x14, 0x54, 0x97, 0x89, 0xAD, 0xCE,
+      0x2F, 0x8F, 0x34, 0xF7, 0xF0, 0xB6, 0x6D, 0x0F, 0x3A, 0xE3, 0xA3,
+      0xB8, 0x4D, 0x21, 0xEC, 0x15, 0xDB, 0xBA, 0x4F, 0xAD, 0xC7 },
     "MIGFMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAw"
     "DgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDErMCkG"
     "A1UEAxMiQ09NT0RPIEVDQyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
     "H0evqmIAcFBUTAGem2OZKg==",
     nullptr
   },
   {
     // CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB
     "1.3.6.1.4.1.6449.1.2.1.5.1",
     "Comodo EV OID",
     SEC_OID_UNKNOWN,
-    { 0x66, 0x31, 0xBF, 0x9E, 0xF7, 0x4F, 0x9E, 0xB6, 0xC9, 0xD5,
-      0xA6, 0x0C, 0xBA, 0x6A, 0xBE, 0xD1, 0xF7, 0xBD, 0xEF, 0x7B },
+    { 0x0C, 0x2C, 0xD6, 0x3D, 0xF7, 0x80, 0x6F, 0xA3, 0x99, 0xED, 0xE8,
+      0x09, 0x11, 0x6B, 0x57, 0x5B, 0xF8, 0x79, 0x89, 0xF0, 0x65, 0x18,
+      0xF9, 0x80, 0x8C, 0x86, 0x05, 0x03, 0x17, 0x8B, 0xAF, 0x66 },
     "MIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAw"
     "DgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDEnMCUG"
     "A1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
     "ToEtioJl4AsC7j41AkblPQ==",
     nullptr
   },
   {
     // CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE
     "1.3.6.1.4.1.6449.1.2.1.5.1",
     "Comodo EV OID",
     SEC_OID_UNKNOWN,
-    { 0x02, 0xFA, 0xF3, 0xE2, 0x91, 0x43, 0x54, 0x68, 0x60, 0x78,
-      0x57, 0x69, 0x4D, 0xF5, 0xE4, 0x5B, 0x68, 0x85, 0x18, 0x68 },
+    { 0x68, 0x7F, 0xA4, 0x51, 0x38, 0x22, 0x78, 0xFF, 0xF0, 0xC8, 0xB1,
+      0x1F, 0x8D, 0x43, 0xD5, 0x76, 0x67, 0x1C, 0x6E, 0xB2, 0xBC, 0xEA,
+      0xB4, 0x13, 0xFB, 0x83, 0xD9, 0x65, 0xD0, 0x6D, 0x2F, 0xF2 },
     "MG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMd"
     "QWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0"
     "IEV4dGVybmFsIENBIFJvb3Q=",
     "AQ==",
     nullptr
   },
   {
     // CN=UTN - DATACorp SGC,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US
     "1.3.6.1.4.1.6449.1.2.1.5.1",
     "Comodo EV OID",
     SEC_OID_UNKNOWN,
-    { 0x58, 0x11, 0x9F, 0x0E, 0x12, 0x82, 0x87, 0xEA, 0x50, 0xFD,
-      0xD9, 0x87, 0x45, 0x6F, 0x4F, 0x78, 0xDC, 0xFA, 0xD6, 0xD4 },
+    { 0x85, 0xFB, 0x2F, 0x91, 0xDD, 0x12, 0x27, 0x5A, 0x01, 0x45, 0xB6,
+      0x36, 0x53, 0x4F, 0x84, 0x02, 0x4A, 0xD6, 0x8B, 0x69, 0xB8, 0xEE,
+      0x88, 0x68, 0x4F, 0xF7, 0x11, 0x37, 0x58, 0x05, 0xB3, 0x48 },
     "MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFr"
     "ZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsT"
     "GGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNv"
     "cnAgU0dD",
     "RL4Mi1AAIbQR0ypoBqmtaQ==",
     nullptr
   },
   {
     // CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US
     "1.3.6.1.4.1.6449.1.2.1.5.1",
     "Comodo EV OID",
     SEC_OID_UNKNOWN,
-    { 0x04, 0x83, 0xED, 0x33, 0x99, 0xAC, 0x36, 0x08, 0x05, 0x87,
-      0x22, 0xED, 0xBC, 0x5E, 0x46, 0x00, 0xE3, 0xBE, 0xF9, 0xD7 },
+    { 0x6E, 0xA5, 0x47, 0x41, 0xD0, 0x04, 0x66, 0x7E, 0xED, 0x1B, 0x48,
+      0x16, 0x63, 0x4A, 0xA3, 0xA7, 0x9E, 0x6E, 0x4B, 0x96, 0x95, 0x0F,
+      0x82, 0x79, 0xDA, 0xFC, 0x8D, 0x9B, 0xD8, 0x81, 0x21, 0x37 },
     "MIGXMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFr"
     "ZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsT"
     "GGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTEfMB0GA1UEAxMWVVROLVVTRVJGaXJz"
     "dC1IYXJkd2FyZQ==",
     "RL4Mi1AAJLQR0zYq/mUK/Q==",
     nullptr
   },
   {
     // OU=Go Daddy Class 2 Certification Authority,O=\"The Go Daddy Group, Inc.\",C=US
     "2.16.840.1.114413.1.7.23.3",
     "Go Daddy EV OID a",
     SEC_OID_UNKNOWN,
-    { 0x27, 0x96, 0xBA, 0xE6, 0x3F, 0x18, 0x01, 0xE2, 0x77, 0x26,
-      0x1B, 0xA0, 0xD7, 0x77, 0x70, 0x02, 0x8F, 0x20, 0xEE, 0xE4 },
+    { 0xC3, 0x84, 0x6B, 0xF2, 0x4B, 0x9E, 0x93, 0xCA, 0x64, 0x27, 0x4C,
+      0x0E, 0xC6, 0x7C, 0x1E, 0xCC, 0x5E, 0x02, 0x4F, 0xFC, 0xAC, 0xD2,
+      0xD7, 0x40, 0x19, 0x35, 0x0E, 0x81, 0xFE, 0x54, 0x6A, 0xE4 },
     "MGMxCzAJBgNVBAYTAlVTMSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIElu"
     "Yy4xMTAvBgNVBAsTKEdvIERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRo"
     "b3JpdHk=",
     "AA==",
     nullptr
   },
   {
     // CN=Go Daddy Root Certificate Authority - G2,O="GoDaddy.com, Inc.",L=Scottsdale,ST=Arizona,C=US
     "2.16.840.1.114413.1.7.23.3",
     "Go Daddy EV OID a",
     SEC_OID_UNKNOWN,
-    { 0x47, 0xBE, 0xAB, 0xC9, 0x22, 0xEA, 0xE8, 0x0E, 0x78, 0x78,
-      0x34, 0x62, 0xA7, 0x9F, 0x45, 0xC2, 0x54, 0xFD, 0xE6, 0x8B },
+    { 0x45, 0x14, 0x0B, 0x32, 0x47, 0xEB, 0x9C, 0xC8, 0xC5, 0xB4, 0xF0,
+      0xD7, 0xB5, 0x30, 0x91, 0xF7, 0x32, 0x92, 0x08, 0x9E, 0x6E, 0x5A,
+      0x63, 0xE2, 0x74, 0x9D, 0xD3, 0xAC, 0xA9, 0x19, 0x8E, 0xDA },
     "MIGDMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2Nv"
     "dHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5jb20sIEluYy4xMTAvBgNVBAMTKEdv"
     "IERhZGR5IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzI=",
     "AA==",
     nullptr
   },
   {
     // OU=Starfield Class 2 Certification Authority,O=\"Starfield Technologies, Inc.\",C=US
     "2.16.840.1.114414.1.7.23.3",
     "Go Daddy EV OID b",
     SEC_OID_UNKNOWN,
-    { 0xAD, 0x7E, 0x1C, 0x28, 0xB0, 0x64, 0xEF, 0x8F, 0x60, 0x03,
-      0x40, 0x20, 0x14, 0xC3, 0xD0, 0xE3, 0x37, 0x0E, 0xB5, 0x8A },
+    { 0x14, 0x65, 0xFA, 0x20, 0x53, 0x97, 0xB8, 0x76, 0xFA, 0xA6, 0xF0,
+      0xA9, 0x95, 0x8E, 0x55, 0x90, 0xE4, 0x0F, 0xCC, 0x7F, 0xAA, 0x4F,
+      0xB7, 0xC2, 0xC8, 0x67, 0x75, 0x21, 0xFB, 0x5F, 0xB6, 0x58 },
     "MGgxCzAJBgNVBAYTAlVTMSUwIwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVz"
     "LCBJbmMuMTIwMAYDVQQLEylTdGFyZmllbGQgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9u"
     "IEF1dGhvcml0eQ==",
     "AA==",
     nullptr
   },
   {
     // CN=Starfield Root Certificate Authority - G2,O="Starfield Technologies, Inc.",L=Scottsdale,ST=Arizona,C=US
     "2.16.840.1.114414.1.7.23.3",
     "Go Daddy EV OID b",
     SEC_OID_UNKNOWN,
-    { 0xB5, 0x1C, 0x06, 0x7C, 0xEE, 0x2B, 0x0C, 0x3D, 0xF8, 0x55,
-      0xAB, 0x2D, 0x92, 0xF4, 0xFE, 0x39, 0xD4, 0xE7, 0x0F, 0x0E },
+    { 0x2C, 0xE1, 0xCB, 0x0B, 0xF9, 0xD2, 0xF9, 0xE1, 0x02, 0x99, 0x3F,
+      0xBE, 0x21, 0x51, 0x52, 0xC3, 0xB2, 0xDD, 0x0C, 0xAB, 0xDE, 0x1C,
+      0x68, 0xE5, 0x31, 0x9B, 0x83, 0x91, 0x54, 0xDB, 0xB7, 0xF5 },
     "MIGPMQswCQYDVQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2Nv"
     "dHRzZGFsZTElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEy"
     "MDAGA1UEAxMpU3RhcmZpZWxkIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0g"
     "RzI=",
     "AA==",
     nullptr
   },
   {
     // CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US
     "2.16.840.1.114412.2.1",
     "DigiCert EV OID",
     SEC_OID_UNKNOWN,
-    { 0x5F, 0xB7, 0xEE, 0x06, 0x33, 0xE2, 0x59, 0xDB, 0xAD, 0x0C,
-      0x4C, 0x9A, 0xE6, 0xD3, 0X8F, 0x1A, 0x61, 0xC7, 0xDC, 0x25 },
+    { 0x74, 0x31, 0xE5, 0xF4, 0xC3, 0xC1, 0xCE, 0x46, 0x90, 0x77, 0x4F,
+      0x0B, 0x61, 0xE0, 0x54, 0x40, 0x88, 0x3B, 0xA9, 0xA0, 0x1E, 0xD0,
+      0x0B, 0xA6, 0xAB, 0xD7, 0x80, 0x6E, 0xD3, 0xB1, 0x18, 0xCF },
     "MGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT"
     "EHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhpZ2ggQXNzdXJh"
     "bmNlIEVWIFJvb3QgQ0E=",
     "AqxcJmoLQJuPC3nyrkYldw==",
     nullptr
   },
   {
     // CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM
     "1.3.6.1.4.1.8024.0.2.100.1.2",
     "Quo Vadis EV OID",
     SEC_OID_UNKNOWN,
-    { 0xCA, 0x3A, 0xFB, 0xCF, 0x12, 0x40, 0x36, 0x4B, 0x44, 0xB2,
-      0x16, 0x20, 0x88, 0x80, 0x48, 0x39, 0x19, 0x93, 0x7C, 0xF7 },
+    { 0x85, 0xA0, 0xDD, 0x7D, 0xD7, 0x20, 0xAD, 0xB7, 0xFF, 0x05, 0xF8,
+      0x3D, 0x54, 0x2B, 0x20, 0x9D, 0xC7, 0xFF, 0x45, 0x28, 0xF7, 0xD6,
+      0x77, 0xB1, 0x83, 0x89, 0xFE, 0xA5, 0xE5, 0xC4, 0x9E, 0x86 },
     "MEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYD"
     "VQQDExJRdW9WYWRpcyBSb290IENBIDI=",
     "BQk=",
     nullptr
   },
   {
     // CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US
     "1.3.6.1.4.1.782.1.2.1.8.1",
     "Network Solutions EV OID",
     SEC_OID_UNKNOWN,
-    { 0x74, 0xF8, 0xA3, 0xC3, 0xEF, 0xE7, 0xB3, 0x90, 0x06, 0x4B,
-      0x83, 0x90, 0x3C, 0x21, 0x64, 0x60, 0x20, 0xE5, 0xDF, 0xCE },
+    { 0x15, 0xF0, 0xBA, 0x00, 0xA3, 0xAC, 0x7A, 0xF3, 0xAC, 0x88, 0x4C,
+      0x07, 0x2B, 0x10, 0x11, 0xA0, 0x77, 0xBD, 0x77, 0xC0, 0x97, 0xF4,
+      0x01, 0x64, 0xB2, 0xF8, 0x59, 0x8A, 0xBD, 0x83, 0x86, 0x0C },
     "MGIxCzAJBgNVBAYTAlVTMSEwHwYDVQQKExhOZXR3b3JrIFNvbHV0aW9ucyBMLkwu"
     "Qy4xMDAuBgNVBAMTJ05ldHdvcmsgU29sdXRpb25zIENlcnRpZmljYXRlIEF1dGhv"
     "cml0eQ==",
     "V8szb8JcFuZHFhfjkDFo4A==",
     nullptr
   },
   {
     // CN=Entrust Root Certification Authority,OU="(c) 2006 Entrust, Inc.",OU=www.entrust.net/CPS is incorporated by reference,O="Entrust, Inc.",C=US
     "2.16.840.1.114028.10.1.2",
     "Entrust EV OID",
     SEC_OID_UNKNOWN,
-    { 0xB3, 0x1E, 0xB1, 0xB7, 0x40, 0xE3, 0x6C, 0x84, 0x02, 0xDA,
-      0xDC, 0x37, 0xD4, 0x4D, 0xF5, 0xD4, 0x67, 0x49, 0x52, 0xF9 },
+    { 0x73, 0xC1, 0x76, 0x43, 0x4F, 0x1B, 0xC6, 0xD5, 0xAD, 0xF4, 0x5B,
+      0x0E, 0x76, 0xE7, 0x27, 0x28, 0x7C, 0x8D, 0xE5, 0x76, 0x16, 0xC1,
+      0xE6, 0xE6, 0x14, 0x1A, 0x2B, 0x2C, 0xBC, 0x7D, 0x8E, 0x4C },
     "MIGwMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjE5MDcGA1UE"
     "CxMwd3d3LmVudHJ1c3QubmV0L0NQUyBpcyBpbmNvcnBvcmF0ZWQgYnkgcmVmZXJl"
     "bmNlMR8wHQYDVQQLExYoYykgMjAwNiBFbnRydXN0LCBJbmMuMS0wKwYDVQQDEyRF"
     "bnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHk=",
     "RWtQVA==",
     nullptr
   },
   {
     // CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE
     "1.3.6.1.4.1.4146.1.1",
     "GlobalSign EV OID",
     SEC_OID_UNKNOWN,
-    { 0xB1, 0xBC, 0x96, 0x8B, 0xD4, 0xF4, 0x9D, 0x62, 0x2A, 0xA8,
-      0x9A, 0x81, 0xF2, 0x15, 0x01, 0x52, 0xA4, 0x1D, 0x82, 0x9C },
+    { 0xEB, 0xD4, 0x10, 0x40, 0xE4, 0xBB, 0x3E, 0xC7, 0x42, 0xC9, 0xE3,
+      0x81, 0xD3, 0x1E, 0xF2, 0xA4, 0x1A, 0x48, 0xB6, 0x68, 0x5C, 0x96,
+      0xE7, 0xCE, 0xF3, 0xC1, 0xDF, 0x6C, 0xD4, 0x33, 0x1C, 0x99 },
     "MFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYD"
     "VQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxTaWduIFJvb3QgQ0E=",
     "BAAAAAABFUtaw5Q=",
     nullptr
   },
   {
     // CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R2
     "1.3.6.1.4.1.4146.1.1",
     "GlobalSign EV OID",
     SEC_OID_UNKNOWN,
-    { 0x75, 0xE0, 0xAB, 0xB6, 0x13, 0x85, 0x12, 0x27, 0x1C, 0x04,
-      0xF8, 0x5F, 0xDD, 0xDE, 0x38, 0xE4, 0xB7, 0x24, 0x2E, 0xFE },
+    { 0xCA, 0x42, 0xDD, 0x41, 0x74, 0x5F, 0xD0, 0xB8, 0x1E, 0xB9, 0x02,
+      0x36, 0x2C, 0xF9, 0xD8, 0xBF, 0x71, 0x9D, 0xA1, 0xBD, 0x1B, 0x1E,
+      0xFC, 0x94, 0x6F, 0x5B, 0x4C, 0x99, 0xF4, 0x2C, 0x1B, 0x9E },
     "MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMwEQYDVQQKEwpH"
     "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu",
     "BAAAAAABD4Ym5g0=",
     nullptr
   },
   {
     // CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3
     "1.3.6.1.4.1.4146.1.1",
     "GlobalSign EV OID",
     SEC_OID_UNKNOWN,
-    { 0xD6, 0x9B, 0x56, 0x11, 0x48, 0xF0, 0x1C, 0x77, 0xC5, 0x45,
-      0x78, 0xC1, 0x09, 0x26, 0xDF, 0x5B, 0x85, 0x69, 0x76, 0xAD },
+    { 0xCB, 0xB5, 0x22, 0xD7, 0xB7, 0xF1, 0x27, 0xAD, 0x6A, 0x01, 0x13,
+      0x86, 0x5B, 0xDF, 0x1C, 0xD4, 0x10, 0x2E, 0x7D, 0x07, 0x59, 0xAF,
+      0x63, 0x5A, 0x7C, 0xF4, 0x72, 0x0D, 0xC9, 0x63, 0xC5, 0x3B },
     "MEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIzMRMwEQYDVQQKEwpH"
     "bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu",
     "BAAAAAABIVhTCKI=",
     nullptr
   },
   {
     // CN=Buypass Class 3 CA 1,O=Buypass AS-983163327,C=NO
     "2.16.578.1.26.1.3.3",
     "Buypass EV OID",
     SEC_OID_UNKNOWN,
-    { 0x61, 0x57, 0x3A, 0x11, 0xDF, 0x0E, 0xD8, 0x7E, 0xD5, 0x92,
-      0x65, 0x22, 0xEA, 0xD0, 0x56, 0xD7, 0x44, 0xB3, 0x23, 0x71 },
+    { 0xB7, 0xB1, 0x2B, 0x17, 0x1F, 0x82, 0x1D, 0xAA, 0x99, 0x0C, 0xD0,
+      0xFE, 0x50, 0x87, 0xB1, 0x28, 0x44, 0x8B, 0xA8, 0xE5, 0x18, 0x4F,
+      0x84, 0xC5, 0x1E, 0x02, 0xB5, 0xC8, 0xFB, 0x96, 0x2B, 0x24 },
     "MEsxCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEd"
     "MBsGA1UEAwwUQnV5cGFzcyBDbGFzcyAzIENBIDE=",
     "Ag==",
     nullptr
   },
   {
     // CN=Buypass Class 3 Root CA,O=Buypass AS-983163327,C=NO
     "2.16.578.1.26.1.3.3",
     "Buypass EV OID",
     SEC_OID_UNKNOWN,
-    { 0xDA, 0xFA, 0xF7, 0xFA, 0x66, 0x84, 0xEC, 0x06, 0x8F, 0x14,
-      0x50, 0xBD, 0xC7, 0xC2, 0x81, 0xA5, 0xBC, 0xA9, 0x64, 0x57 },
+    { 0xED, 0xF7, 0xEB, 0xBC, 0xA2, 0x7A, 0x2A, 0x38, 0x4D, 0x38, 0x7B,
+      0x7D, 0x40, 0x10, 0xC6, 0x66, 0xE2, 0xED, 0xB4, 0x84, 0x3E, 0x4C,
+      0x29, 0xB4, 0xAE, 0x1D, 0x5B, 0x93, 0x32, 0xE6, 0xB2, 0x4D },
     "ME4xCzAJBgNVBAYTAk5PMR0wGwYDVQQKDBRCdXlwYXNzIEFTLTk4MzE2MzMyNzEg"
     "MB4GA1UEAwwXQnV5cGFzcyBDbGFzcyAzIFJvb3QgQ0E=",
     "Ag==",
     nullptr
   },
   {
     // CN=Class 2 Primary CA,O=Certplus,C=FR
     "1.3.6.1.4.1.22234.2.5.2.3.1",
     "Certplus EV OID",
     SEC_OID_UNKNOWN,
-    { 0x74, 0x20, 0x74, 0x41, 0x72, 0x9C, 0xDD, 0x92, 0xEC, 0x79,
-      0x31, 0xD8, 0x23, 0x10, 0x8D, 0xC2, 0x81, 0x92, 0xE2, 0xBB },
+    { 0x0F, 0x99, 0x3C, 0x8A, 0xEF, 0x97, 0xBA, 0xAF, 0x56, 0x87, 0x14,
+      0x0E, 0xD5, 0x9A, 0xD1, 0x82, 0x1B, 0xB4, 0xAF, 0xAC, 0xF0, 0xAA,
+      0x9A, 0x58, 0xB5, 0xD5, 0x7A, 0x33, 0x8A, 0x3A, 0xFB, 0xCB },
     "MD0xCzAJBgNVBAYTAkZSMREwDwYDVQQKEwhDZXJ0cGx1czEbMBkGA1UEAxMSQ2xh"
     "c3MgMiBQcmltYXJ5IENB",
     "AIW9S/PY2uNp9pTXX8OlRCM=",
     nullptr
   },
   {
     // CN=Chambers of Commerce Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU
     "1.3.6.1.4.1.17326.10.14.2.1.2",
     "Camerfirma EV OID a",
     SEC_OID_UNKNOWN,
-    { 0x78, 0x6A, 0x74, 0xAC, 0x76, 0xAB, 0x14, 0x7F, 0x9C, 0x6A,
-      0x30, 0x50, 0xBA, 0x9E, 0xA8, 0x7E, 0xFE, 0x9A, 0xCE, 0x3C },
+    { 0x06, 0x3E, 0x4A, 0xFA, 0xC4, 0x91, 0xDF, 0xD3, 0x32, 0xF3, 0x08,
+      0x9B, 0x85, 0x42, 0xE9, 0x46, 0x17, 0xD8, 0x93, 0xD7, 0xFE, 0x94,
+      0x4E, 0x10, 0xA7, 0x93, 0x7E, 0xE2, 0x9D, 0x96, 0x93, 0xC0 },
     "MIGuMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBh"
     "ZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ"
     "QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMT"
     "IENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4",
     "AKPaQn6ksa7a",
     nullptr
   },
   {
     // CN=Global Chambersign Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU
     "1.3.6.1.4.1.17326.10.8.12.1.2",
     "Camerfirma EV OID b",
     SEC_OID_UNKNOWN,
-    { 0x4A, 0xBD, 0xEE, 0xEC, 0x95, 0x0D, 0x35, 0x9C, 0x89, 0xAE,
-      0xC7, 0x52, 0xA1, 0x2C, 0x5B, 0x29, 0xF6, 0xD6, 0xAA, 0x0C },
+    { 0x13, 0x63, 0x35, 0x43, 0x93, 0x34, 0xA7, 0x69, 0x80, 0x16, 0xA0,
+      0xD3, 0x24, 0xDE, 0x72, 0x28, 0x4E, 0x07, 0x9D, 0x7B, 0x52, 0x20,
+      0xBB, 0x8F, 0xBD, 0x74, 0x78, 0x16, 0xEE, 0xBE, 0xBA, 0xCA },
     "MIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBh"
     "ZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ"
     "QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMT"
     "Hkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwOA==",
     "AMnN0+nVfSPO",
     nullptr
   },
   {
     // CN=TC TrustCenter Universal CA III,OU=TC TrustCenter Universal CA,O=TC TrustCenter GmbH,C=DE
     "1.2.276.0.44.1.1.1.4",
     "TC TrustCenter EV OID",
     SEC_OID_UNKNOWN,
-    { 0x96, 0x56, 0xCD, 0x7B, 0x57, 0x96, 0x98, 0x95, 0xD0, 0xE1,
-      0x41, 0x46, 0x68, 0x06, 0xFB, 0xB8, 0xC6, 0x11, 0x06, 0x87 },
+    { 0x30, 0x9B, 0x4A, 0x87, 0xF6, 0xCA, 0x56, 0xC9, 0x31, 0x69, 0xAA,
+      0xA9, 0x9C, 0x6D, 0x98, 0x88, 0x54, 0xD7, 0x89, 0x2B, 0xD5, 0x43,
+      0x7E, 0x2D, 0x07, 0xB2, 0x9C, 0xBE, 0xDA, 0x55, 0xD3, 0x5D },
     "MHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRlciBHbWJIMSQw"
     "IgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAmBgNVBAMTH1RD"
     "IFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUk=",
     "YyUAAQACFI0zFQLkbPQ=",
     nullptr
   },
   {
     // CN=AffirmTrust Commercial,O=AffirmTrust,C=US
     "1.3.6.1.4.1.34697.2.1",
     "AffirmTrust EV OID a",
     SEC_OID_UNKNOWN,
-    { 0xF9, 0xB5, 0xB6, 0x32, 0x45, 0x5F, 0x9C, 0xBE, 0xEC, 0x57,
-      0x5F, 0x80, 0xDC, 0xE9, 0x6E, 0x2C, 0xC7, 0xB2, 0x78, 0xB7 },
+    { 0x03, 0x76, 0xAB, 0x1D, 0x54, 0xC5, 0xF9, 0x80, 0x3C, 0xE4, 0xB2,
+      0xE2, 0x01, 0xA0, 0xEE, 0x7E, 0xEF, 0x7B, 0x57, 0xB6, 0x36, 0xE8,
+      0xA9, 0x3C, 0x9B, 0x8D, 0x48, 0x60, 0xC9, 0x6F, 0x5F, 0xA7 },
     "MEQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEfMB0GA1UEAwwW"
     "QWZmaXJtVHJ1c3QgQ29tbWVyY2lhbA==",
     "d3cGJyapsXw=",
     nullptr
   },
   {
     // CN=AffirmTrust Networking,O=AffirmTrust,C=US
     "1.3.6.1.4.1.34697.2.2",
     "AffirmTrust EV OID b",
     SEC_OID_UNKNOWN,
-    { 0x29, 0x36, 0x21, 0x02, 0x8B, 0x20, 0xED, 0x02, 0xF5, 0x66,
-      0xC5, 0x32, 0xD1, 0xD6, 0xED, 0x90, 0x9F, 0x45, 0x00, 0x2F },
+    { 0x0A, 0x81, 0xEC, 0x5A, 0x92, 0x97, 0x77, 0xF1, 0x45, 0x90, 0x4A,
+      0xF3, 0x8D, 0x5D, 0x50, 0x9F, 0x66, 0xB5, 0xE2, 0xC5, 0x8F, 0xCD,
+      0xB5, 0x31, 0x05, 0x8B, 0x0E, 0x17, 0xF3, 0xF0, 0xB4, 0x1B },
     "MEQxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEfMB0GA1UEAwwW"
     "QWZmaXJtVHJ1c3QgTmV0d29ya2luZw==",
     "fE8EORzUmS0=",
     nullptr
   },
   {
     // CN=AffirmTrust Premium,O=AffirmTrust,C=US
     "1.3.6.1.4.1.34697.2.3",
     "AffirmTrust EV OID c",
     SEC_OID_UNKNOWN,
-    { 0xD8, 0xA6, 0x33, 0x2C, 0xE0, 0x03, 0x6F, 0xB1, 0x85, 0xF6,
-      0x63, 0x4F, 0x7D, 0x6A, 0x06, 0x65, 0x26, 0x32, 0x28, 0x27 },
+    { 0x70, 0xA7, 0x3F, 0x7F, 0x37, 0x6B, 0x60, 0x07, 0x42, 0x48, 0x90,
+      0x45, 0x34, 0xB1, 0x14, 0x82, 0xD5, 0xBF, 0x0E, 0x69, 0x8E, 0xCC,
+      0x49, 0x8D, 0xF5, 0x25, 0x77, 0xEB, 0xF2, 0xE9, 0x3B, 0x9A },
     "MEExCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEcMBoGA1UEAwwT"
     "QWZmaXJtVHJ1c3QgUHJlbWl1bQ==",
     "bYwURrGmCu4=",
     nullptr
   },
   {
     // CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US
     "1.3.6.1.4.1.34697.2.4",
     "AffirmTrust EV OID d",
     SEC_OID_UNKNOWN,
-    { 0xB8, 0x23, 0x6B, 0x00, 0x2F, 0x1D, 0x16, 0x86, 0x53, 0x01,
-      0x55, 0x6C, 0x11, 0xA4, 0x37, 0xCA, 0xEB, 0xFF, 0xC3, 0xBB },
+    { 0xBD, 0x71, 0xFD, 0xF6, 0xDA, 0x97, 0xE4, 0xCF, 0x62, 0xD1, 0x64,
+      0x7A, 0xDD, 0x25, 0x81, 0xB0, 0x7D, 0x79, 0xAD, 0xF8, 0x39, 0x7E,
+      0xB4, 0xEC, 0xBA, 0x9C, 0x5E, 0x84, 0x88, 0x82, 0x14, 0x23 },
     "MEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwX"
     "QWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0M=",
     "dJclisc/elQ=",
     nullptr
   },
   {
     // CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL
     "1.2.616.1.113527.2.5.1.1",
     "Certum EV OID",
     SEC_OID_UNKNOWN,
-    { 0x07, 0xE0, 0x32, 0xE0, 0x20, 0xB7, 0x2C, 0x3F, 0x19, 0x2F,
-      0x06, 0x28, 0xA2, 0x59, 0x3A, 0x19, 0xA7, 0x0F, 0x06, 0x9E },
+    { 0x5C, 0x58, 0x46, 0x8D, 0x55, 0xF5, 0x8E, 0x49, 0x7E, 0x74, 0x39,
+      0x82, 0xD2, 0xB5, 0x00, 0x10, 0xB6, 0xD1, 0x65, 0x37, 0x4A, 0xCF,
+      0x83, 0xA7, 0xD4, 0xA3, 0x2D, 0xB7, 0x68, 0xC4, 0x40, 0x8E },
     "MH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBT"
     "LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAg"
     "BgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0E=",
     "BETA",
     nullptr
   },
   {
     // CN=Izenpe.com,O=IZENPE S.A.,C=ES
     "1.3.6.1.4.1.14777.6.1.1",
     "Izenpe EV OID 1",
     SEC_OID_UNKNOWN,
-    { 0x2F, 0x78, 0x3D, 0x25, 0x52, 0x18, 0xA7, 0x4A, 0x65, 0x39,
-      0x71, 0xB5, 0x2C, 0xA2, 0x9C, 0x45, 0x15, 0x6F, 0xE9, 0x19 },
+    { 0x25, 0x30, 0xCC, 0x8E, 0x98, 0x32, 0x15, 0x02, 0xBA, 0xD9, 0x6F,
+      0x9B, 0x1F, 0xBA, 0x1B, 0x09, 0x9E, 0x2D, 0x29, 0x9E, 0x0F, 0x45,
+      0x48, 0xBB, 0x91, 0x4F, 0x36, 0x3B, 0xC0, 0xD4, 0x53, 0x1F },
     "MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwK"
     "SXplbnBlLmNvbQ==",
     "ALC3WhZIX7/hy/WL1xnmfQ==",
     nullptr
   },
   {
     // CN=Izenpe.com,O=IZENPE S.A.,C=ES
     "1.3.6.1.4.1.14777.6.1.2",
     "Izenpe EV OID 2",
     SEC_OID_UNKNOWN,
-    { 0x2F, 0x78, 0x3D, 0x25, 0x52, 0x18, 0xA7, 0x4A, 0x65, 0x39,
-      0x71, 0xB5, 0x2C, 0xA2, 0x9C, 0x45, 0x15, 0x6F, 0xE9, 0x19 },
+    { 0x25, 0x30, 0xCC, 0x8E, 0x98, 0x32, 0x15, 0x02, 0xBA, 0xD9, 0x6F,
+      0x9B, 0x1F, 0xBA, 0x1B, 0x09, 0x9E, 0x2D, 0x29, 0x9E, 0x0F, 0x45,
+      0x48, 0xBB, 0x91, 0x4F, 0x36, 0x3B, 0xC0, 0xD4, 0x53, 0x1F },
     "MDgxCzAJBgNVBAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjETMBEGA1UEAwwK"
     "SXplbnBlLmNvbQ==",
     "ALC3WhZIX7/hy/WL1xnmfQ==",
     nullptr
   },
   {
     // CN=A-Trust-nQual-03,OU=A-Trust-nQual-03,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT
     "1.2.40.0.17.1.22",
     "A-Trust EV OID",
     SEC_OID_UNKNOWN,
-    { 0xD3, 0xC0, 0x63, 0xF2, 0x19, 0xED, 0x07, 0x3E, 0x34, 0xAD,
-      0x5D, 0x75, 0x0B, 0x32, 0x76, 0x29, 0xFF, 0xD5, 0x9A, 0xF2 },
+    { 0x79, 0x3C, 0xBF, 0x45, 0x59, 0xB9, 0xFD, 0xE3, 0x8A, 0xB2, 0x2D,
+      0xF1, 0x68, 0x69, 0xF6, 0x98, 0x81, 0xAE, 0x14, 0xC4, 0xB0, 0x13,
+      0x9A, 0xC7, 0x88, 0xA7, 0x8A, 0x1A, 0xFC, 0xCA, 0x02, 0xFB },
     "MIGNMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hl"
     "cmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYD"
     "VQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAz",
     "AWwe",
     nullptr
   },
   {
     // CN=T-TeleSec GlobalRoot Class 3,OU=T-Systems Trust Center,O=T-Systems Enterprise Services GmbH,C=DE
     "1.3.6.1.4.1.7879.13.24.1",
     "T-Systems EV OID",
     SEC_OID_UNKNOWN,
-    { 0x55, 0xA6, 0x72, 0x3E, 0xCB, 0xF2, 0xEC, 0xCD, 0xC3, 0x23,
-      0x74, 0x70, 0x19, 0x9D, 0x2A, 0xBE, 0x11, 0xE3, 0x81, 0xD1 },
+    { 0xFD, 0x73, 0xDA, 0xD3, 0x1C, 0x64, 0x4F, 0xF1, 0xB4, 0x3B, 0xEF,
+      0x0C, 0xCD, 0xDA, 0x96, 0x71, 0x0B, 0x9C, 0xD9, 0x87, 0x5E, 0xCA,
+      0x7E, 0x31, 0x70, 0x7A, 0xF3, 0xE9, 0x6D, 0x52, 0x2B, 0xBD },
     "MIGCMQswCQYDVQQGEwJERTErMCkGA1UECgwiVC1TeXN0ZW1zIEVudGVycHJpc2Ug"
     "U2VydmljZXMgR21iSDEfMB0GA1UECwwWVC1TeXN0ZW1zIFRydXN0IENlbnRlcjEl"
     "MCMGA1UEAwwcVC1UZWxlU2VjIEdsb2JhbFJvb3QgQ2xhc3MgMw==",
     "AQ==",
     nullptr
   },
   {
     // CN=TURKTRUST Elektronik Sertifika Hizmet Saglayicisi,O=TURKTRUST Bilgi Illetisim ve Bilisim Guvenligi Hizmetleri A.S.,C=TR
     "2.16.792.3.0.3.1.1.5",
     "TurkTrust EV OID",
     SEC_OID_UNKNOWN,
-    { 0xF1, 0x7F, 0x6F, 0xB6, 0x31, 0xDC, 0x99, 0xE3, 0xA3, 0xC8,
-      0x7F, 0xFE, 0x1C, 0xF1, 0x81, 0x10, 0x88, 0xD9, 0x60, 0x33 },
+    { 0x97, 0x8C, 0xD9, 0x66, 0xF2, 0xFA, 0xA0, 0x7B, 0xA7, 0xAA, 0x95,
+      0x00, 0xD9, 0xC0, 0x2E, 0x9D, 0x77, 0xF2, 0xCD, 0xAD, 0xA6, 0xAD,
+      0x6B, 0xA7, 0x4A, 0xF4, 0xB9, 0x1C, 0x66, 0x59, 0x3C, 0x50 },
     "MIG/MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2VydGlmaWthIEhp"
     "em1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmth"
     "cmExXjBcBgNVBAoMVVTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBCaWxp"
     "xZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uIChjKSBBcmFsxLFrIDIw"
     "MDc=",
     "AQ==",
     nullptr
   },
   {
     // CN=China Internet Network Information Center EV Certificates Root,O=China Internet Network Information Center,C=CN
     "1.3.6.1.4.1.29836.1.10",
     "CNNIC EV OID",
     SEC_OID_UNKNOWN,
-    { 0x4F, 0x99, 0xAA, 0x93, 0xFB, 0x2B, 0xD1, 0x37, 0x26, 0xA1,
-      0x99, 0x4A, 0xCE, 0x7F, 0xF0, 0x05, 0xF2, 0x93, 0x5D, 0x1E },
+    { 0x1C, 0x01, 0xC6, 0xF4, 0xDB, 0xB2, 0xFE, 0xFC, 0x22, 0x55, 0x8B,
+      0x2B, 0xCA, 0x32, 0x56, 0x3F, 0x49, 0x84, 0x4A, 0xCF, 0xC3, 0x2B,
+      0x7B, 0xE4, 0xB0, 0xFF, 0x59, 0x9F, 0x9E, 0x8C, 0x7A, 0xF7 },
     "MIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29y"
     "ayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNoaW5hIEludGVybmV0IE5l"
     "dHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRlcyBSb290",
     "SJ8AAQ==",
     nullptr
   },
   {
     // CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW
     "1.3.6.1.4.1.40869.1.1.22.3",
     "TWCA EV OID",
     SEC_OID_UNKNOWN,
-    { 0xCF, 0x9E, 0x87, 0x6D, 0xD3, 0xEB, 0xFC, 0x42, 0x26, 0x97,
-      0xA3, 0xB5, 0xA3, 0x7A, 0xA0, 0x76, 0xA9, 0x06, 0x23, 0x48 },
+    { 0xBF, 0xD8, 0x8F, 0xE1, 0x10, 0x1C, 0x41, 0xAE, 0x3E, 0x80, 0x1B,
+      0xF8, 0xBE, 0x56, 0x35, 0x0E, 0xE9, 0xBA, 0xD1, 0xA6, 0xB9, 0xBD,
+      0x51, 0x5E, 0xDC, 0x5C, 0x6D, 0x5B, 0x87, 0x11, 0xAC, 0x44 },
     "MF8xCzAJBgNVBAYTAlRXMRIwEAYDVQQKDAlUQUlXQU4tQ0ExEDAOBgNVBAsMB1Jv"
     "b3QgQ0ExKjAoBgNVBAMMIVRXQ0EgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0"
     "eQ==",
     "AQ==",
     nullptr
   },
   {
     // CN=D-TRUST Root Class 3 CA 2 EV 2009,O=D-Trust GmbH,C=DE
     "1.3.6.1.4.1.4788.2.202.1",
     "D-TRUST EV OID",
     SEC_OID_UNKNOWN,
-    { 0x96, 0xC9, 0x1B, 0x0B, 0x95, 0xB4, 0x10, 0x98, 0x42, 0xFA,
-      0xD0, 0xD8, 0x22, 0x79, 0xFE, 0x60, 0xFA, 0xB9, 0x16, 0x83 },
+    { 0xEE, 0xC5, 0x49, 0x6B, 0x98, 0x8C, 0xE9, 0x86, 0x25, 0xB9, 0x34,
+      0x09, 0x2E, 0xEC, 0x29, 0x08, 0xBE, 0xD0, 0xB0, 0xF3, 0x16, 0xC2,
+      0xD4, 0x73, 0x0C, 0x84, 0xEA, 0xF1, 0xF3, 0xD3, 0x48, 0x81 },
     "MFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMM"
     "IUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOQ==",
     "CYP0",
     nullptr
   },
   {
     // CN=Swisscom Root EV CA 2,OU=Digital Certificate Services,O=Swisscom,C=ch
     "2.16.756.1.83.21.0",
     "Swisscom  EV OID",
     SEC_OID_UNKNOWN,
-    { 0xE7, 0xA1, 0x90, 0x29, 0xD3, 0xD5, 0x52, 0xDC, 0x0D, 0x0F,
-      0xC6, 0x92, 0xD3, 0xEA, 0x88, 0x0D, 0x15, 0x2E, 0x1A, 0x6B },
+    { 0xD9, 0x5F, 0xEA, 0x3C, 0xA4, 0xEE, 0xDC, 0xE7, 0x4C, 0xD7, 0x6E,
+      0x75, 0xFC, 0x6D, 0x1F, 0xF6, 0x2C, 0x44, 0x1F, 0x0F, 0xA8, 0xBC,
+      0x77, 0xF0, 0x34, 0xB1, 0x9E, 0x5D, 0xB2, 0x58, 0x01, 0x5D },
     "MGcxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln"
     "aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEeMBwGA1UEAxMVU3dpc3Njb20gUm9v"
     "dCBFViBDQSAy",
     "APL6ZOJ0Y9ON/RAdBB92ylg=",
     nullptr
   },
   {
     // CN=VeriSign Universal Root Certification Authority,OU="(c) 2008 VeriSign, Inc. - For authorized use only",OU=VeriSign Trust Network,O="VeriSign, Inc.",C=US
     "2.16.840.1.113733.1.7.23.6",
     "VeriSign EV OID",
     SEC_OID_UNKNOWN,
-    { 0x36, 0x79, 0xCA, 0x35, 0x66, 0x87, 0x72, 0x30, 0x4D, 0x30,
-      0xA5, 0xFB, 0x87, 0x3B, 0x0F, 0xA7, 0x7B, 0xB7, 0x0D, 0x54 },
+    { 0x23, 0x99, 0x56, 0x11, 0x27, 0xA5, 0x71, 0x25, 0xDE, 0x8C, 0xEF,
+      0xEA, 0x61, 0x0D, 0xDF, 0x2F, 0xA0, 0x78, 0xB5, 0xC8, 0x06, 0x7F,
+      0x4E, 0x82, 0x82, 0x90, 0xBF, 0xB8, 0x60, 0xE8, 0x4B, 0x3C },
     "MIG9MQswCQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNV"
     "BAsTFlZlcmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZl"
     "cmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMT"
     "L1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5",
     "QBrEZCGzEyEDDrvkEhrFHQ==",
     nullptr
   },
   {
     // CN=GeoTrust Primary Certification Authority - G3,OU=(c) 2008 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US
     "1.3.6.1.4.1.14370.1.6",
     "GeoTrust EV OID",
     SEC_OID_UNKNOWN,
-    { 0x03, 0x9E, 0xED, 0xB8, 0x0B, 0xE7, 0xA0, 0x3C, 0x69, 0x53,
-      0x89, 0x3B, 0x20, 0xD2, 0xD9, 0x32, 0x3A, 0x4C, 0x2A, 0xFD },
+    { 0xB4, 0x78, 0xB8, 0x12, 0x25, 0x0D, 0xF8, 0x78, 0x63, 0x5C, 0x2A,
+      0xA7, 0xEC, 0x7D, 0x15, 0x5E, 0xAA, 0x62, 0x5E, 0xE8, 0x29, 0x16,
+      0xE2, 0xCD, 0x29, 0x43, 0x61, 0x88, 0x6C, 0xD1, 0xFB, 0xD4 },
     "MIGYMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjE5MDcGA1UE"
     "CxMwKGMpIDIwMDggR2VvVHJ1c3QgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBv"
     "bmx5MTYwNAYDVQQDEy1HZW9UcnVzdCBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0"
     "aG9yaXR5IC0gRzM=",
     "FaxulBmyeUtB9iepwxgPHw==",
     nullptr
   },
   {
     // CN=thawte Primary Root CA - G3,OU="(c) 2008 thawte, Inc. - For authorized use only",OU=Certification Services Division,O="thawte, Inc.",C=US
     "2.16.840.1.113733.1.7.48.1",
     "Thawte EV OID",
     SEC_OID_UNKNOWN,
-    { 0xF1, 0x8B, 0x53, 0x8D, 0x1B, 0xE9, 0x03, 0xB6, 0xA6, 0xF0,
-      0x56, 0x43, 0x5B, 0x17, 0x15, 0x89, 0xCA, 0xF3, 0x6B, 0xF2 },
+    { 0x4B, 0x03, 0xF4, 0x58, 0x07, 0xAD, 0x70, 0xF2, 0x1B, 0xFC, 0x2C,
+      0xAE, 0x71, 0xC9, 0xFD, 0xE4, 0x60, 0x4C, 0x06, 0x4C, 0xF5, 0xFF,
+      0xB6, 0x86, 0xBA, 0xE5, 0xDB, 0xAA, 0xD7, 0xFD, 0xD3, 0x4C },
     "MIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3RlLCBJbmMuMSgwJgYDVQQL"
     "Ex9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYDVQQLEy8oYykg"
     "MjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG"
     "A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz",
     "YAGXt0an6rS0mtZLL/eQ+w==",
     nullptr
   },
   {
     // CN = Autoridad de Certificacion Firmaprofesional CIF A62634068, C = ES
     "1.3.6.1.4.1.13177.10.1.3.10",
     "Firmaprofesional EV OID",
     SEC_OID_UNKNOWN,
-    { 0xAE, 0xC5, 0xFB, 0x3F, 0xC8, 0xE1, 0xBF, 0xC4, 0xE5, 0x4F,
-      0x03, 0x07, 0x5A, 0x9A, 0xE8, 0x00, 0xB7, 0xF7, 0xB6, 0xFA },
+    { 0x04, 0x04, 0x80, 0x28, 0xBF, 0x1F, 0x28, 0x64, 0xD4, 0x8F, 0x9A,
+      0xD4, 0xD8, 0x32, 0x94, 0x36, 0x6A, 0x82, 0x88, 0x56, 0x55, 0x3F,
+      0x3B, 0x14, 0x30, 0x3F, 0x90, 0x14, 0x7F, 0x5D, 0x40, 0xEF },
     "MFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNh"
     "Y2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjg=",
     "U+w77vuySF8=",
     nullptr
   },
   {
     // CN = TWCA Global Root CA, OU = Root CA, O = TAIWAN-CA, C = TW
     "1.3.6.1.4.1.40869.1.1.22.3",
     "TWCA EV OID",
     SEC_OID_UNKNOWN,
-    { 0x9C, 0xBB, 0x48, 0x53, 0xF6, 0xA4, 0xF6, 0xD3, 0x52, 0xA4,
-      0xE8, 0x32, 0x52, 0x55, 0x60, 0x13, 0xF5, 0xAD, 0xAF, 0x65 },
+    { 0x59, 0x76, 0x90, 0x07, 0xF7, 0x68, 0x5D, 0x0F, 0xCD, 0x50, 0x87,
+      0x2F, 0x9F, 0x95, 0xD5, 0x75, 0x5A, 0x5B, 0x2B, 0x45, 0x7D, 0x81,
+      0xF3, 0x69, 0x2B, 0x61, 0x0A, 0x98, 0x67, 0x2F, 0x0E, 0x1B },
     "MFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jv"
     "b3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0E=",
     "DL4=",
     nullptr
   },
   {
     // CN = E-Tugra Certification Authority, OU = E-Tugra Sertifikasyon Merkezi, O = E-Tuğra EBG Bilişim Teknolojileri ve Hizmetleri A.Ş., L = Ankara, C = TR
     "2.16.792.3.0.4.1.1.4",
     "ETugra EV OID",
     SEC_OID_UNKNOWN,
-    { 0x51, 0xC6, 0xE7, 0x08, 0x49, 0x06, 0x6E, 0xF3, 0x92, 0xD4,
-      0x5C, 0xA0, 0x0D, 0x6D, 0xA3, 0x62, 0x8F, 0xC3, 0x52, 0x39 },
+    { 0xB0, 0xBF, 0xD5, 0x2B, 0xB0, 0xD7, 0xD9, 0xBD, 0x92, 0xBF, 0x5D,
+      0x4D, 0xC1, 0x3D, 0xA2, 0x55, 0xC0, 0x2C, 0x54, 0x2F, 0x37, 0x83,
+      0x65, 0xEA, 0x89, 0x39, 0x11, 0xF5, 0x5E, 0x55, 0xF2, 0x3C },
     "MIGyMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMUAwPgYDVQQKDDdFLVR1"
     "xJ9yYSBFQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEu"
     "xZ4uMSYwJAYDVQQLDB1FLVR1Z3JhIFNlcnRpZmlrYXN5b24gTWVya2V6aTEoMCYG"
     "A1UEAwwfRS1UdWdyYSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eQ==",
     "amg+nFGby1M=",
     nullptr
   }
 };
@@ -941,23 +997,24 @@ IdentityInfoInit()
       if (iEV == 0) {
         continue;
       }
 #endif
       PR_NOT_REACHED("Could not find EV root in NSS storage");
       continue;
     }
 
-    unsigned char certFingerprint[20];
-    rv = PK11_HashBuf(SEC_OID_SHA1, certFingerprint,
+    unsigned char certFingerprint[SHA256_LENGTH];
+    rv = PK11_HashBuf(SEC_OID_SHA256, certFingerprint,
                       entry.cert->derCert.data,
                       static_cast<int32_t>(entry.cert->derCert.len));
     PR_ASSERT(rv == SECSuccess);
     if (rv == SECSuccess) {
-      bool same = !memcmp(certFingerprint, entry.ev_root_sha1_fingerprint, 20);
+      bool same = !memcmp(certFingerprint, entry.ev_root_sha256_fingerprint,
+                          sizeof(certFingerprint));
       PR_ASSERT(same);
       if (same) {
 
         SECItem ev_oid_item;
         ev_oid_item.data = nullptr;
         ev_oid_item.len = 0;
         rv = SEC_StringToOID(nullptr, &ev_oid_item, entry.dotted_oid, 0);
         PR_ASSERT(rv == SECSuccess);
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -476,19 +476,29 @@ class MochitestUtilsMixin(object):
       # rid ourselves of 2.6.
       info = {}
       for k, v in mozinfo.info.items():
         if isinstance(k, unicode):
           k = k.encode('ascii')
         info[k] = v
 
       # Bug 883858 - return all tests including disabled tests
-      tests = manifest.active_tests(disabled=True, options=options, **info)
+      testPath = self.getTestPath(options)
+      if testPath.endswith('.html') or \
+         testPath.endswith('.xhtml') or \
+         testPath.endswith('.xul') or \
+         testPath.endswith('.js'):
+          # In the case where we have a single file, we don't want to filter based on options such as subsuite.
+          tests = manifest.active_tests(disabled=True, options=None, **info)
+          for test in tests:
+              if 'disabled' in test:
+                  del test['disabled']
+      else:
+          tests = manifest.active_tests(disabled=True, options=options, **info)
       paths = []
-      testPath = self.getTestPath(options)
 
       for test in tests:
         pathAbs = os.path.abspath(test['path'])
         assert pathAbs.startswith(testRootAbs)
         tp = pathAbs[len(testRootAbs):].replace('\\', '/').strip('/')
 
         # Filter out tests if we are using --test-path
         if testPath and not tp.startswith(testPath):
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/docs/_static/structured_example.py
@@ -0,0 +1,91 @@
+import argparse
+import sys
+import traceback
+import types
+
+from mozlog.structured import structuredlog, commandline
+
+class TestAssertion(Exception):
+    pass
+
+def assert_equals(a, b):
+    if a != b:
+        raise TestAssertion("%r not equal to %r" % (a, b))
+
+def expected(status):
+    def inner(f):
+        def test_func():
+            f()
+        test_func.__name__ = f.__name__
+        test_func._expected = status
+        return test_func
+    return inner
+
+def test_that_passes():
+    assert_equals(1, int("1"))
+
+def test_that_fails():
+    assert_equals(1, int("2"))
+
+def test_that_has_an_error():
+    assert_equals(2, 1 + "1")
+
+@expected("FAIL")
+def test_expected_fail():
+    assert_equals(2 + 2, 5)
+
+class TestRunner(object):
+    def __init__(self, logger):
+        self.logger = logger
+
+    def gather_tests(self):
+        for item in globals().itervalues():
+            if type(item) == types.FunctionType and item.__name__.startswith("test_"):
+                yield item.__name__, item
+
+    def run(self):
+        tests = list(self.gather_tests())
+
+        self.logger.suite_start(tests=[name for name, func in tests])
+        self.logger.info("Running tests")
+        for name, func in tests:
+            self.run_test(name, func)
+        self.logger.suite_end()
+
+    def run_test(self, name, func):
+        self.logger.test_start(name)
+        status = None
+        message = None
+        expected = func._expected if hasattr(func, "_expected") else "PASS"
+        try:
+            func()
+        except TestAssertion as e:
+            status = "FAIL"
+            message = e.message
+        except:
+            status = "ERROR"
+            message = traceback.format_exc()
+        else:
+            status = "PASS"
+        self.logger.test_end(name, status=status, expected=expected, message=message)
+
+def get_parser():
+    parser = argparse.ArgumentParser()
+    return parser
+
+def main():
+    parser = get_parser()
+    commandline.add_logging_group(parser)
+
+    args = parser.parse_args()
+
+    logger = commandline.setup_logging("structured-example", args, {"raw": sys.stdout})
+
+    runner = TestRunner(logger)
+    try:
+        runner.run()
+    except:
+        logger.critical("Error during test run:\n%s" % traceback.format_exc())
+
+if __name__ == "__main__":
+    main()
--- a/testing/mozbase/docs/mozlog_structured.rst
+++ b/testing/mozbase/docs/mozlog_structured.rst
@@ -1,23 +1,27 @@
 :mod:`mozlog.structured` --- Structured logging for test output
 ===============================================================
 
-``mozlog.structured`` is a library designed for logging the execution
-and results of test harnesses. The canonical output format is JSON,
-with one line of JSON per log entry. It is *not* based on the stdlib
-logging module, although it shares several concepts with this module.
+:py:mod:`mozlog.structured` is a library designed for logging the
+execution and results of test harnesses. The internal data model is a
+stream of JSON-compatible objects, with one object per log entry. The
+default output format is line-based, with one JSON object serialized
+per line.
+
+:py:mod:`mozlog.structured` is *not* based on the stdlib logging
+module, although it shares several concepts with it.
 
 One notable difference between this module and the standard logging
 module is the way that loggers are created. The structured logging
 module does not require that loggers with a specific name are
 singleton objects accessed through a factory function. Instead the
 ``StructuredLogger`` constructor may be used directly. However all
 loggers with the same name share the same internal state (the "Borg"
-pattern). In particular the list of handlers functions is the same for
+pattern). In particular the list of handler functions is the same for
 all loggers with the same name.
 
 Logging is threadsafe, with access to handlers protected by a
 ``threading.Lock``. However it is `not` process-safe. This means that
 applications using multiple processes, e.g. via the
 ``multiprocessing`` module, should arrange for all logging to happen in
 a single process.
 
@@ -50,17 +54,21 @@ on on all messages is:
 For each ``action`` there are is a further set of specific fields
 describing the details of the event that caused the message to be
 emitted:
 
 ``suite_start``
   Emitted when the testsuite starts running.
 
   ``tests``
-    A list of test_ids (list).
+    A list of test ids. Test ids can either be strings or lists of
+    strings (an example of the latter is reftests where the id has the
+    form [test_url, ref_type, ref_url]) and are assumed to be unique
+    within a given testsuite. In cases where the test list is not
+    known upfront an empty list may be passed (list).
 
   ``run_info``
     An optional dictionary describing the properties of the
     build and test environment. This contains the information provided
     by :doc:`mozinfo <mozinfo>`, plus a boolean ``debug`` field indicating
     whether the build under test is a debug build.
 
 ``suite_end``
@@ -69,17 +77,17 @@ emitted:
 ``test_start``
   Emitted when a test is being started.
 
   ``test``
     A unique id for the test (string or list of strings).
 
 ``test_status``
   Emitted for a test which has subtests to record the result of a
-  single subtest
+  single subtest.
 
   ``test``
     The same unique id for the test as in the ``test_start`` message.
 
   ``subtest``
     Name of the subtest (string).
 
   ``status``
@@ -100,17 +108,17 @@ emitted:
   ``status``
     Either result of the test (if there are no subtests) in which case
     (string enum ``PASS``, ``FAIL``, ``TIMEOUT``, ``CRASH``,
     ``ASSERT``, ``SKIP``) or the status of the overall file where
     there are subtests (string enum ``OK``, ``ERROR``, ``TIMEOUT``,
     ``CRASH``, ``ASSERT``, ``SKIP``).
 
   ``expected``
-    The expected status, or emitted if the expected status matches the
+    The expected status, or omitted if the expected status matches the
     actual status (string enum, same as ``status``).
 
 ``process_output``
   Output from a managed subprocess.
 
   ``process``
   pid of the subprocess.
 
@@ -126,16 +134,65 @@ emitted:
 
   ``level``
     Level of the log message (string enum ``CRITICAL``, ``ERROR``,
     ``WARNING``, ``INFO``, ``DEBUG``).
 
   ``message``
     Text of the log message.
 
+Testsuite Protocol
+------------------
+
+When used for testsuites, the following structured logging messages must be emitted:
+
+ * One ``suite_start`` message before any ``test_*`` messages
+
+ * One ``test_start`` message per test that is run
+
+ * One ``test_status`` message per subtest that is run. This might be
+   zero if the test type doesn't have the notion of subtests.
+
+ * One ``test_end`` message per test that is run, after the
+   ``test_start`` and any ``test_status`` messages for that same test.
+
+ * One ``suite_end`` message after all ``test_*`` messages have been
+   emitted.
+
+The above mandatory events may be interspersed with ``process_output``
+and ``log`` events, as required.
+
+Subtests
+~~~~~~~~
+
+The purpose of subtests is to deal with situations where a single test
+produces more than one result, and the exact details of the number of
+results is not known ahead of time. For example consider a test
+harness that loads JavaScript-based tests in a browser. Each url
+loaded would be a single test, with corresponding ``test_start`` and
+``test_end`` messages. If there can be more than one JS-defined test
+on a page, however, it it useful to track the results of those tests
+seperately. Therefore each of those tests is a subtest, and one
+``test_status`` message must be generated for each subtest result.
+
+Subtests must have a name that is unique within their parent test.
+
+Whether or not a test has subtests changes the meaning of the
+``status`` property on the test itself. When the test does not have
+any subtests, this property is the actual test result such as ``PASS``
+or ``FAIL`` . When a test does have subtests, the test itself does not
+have a result as-such; it isn't meaningful to describe it as having a
+``PASS`` result, especially if the subtests did not all pass. Instead
+this property is used to hold information about whether the test ran
+without error. If no errors were detected the test must be given the
+status ``OK``. Otherwise the test may get the status ``ERROR`` (for
+e.g. uncaught JS exceptions), ``TIMEOUT`` (if no results were reported
+in the allowed time) or ``CRASH`` (if the test caused the process
+under test to crash).
+
 StructuredLogger Objects
 ------------------------
 
 .. automodule:: mozlog.structured.structuredlog
 
 .. autoclass:: StructuredLogger
    :members: add_handler, remove_handler, handlers, suite_start,
              suite_end, test_start, test_status, test_end,
@@ -215,23 +272,23 @@ with structured log files.
 
 Integration with argparse
 -------------------------
 
 The `mozlog.structured.commandline` module provides integration with
 the `argparse` module to provide uniform logging-related command line
 arguments to programs using `mozlog.structured`. Each known formatter
 gets a command line argument of the form ``--log-{name}``, which takes
-the name of a file to log to with that format of `-` to indicate stdout.
+the name of a file to log to with that format, or ``-`` to indicate stdout.
 
 .. automodule:: mozlog.structured.commandline
   :members:
 
-Examples
---------
+Simple Examples
+---------------
 
 Log to stdout::
 
     from mozlog.structured import structuredlog
     from mozlog.structured import handlers, formatters
     logger = structuredlog.StructuredLogger("my-test-suite")
     logger.add_handler(handlers.StreamHandler(sys.stdout,
                                               formatters.JSONFormatter()))
@@ -256,19 +313,133 @@ JSON output on stdout if nothing else is
 
    args = parser.parse_args()
    logger = commandline.setup_logging("testsuite-name", args, {"raw": sys.stdout})
 
 Count the number of tests that timed out in a testsuite::
 
    from mozlog.structured import reader
 
-   count = 0;
+   count = 0
 
    def handle_test_end(data):
        global count
        if data["status"] == "TIMEOUT":
            count += 1
 
    reader.each_log(reader.read("my_test_run.log"),
                    {"test_end": handle_test_end})
 
    print count
+
+More Complete Example
+---------------------
+
+This example shows a complete toy testharness set up to used
+structured logging. It is avaliable as `structured_example.py <_static/structured_example.py>`_:
+
+.. literalinclude:: _static/structured_example.py
+
+Each global function with a name starting
+``test_`` represents a test. A passing test returns without
+throwing. A failing test throws a :py:class:`TestAssertion` exception
+via the :py:func:`assert_equals` function. Throwing anything else is
+considered an error in the test. There is also a :py:func:`expected`
+decorator that is used to annotate tests that are expected to do
+something other than pass.
+
+The main entry point to the test runner is via that :py:func:`main`
+function. This is responsible for parsing command line
+arguments, and initiating the test run. Although the test harness
+itself does not provide any command line arguments, the
+:py:class:`ArgumentParser` object is populated by
+:py:meth:`commandline.add_logging_group`, which provides a generic
+set of structured logging arguments appropriate to all tools producing
+structured logging.
+
+The values of these command line arguments are used to create a
+:py:class:`mozlog.structured.StructuredLogger` object populated with the
+specified handlers and formatters in
+:py:func:`commandline.setup_logging`. The third argument to this
+function is the default arguments to use. In this case the default
+is to output raw (i.e. JSON-formatted) logs to stdout.
+
+The main test harness is provided by the :py:class:`TestRunner`
+class. This class is responsible for scheduling all the tests and
+logging all the results. It is passed the :py:obj:`logger` object
+created from the command line arguments. The :py:meth:`run` method
+starts the test run. Before the run is started it logs a
+``suite_start`` message containing the id of each test that will run,
+and after the testrun is done it logs a ``suite_end`` message.
+
+Individual tests are run in the :py:meth:`run_test` method. For each
+test this logs a ``test_start`` message. It then runs the test and
+logs a ``test_end`` message containing the test name, status, expected
+status, and any informational message about the reason for the
+result. In this test harness there are no subtests, so the
+``test_end`` message has the status of the test and there are no
+``test_status`` messages.
+
+Example Output
+~~~~~~~~~~~~~~
+
+When run without providing any command line options, the raw
+structured log messages are sent to stdout::
+
+  $ python structured_example.py
+
+  {"source": "structured-example", "tests": ["test_that_has_an_error", "test_that_fails", "test_expected_fail", "test_that_passes"], "thread": "MainThread", "time": 1401446682787, "action": "suite_start", "pid": 18456}
+  {"source": "structured-example", "thread": "MainThread", "time": 1401446682787, "action": "log", "message": "Running tests", "level": "INFO", "pid": 18456}
+  {"source": "structured-example", "test": "test_that_has_an_error", "thread": "MainThread", "time": 1401446682787, "action": "test_start", "pid": 18456}
+  {"status": "ERROR", "thread": "MainThread", "pid": 18456, "source": "structured-example", "test": "test_that_has_an_error", "time": 1401446682788, "action": "test_end", "message": "Traceback (most recent call last):\n  File \"structured_example.py\", line 61, in run_test\n    func()\n  File \"structured_example.py\", line 31, in test_that_has_an_error\n    assert_equals(2, 1 + \"1\")\nTypeError: unsupported operand type(s) for +: 'int' and 'str'\n", "expected": "PASS"}
+  {"source": "structured-example", "test": "test_that_fails", "thread": "MainThread", "time": 1401446682788, "action": "test_start", "pid": 18456}
+  {"status": "FAIL", "thread": "MainThread", "pid": 18456, "source": "structured-example", "test": "test_that_fails", "time": 1401446682788, "action": "test_end", "message": "1 not equal to 2", "expected": "PASS"}
+  {"source": "structured-example", "test": "test_expected_fail", "thread": "MainThread", "time": 1401446682788, "action": "test_start", "pid": 18456}
+  {"status": "FAIL", "thread": "MainThread", "pid": 18456, "source": "structured-example", "test": "test_expected_fail", "time": 1401446682788, "action": "test_end", "message": "4 not equal to 5"}
+  {"source": "structured-example", "test": "test_that_passes", "thread": "MainThread", "time": 1401446682788, "action": "test_start", "pid": 18456}
+  {"status": "PASS", "source": "structured-example", "test": "test_that_passes", "thread": "MainThread", "time": 1401446682789, "action": "test_end", "pid": 18456}
+  {"action": "suite_end", "source": "structured-example", "pid": 18456, "thread": "MainThread", "time": 1401446682789}
+
+The structured logging module provides a number of command line
+options::
+
+  $ python structured_example.py --help
+
+  usage: structured_example.py [-h] [--log-unittest LOG_UNITTEST]
+                               [--log-raw LOG_RAW] [--log-html LOG_HTML]
+                               [--log-xunit LOG_XUNIT]
+                               [--log-mach_terminal LOG_MACH_TERMINAL]
+                               [--log-mach LOG_MACH]
+
+  optional arguments:
+    -h, --help            show this help message and exit
+
+  Output Logging:
+    Options for logging output. Each option represents a possible logging
+    format and takes a filename to write that format to, or '-' to write to
+    stdout.
+
+    --log-unittest LOG_UNITTEST
+                          Unittest style output
+    --log-raw LOG_RAW     Raw structured log messages
+    --log-html LOG_HTML   HTML report
+    --log-xunit LOG_XUNIT
+                          xUnit compatible XML
+    --log-mach_terminal LOG_MACH_TERMINAL
+                          Colored mach-like output for use in a tty
+    --log-mach LOG_MACH   Uncolored mach-like output
+
+In order to get human-readable output on stdout and the structured log
+data to go to the file ``structured.log``, we would run::
+
+  $ python structured_example.py --log-mach=- --log-raw=structured.log
+
+  0:00.00 SUITE_START: MainThread 4
+  0:01.00 LOG: MainThread INFO Running tests
+  0:01.00 TEST_START: MainThread test_that_has_an_error
+  0:01.00 TEST_END: MainThread Harness status ERROR, expected PASS. Subtests passed 0/0. Unexpected 1
+  0:01.00 TEST_START: MainThread test_that_fails
+  0:01.00 TEST_END: MainThread Harness status FAIL, expected PASS. Subtests passed 0/0. Unexpected 1
+  0:01.00 TEST_START: MainThread test_expected_fail
+  0:02.00 TEST_END: MainThread Harness status FAIL. Subtests passed 0/0. Unexpected 0
+  0:02.00 TEST_START: MainThread test_that_passes
+  0:02.00 TEST_END: MainThread Harness status PASS. Subtests passed 0/0. Unexpected 0
+  0:02.00 SUITE_END: MainThread
--- a/testing/mozbase/mozlog/mozlog/structured/formatters/html/html.py
+++ b/testing/mozbase/mozlog/mozlog/structured/formatters/html/html.py
@@ -20,16 +20,17 @@ base_path = os.path.split(__file__)[0]
 def do_defered_imports():
     global html
     global raw
 
     from py.xml import html, raw
 
 
 class HTMLFormatter(base.BaseFormatter):
+    """Formatter that produces a simple HTML-formatted report."""
     def __init__(self):
         do_defered_imports()
         self.suite_name = None
         self.result_rows = []
         self.test_count = defaultdict(int)
         self.start_times = {}
         self.suite_times = {"start": None,
                             "end": None}
--- a/testing/mozbase/mozlog/mozlog/structured/handlers/__init__.py
+++ b/testing/mozbase/mozlog/mozlog/structured/handlers/__init__.py
@@ -18,17 +18,17 @@ class BaseHandler(object):
     def remove_filter(self, filter_func):
         self.filters.remove(filter_func)
 
     def filter(self, data):
         return all(item(data) for item in self.filters)
 
 
 class LogLevelFilter(object):
-    """Handler that filters out messages with action:log and a level
+    """Handler that filters out messages with action of log and a level
     lower than some specified level.
 
     :param inner: Handler to use for messages that pass this filter
     :param level: Minimum log level to process
     """
     def __init__(self, inner, level):
         self.inner = inner
         self.level = log_levels[level.upper()]
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -2323,16 +2323,24 @@
   },
   "PLUGIN_LOAD_METADATA": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "5000",
     "n_buckets": 20,
     "description": "Time spent loading plugin DLL and obtaining metadata (ms)"
   },
+  "PLUGIN_STARTUP_MS": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": "5000",
+    "n_buckets": 20,
+    "extended_statistics_ok": true,
+    "description": "Time spent starting up plugins (ms)"
+  },
   "PLUGIN_SHUTDOWN_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "5000",
     "n_buckets": 20,
     "extended_statistics_ok": true,
     "description": "Time spent shutting down plugins (ms)"
   },
--- a/toolkit/library/libxul.mk
+++ b/toolkit/library/libxul.mk
@@ -163,17 +163,21 @@ ifeq (OpenBSD,$(OS_ARCH))
 EXTRA_DSO_LDOPTS += -lsndio
 endif
 
 ifdef MOZ_ENABLE_DBUS
 EXTRA_DSO_LDOPTS += $(MOZ_DBUS_GLIB_LIBS)
 endif
 
 ifdef MOZ_WIDGET_GTK
+ifdef MOZ_ENABLE_GTK3
+EXTRA_DSO_LDOPTS += $(filter-out -lgtk-3 -lgdk-3,$(TK_LIBS)) -lmozgtk_stub
+else
 EXTRA_DSO_LDOPTS += $(TK_LIBS)
+endif
 EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(XEXT_LIBS) $(XCOMPOSITE_LIBS) $(MOZ_PANGO_LIBS) $(XT_LIBS) -lgthread-2.0
 EXTRA_DSO_LDOPTS += $(FT2_LIBS)
 endif
 
 ifeq (qt,$(MOZ_WIDGET_TOOLKIT))
 EXTRA_DSO_LDOPTS += $(XLDFLAGS) $(XLIBS) $(XT_LIBS) $(MOZ_QT_LIBS)
 EXTRA_DSO_LDOPTS += $(FT2_LIBS) $(MOZ_PANGO_LIBS)
 endif
--- a/widget/gtk/moz.build
+++ b/widget/gtk/moz.build
@@ -1,14 +1,17 @@
 # -*- 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/.
 
+if CONFIG['MOZ_ENABLE_GTK3']:
+    DIRS += ['mozgtk']
+
 if CONFIG['MOZ_ENABLE_GTK2']:
     LIBRARY_NAME = 'widget_gtk2'
 else:
     LIBRARY_NAME = 'widget_gtk3'
 
 EXPORTS += [
     'mozcontainer.h',
     'nsGTKToolkit.h',
new file mode 100644
--- /dev/null
+++ b/widget/gtk/mozgtk/gtk2/Makefile.in
@@ -0,0 +1,9 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXTRA_DSO_LDOPTS += -lgtk-x11-2.0 -lgdk-x11-2.0
+
+include $(topsrcdir)/config/rules.mk
+
+LDFLAGS += -Wl,-soname=$(DLL_PREFIX)mozgtk$(DLL_SUFFIX)
new file mode 100644
--- /dev/null
+++ b/widget/gtk/mozgtk/gtk2/moz.build
@@ -0,0 +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/.
+
+SOURCES += [
+    '../mozgtk.c',
+]
+
+DEFINES['GTK3_SYMBOLS'] = True
+
+LIBRARY_NAME = 'mozgtk2'
+
+FORCE_SHARED_LIB = True
new file mode 100644
--- /dev/null
+++ b/widget/gtk/mozgtk/gtk3/Makefile.in
@@ -0,0 +1,7 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXTRA_DSO_LDOPTS += -lgtk-3 -lgdk-3
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/widget/gtk/mozgtk/gtk3/moz.build
@@ -0,0 +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/.
+
+SOURCES += [
+    '../mozgtk.c',
+]
+
+DEFINES['GTK2_SYMBOLS'] = True
+
+LIBRARY_NAME = 'mozgtk'
+
+FORCE_SHARED_LIB = True
new file mode 100644
--- /dev/null
+++ b/widget/gtk/mozgtk/moz.build
@@ -0,0 +1,7 @@
+# -*- 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/.
+
+DIRS += ['stub', 'gtk2', 'gtk3']
new file mode 100644
--- /dev/null
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -0,0 +1,550 @@
+#include "mozilla/Types.h"
+#include "mozilla/Assertions.h"
+
+#define STUB(symbol) MOZ_EXPORT void symbol (void) { MOZ_CRASH(); }
+
+#ifdef COMMON_SYMBOLS
+STUB(gdk_atom_intern)
+STUB(gdk_atom_name)
+STUB(gdk_beep)
+STUB(gdk_color_free)
+STUB(gdk_cursor_new)
+STUB(gdk_cursor_new_from_name)
+STUB(gdk_cursor_new_from_pixbuf)
+STUB(gdk_cursor_unref)
+STUB(gdk_display_close)
+STUB(gdk_display_get_default)
+STUB(gdk_display_get_default_screen)
+STUB(gdk_display_get_pointer)
+STUB(gdk_display_get_window_at_pointer)
+STUB(gdk_display_manager_get)
+STUB(gdk_display_manager_set_default_display)
+STUB(gdk_display_open)
+STUB(gdk_display_sync)
+STUB(gdk_display_warp_pointer)
+STUB(gdk_drag_context_get_actions)
+STUB(gdk_drag_context_get_dest_window)
+STUB(gdk_drag_context_list_targets)
+STUB(gdk_drag_status)
+STUB(gdk_error_trap_pop)
+STUB(gdk_error_trap_push)
+STUB(gdk_event_copy)
+STUB(gdk_event_free)
+STUB(gdk_event_get_axis)
+STUB(gdk_event_get_time)
+STUB(gdk_event_handler_set)
+STUB(gdk_event_peek)
+STUB(gdk_event_put)
+STUB(gdk_flush)
+STUB(gdk_get_default_root_window)
+STUB(gdk_get_display)
+STUB(gdk_get_display_arg_name)
+STUB(gdk_get_program_class)
+STUB(gdk_keymap_get_default)
+STUB(gdk_keymap_get_direction)
+STUB(gdk_keymap_get_entries_for_keyval)
+STUB(gdk_keymap_have_bidi_layouts)
+STUB(gdk_keymap_translate_keyboard_state)
+STUB(gdk_keyval_name)
+STUB(gdk_keyval_to_unicode)
+STUB(gdk_pango_context_get)
+STUB(gdk_pointer_grab)
+STUB(gdk_pointer_ungrab)
+STUB(gdk_property_get)
+STUB(gdk_screen_get_default)
+STUB(gdk_screen_get_display)
+STUB(gdk_screen_get_font_options)
+STUB(gdk_screen_get_resolution)
+STUB(gdk_screen_get_rgba_visual)
+STUB(gdk_screen_get_root_window)
+STUB(gdk_screen_get_system_visual)
+STUB(gdk_screen_height)
+STUB(gdk_screen_is_composited)
+STUB(gdk_screen_width)
+STUB(gdk_unicode_to_keyval)
+STUB(gdk_visual_get_depth)
+STUB(gdk_visual_get_system)
+STUB(gdk_window_add_filter)
+STUB(gdk_window_begin_move_drag)
+STUB(gdk_window_begin_resize_drag)
+STUB(gdk_window_destroy)
+STUB(gdk_window_focus)
+STUB(gdk_window_get_children)
+STUB(gdk_window_get_display)
+STUB(gdk_window_get_events)
+STUB(gdk_window_get_geometry)
+STUB(gdk_window_get_height)
+STUB(gdk_window_get_origin)
+STUB(gdk_window_get_parent)
+STUB(gdk_window_get_position)
+STUB(gdk_window_get_root_origin)
+STUB(gdk_window_get_screen)
+STUB(gdk_window_get_state)
+STUB(gdk_window_get_toplevel)
+STUB(gdk_window_get_update_area)
+STUB(gdk_window_get_user_data)
+STUB(gdk_window_get_visual)
+STUB(gdk_window_get_width)
+STUB(gdk_window_hide)
+STUB(gdk_window_input_shape_combine_region)
+STUB(gdk_window_invalidate_rect)
+STUB(gdk_window_invalidate_region)
+STUB(gdk_window_is_destroyed)
+STUB(gdk_window_is_visible)
+STUB(gdk_window_lower)
+STUB(gdk_window_move)
+STUB(gdk_window_move_resize)
+STUB(gdk_window_new)
+STUB(gdk_window_peek_children)
+STUB(gdk_window_process_updates)
+STUB(gdk_window_raise)
+STUB(gdk_window_remove_filter)
+STUB(gdk_window_reparent)
+STUB(gdk_window_resize)
+STUB(gdk_window_set_cursor)
+STUB(gdk_window_set_debug_updates)
+STUB(gdk_window_set_decorations)
+STUB(gdk_window_set_events)
+STUB(gdk_window_set_role)
+STUB(gdk_window_set_urgency_hint)
+STUB(gdk_window_set_user_data)
+STUB(gdk_window_shape_combine_region)
+STUB(gdk_window_show)
+STUB(gdk_window_show_unraised)
+STUB(gdk_x11_atom_to_xatom)
+STUB(gdk_x11_display_get_user_time)
+STUB(gdk_x11_display_get_xdisplay)
+STUB(gdk_x11_get_default_root_xwindow)
+STUB(gdk_x11_get_default_xdisplay)
+STUB(gdk_x11_get_xatom_by_name)
+STUB(gdk_x11_lookup_xdisplay)
+STUB(gdk_x11_screen_get_xscreen)
+STUB(gdk_x11_visual_get_xvisual)
+STUB(gdk_x11_window_lookup_for_display)
+STUB(gdk_x11_xatom_to_atom)
+STUB(gtk_accel_label_new)
+STUB(gtk_alignment_get_type)
+STUB(gtk_alignment_new)
+STUB(gtk_alignment_set_padding)
+STUB(gtk_arrow_get_type)
+STUB(gtk_arrow_new)
+STUB(gtk_bindings_activate)
+STUB(gtk_bin_get_child)
+STUB(gtk_bin_get_type)
+STUB(gtk_border_free)
+STUB(gtk_box_get_type)
+STUB(gtk_box_pack_start)
+STUB(gtk_button_new)
+STUB(gtk_button_new_with_label)
+STUB(gtk_check_button_new_with_label)
+STUB(gtk_check_button_new_with_mnemonic)
+STUB(gtk_check_menu_item_new_with_label)
+STUB(gtk_check_version)
+STUB(gtk_clipboard_clear)
+STUB(gtk_clipboard_get)
+STUB(gtk_clipboard_request_contents)
+STUB(gtk_clipboard_request_text)
+STUB(gtk_clipboard_set_can_store)
+STUB(gtk_clipboard_set_with_data)
+STUB(gtk_clipboard_store)
+STUB(gtk_color_selection_dialog_get_color_selection)
+STUB(gtk_color_selection_dialog_get_type)
+STUB(gtk_color_selection_dialog_new)
+STUB(gtk_color_selection_get_current_color)
+STUB(gtk_color_selection_get_type)
+STUB(gtk_color_selection_set_current_color)
+STUB(gtk_combo_box_get_active)
+STUB(gtk_combo_box_get_type)
+STUB(gtk_combo_box_new)
+STUB(gtk_combo_box_new_with_entry)
+STUB(gtk_combo_box_set_active)
+STUB(gtk_combo_box_text_get_type)
+STUB(gtk_combo_box_text_new)
+STUB(gtk_container_add)
+STUB(gtk_container_forall)
+STUB(gtk_container_get_border_width)
+STUB(gtk_container_get_type)
+STUB(gtk_container_set_border_width)
+STUB(gtk_container_set_resize_mode)
+STUB(gtk_dialog_get_content_area)
+STUB(gtk_dialog_get_type)
+STUB(gtk_dialog_new_with_buttons)
+STUB(gtk_dialog_run)
+STUB(gtk_dialog_set_alternative_button_order)
+STUB(gtk_dialog_set_default_response)
+STUB(gtk_drag_begin)
+STUB(gtk_drag_dest_set)
+STUB(gtk_drag_finish)
+STUB(gtk_drag_get_data)
+STUB(gtk_drag_get_source_widget)
+STUB(gtk_drag_set_icon_pixbuf)
+STUB(gtk_drag_set_icon_widget)
+STUB(gtk_editable_get_type)
+STUB(gtk_editable_select_region)
+STUB(gtk_entry_get_text)
+STUB(gtk_entry_get_type)
+STUB(gtk_entry_new)
+STUB(gtk_entry_set_activates_default)
+STUB(gtk_entry_set_text)
+STUB(gtk_enumerate_printers)
+STUB(gtk_expander_new)
+STUB(gtk_file_chooser_add_filter)
+STUB(gtk_file_chooser_dialog_new)
+STUB(gtk_file_chooser_get_filenames)
+STUB(gtk_file_chooser_get_filter)
+STUB(gtk_file_chooser_get_preview_filename)
+STUB(gtk_file_chooser_get_type)
+STUB(gtk_file_chooser_get_uri)
+STUB(gtk_file_chooser_list_filters)
+STUB(gtk_file_chooser_set_current_folder)
+STUB(gtk_file_chooser_set_current_name)
+STUB(gtk_file_chooser_set_do_overwrite_confirmation)
+STUB(gtk_file_chooser_set_filename)
+STUB(gtk_file_chooser_set_filter)
+STUB(gtk_file_chooser_set_local_only)
+STUB(gtk_file_chooser_set_preview_widget)
+STUB(gtk_file_chooser_set_preview_widget_active)
+STUB(gtk_file_chooser_set_select_multiple)
+STUB(gtk_file_filter_add_pattern)
+STUB(gtk_file_filter_new)
+STUB(gtk_file_filter_set_name)
+STUB(gtk_fixed_new)
+STUB(gtk_frame_new)
+STUB(gtk_grab_add)
+STUB(gtk_grab_remove)
+STUB(gtk_handle_box_new)
+STUB(gtk_hbox_new)
+STUB(gtk_hpaned_new)
+STUB(gtk_hscale_new)
+STUB(gtk_hscrollbar_new)
+STUB(gtk_icon_info_free)
+STUB(gtk_icon_info_load_icon)
+STUB(gtk_icon_set_add_source)
+STUB(gtk_icon_set_new)
+STUB(gtk_icon_set_render_icon)
+STUB(gtk_icon_set_unref)
+STUB(gtk_icon_size_lookup)
+STUB(gtk_icon_source_free)
+STUB(gtk_icon_source_new)
+STUB(gtk_icon_source_set_icon_name)
+STUB(gtk_icon_theme_add_builtin_icon)
+STUB(gtk_icon_theme_get_default)
+STUB(gtk_icon_theme_get_icon_sizes)
+STUB(gtk_icon_theme_lookup_by_gicon)
+STUB(gtk_icon_theme_lookup_icon)
+STUB(gtk_image_get_type)
+STUB(gtk_image_menu_item_new)
+STUB(gtk_image_new)
+STUB(gtk_image_new_from_stock)
+STUB(gtk_image_set_from_pixbuf)
+STUB(gtk_im_context_filter_keypress)
+STUB(gtk_im_context_focus_in)
+STUB(gtk_im_context_focus_out)
+STUB(gtk_im_context_get_preedit_string)
+STUB(gtk_im_context_reset)
+STUB(gtk_im_context_set_client_window)
+STUB(gtk_im_context_set_cursor_location)
+STUB(gtk_im_context_set_surrounding)
+STUB(gtk_im_context_simple_new)
+STUB(gtk_im_multicontext_get_type)
+STUB(gtk_im_multicontext_new)
+STUB(gtk_init)
+STUB(gtk_invisible_new)
+STUB(gtk_key_snooper_install)
+STUB(gtk_key_snooper_remove)
+STUB(gtk_label_get_type)
+STUB(gtk_label_new)
+STUB(gtk_label_set_markup)
+STUB(gtk_link_button_new)
+STUB(gtk_main_do_event)
+STUB(gtk_main_iteration)
+STUB(gtk_menu_bar_new)
+STUB(gtk_menu_get_type)
+STUB(gtk_menu_item_get_type)
+STUB(gtk_menu_item_new)
+STUB(gtk_menu_item_new_with_label)
+STUB(gtk_menu_item_set_submenu)
+STUB(gtk_menu_new)
+STUB(gtk_menu_shell_append)
+STUB(gtk_menu_shell_get_type)
+STUB(gtk_misc_get_alignment)
+STUB(gtk_misc_get_padding)
+STUB(gtk_misc_get_type)
+STUB(gtk_misc_set_alignment)
+STUB(gtk_misc_set_padding)
+STUB(gtk_notebook_new)
+STUB(gtk_page_setup_copy)
+STUB(gtk_page_setup_get_bottom_margin)
+STUB(gtk_page_setup_get_left_margin)
+STUB(gtk_page_setup_get_orientation)
+STUB(gtk_page_setup_get_paper_size)
+STUB(gtk_page_setup_get_right_margin)
+STUB(gtk_page_setup_get_top_margin)
+STUB(gtk_page_setup_new)
+STUB(gtk_page_setup_set_bottom_margin)
+STUB(gtk_page_setup_set_left_margin)
+STUB(gtk_page_setup_set_orientation)
+STUB(gtk_page_setup_set_paper_size)
+STUB(gtk_page_setup_set_paper_size_and_default_margins)
+STUB(gtk_page_setup_set_right_margin)
+STUB(gtk_page_setup_set_top_margin)
+STUB(gtk_paper_size_free)
+STUB(gtk_paper_size_get_display_name)
+STUB(gtk_paper_size_get_height)
+STUB(gtk_paper_size_get_name)
+STUB(gtk_paper_size_get_width)
+STUB(gtk_paper_size_is_equal)
+STUB(gtk_paper_size_new)
+STUB(gtk_paper_size_new_custom)
+STUB(gtk_paper_size_set_size)
+STUB(gtk_parse_args)
+STUB(gtk_plug_get_socket_window)
+STUB(gtk_plug_get_type)
+STUB(gtk_printer_accepts_pdf)
+STUB(gtk_printer_get_name)
+STUB(gtk_printer_get_type)
+STUB(gtk_printer_is_default)
+STUB(gtk_print_job_new)
+STUB(gtk_print_job_send)
+STUB(gtk_print_job_set_source_file)
+STUB(gtk_print_run_page_setup_dialog)
+STUB(gtk_print_settings_copy)
+STUB(gtk_print_settings_get)
+STUB(gtk_print_settings_get_duplex)
+STUB(gtk_print_settings_get_n_copies)
+STUB(gtk_print_settings_get_page_ranges)
+STUB(gtk_print_settings_get_paper_size)
+STUB(gtk_print_settings_get_printer)
+STUB(gtk_print_settings_get_print_pages)
+STUB(gtk_print_settings_get_resolution)
+STUB(gtk_print_settings_get_reverse)
+STUB(gtk_print_settings_get_scale)
+STUB(gtk_print_settings_get_use_color)
+STUB(gtk_print_settings_has_key)
+STUB(gtk_print_settings_new)
+STUB(gtk_print_settings_set)
+STUB(gtk_print_settings_set_duplex)
+STUB(gtk_print_settings_set_n_copies)
+STUB(gtk_print_settings_set_orientation)
+STUB(gtk_print_settings_set_page_ranges)
+STUB(gtk_print_settings_set_paper_size)
+STUB(gtk_print_settings_set_printer)
+STUB(gtk_print_settings_set_print_pages)
+STUB(gtk_print_settings_set_resolution)
+STUB(gtk_print_settings_set_reverse)
+STUB(gtk_print_settings_set_scale)
+STUB(gtk_print_settings_set_use_color)
+STUB(gtk_print_unix_dialog_add_custom_tab)
+STUB(gtk_print_unix_dialog_get_page_setup)
+STUB(gtk_print_unix_dialog_get_selected_printer)
+STUB(gtk_print_unix_dialog_get_settings)
+STUB(gtk_print_unix_dialog_get_type)
+STUB(gtk_print_unix_dialog_new)
+STUB(gtk_print_unix_dialog_set_manual_capabilities)
+STUB(gtk_print_unix_dialog_set_page_setup)
+STUB(gtk_print_unix_dialog_set_settings)
+STUB(gtk_progress_bar_new)
+STUB(gtk_propagate_event)
+STUB(gtk_radio_button_get_type)
+STUB(gtk_radio_button_new_with_label)
+STUB(gtk_radio_button_new_with_mnemonic)
+STUB(gtk_radio_button_new_with_mnemonic_from_widget)
+STUB(gtk_range_get_min_slider_size)
+STUB(gtk_range_get_type)
+STUB(gtk_recent_manager_add_item)
+STUB(gtk_recent_manager_get_default)
+STUB(gtk_scrollbar_get_type)
+STUB(gtk_scrolled_window_new)
+STUB(gtk_selection_data_copy)
+STUB(gtk_selection_data_free)
+STUB(gtk_selection_data_get_data)
+STUB(gtk_selection_data_get_length)
+STUB(gtk_selection_data_get_selection)
+STUB(gtk_selection_data_get_target)
+STUB(gtk_selection_data_get_targets)
+STUB(gtk_selection_data_set)
+STUB(gtk_selection_data_set_pixbuf)
+STUB(gtk_selection_data_set_text)
+STUB(gtk_selection_data_targets_include_text)
+STUB(gtk_separator_get_type)
+STUB(gtk_separator_menu_item_new)
+STUB(gtk_separator_tool_item_new)
+STUB(gtk_settings_get_default)
+STUB(gtk_settings_get_for_screen)
+STUB(gtk_socket_add_id)
+STUB(gtk_socket_get_id)
+STUB(gtk_socket_get_type)
+STUB(gtk_socket_new)
+STUB(gtk_spin_button_new)
+STUB(gtk_statusbar_new)
+STUB(gtk_style_lookup_icon_set)
+STUB(gtk_table_attach)
+STUB(gtk_table_get_type)
+STUB(gtk_table_new)
+STUB(gtk_target_list_add)
+STUB(gtk_target_list_add_image_targets)
+STUB(gtk_target_list_new)
+STUB(gtk_target_list_unref)
+STUB(gtk_targets_include_image)
+STUB(gtk_target_table_free)
+STUB(gtk_target_table_new_from_list)
+STUB(gtk_text_view_new)
+STUB(gtk_toggle_button_get_active)
+STUB(gtk_toggle_button_get_type)
+STUB(gtk_toggle_button_new)
+STUB(gtk_toggle_button_set_active)
+STUB(gtk_toggle_button_set_inconsistent)
+STUB(gtk_toolbar_new)
+STUB(gtk_tree_view_append_column)
+STUB(gtk_tree_view_column_new)
+STUB(gtk_tree_view_column_set_title)
+STUB(gtk_tree_view_get_type)
+STUB(gtk_tree_view_new)
+STUB(gtk_vbox_new)
+STUB(gtk_vpaned_new)
+STUB(gtk_vscale_new)
+STUB(gtk_vscrollbar_new)
+STUB(gtk_widget_add_events)
+STUB(gtk_widget_class_find_style_property)
+STUB(gtk_widget_destroy)
+STUB(gtk_widget_destroyed)
+STUB(gtk_widget_ensure_style)
+STUB(gtk_widget_event)
+STUB(gtk_widget_get_accessible)
+STUB(gtk_widget_get_allocation)
+STUB(gtk_widget_get_default_direction)
+STUB(gtk_widget_get_display)
+STUB(gtk_widget_get_events)
+STUB(gtk_widget_get_has_window)
+STUB(gtk_widget_get_mapped)
+STUB(gtk_widget_get_parent)
+STUB(gtk_widget_get_parent_window)
+STUB(gtk_widget_get_realized)
+STUB(gtk_widget_get_screen)
+STUB(gtk_widget_get_settings)
+STUB(gtk_widget_get_style)
+STUB(gtk_widget_get_toplevel)
+STUB(gtk_widget_get_type)
+STUB(gtk_widget_get_visible)
+STUB(gtk_widget_get_visual)
+STUB(gtk_widget_get_window)
+STUB(gtk_widget_grab_focus)
+STUB(gtk_widget_has_focus)
+STUB(gtk_widget_has_grab)
+STUB(gtk_widget_hide)
+STUB(gtk_widget_is_focus)
+STUB(gtk_widget_is_toplevel)
+STUB(gtk_widget_map)
+STUB(gtk_widget_realize)
+STUB(gtk_widget_reparent)
+STUB(gtk_widget_set_allocation)
+STUB(gtk_widget_set_app_paintable)
+STUB(gtk_widget_set_can_focus)
+STUB(gtk_widget_set_direction)
+STUB(gtk_widget_set_double_buffered)
+STUB(gtk_widget_set_has_window)
+STUB(gtk_widget_set_mapped)
+STUB(gtk_widget_set_name)
+STUB(gtk_widget_set_parent)
+STUB(gtk_widget_set_parent_window)
+STUB(gtk_widget_set_realized)
+STUB(gtk_widget_set_redraw_on_allocate)
+STUB(gtk_widget_set_sensitive)
+STUB(gtk_widget_set_window)
+STUB(gtk_widget_show)
+STUB(gtk_widget_show_all)
+STUB(gtk_widget_size_allocate)
+STUB(gtk_widget_size_request)
+STUB(gtk_widget_style_get)
+STUB(gtk_widget_unparent)
+STUB(gtk_window_deiconify)
+STUB(gtk_window_fullscreen)
+STUB(gtk_window_get_group)
+STUB(gtk_window_get_transient_for)
+STUB(gtk_window_get_type)
+STUB(gtk_window_group_add_window)
+STUB(gtk_window_group_get_current_grab)
+STUB(gtk_window_group_new)
+STUB(gtk_window_iconify)
+STUB(gtk_window_is_active)
+STUB(gtk_window_maximize)
+STUB(gtk_window_move)
+STUB(gtk_window_new)
+STUB(gtk_window_present_with_time)
+STUB(gtk_window_resize)
+STUB(gtk_window_set_accept_focus)
+STUB(gtk_window_set_decorated)
+STUB(gtk_window_set_deletable)
+STUB(gtk_window_set_destroy_with_parent)
+STUB(gtk_window_set_geometry_hints)
+STUB(gtk_window_set_icon_name)
+STUB(gtk_window_set_modal)
+STUB(gtk_window_set_skip_taskbar_hint)
+STUB(gtk_window_set_title)
+STUB(gtk_window_set_transient_for)
+STUB(gtk_window_set_type_hint)
+STUB(gtk_window_set_wmclass)
+STUB(gtk_window_unfullscreen)
+STUB(gtk_window_unmaximize)
+#endif
+
+#ifdef GTK3_SYMBOLS
+STUB(gdk_device_manager_get_client_pointer)
+STUB(gdk_display_get_device_manager)
+STUB(gdk_window_get_type)
+STUB(gdk_x11_window_get_xid)
+STUB(gtk_cairo_should_draw_window)
+STUB(gtk_cairo_transform_to_window)
+STUB(gtk_combo_box_text_append)
+STUB(gtk_get_major_version)
+STUB(gtk_get_micro_version)
+STUB(gtk_get_minor_version)
+STUB(gtk_menu_button_new)
+STUB(gtk_render_activity)
+STUB(gtk_render_arrow)
+STUB(gtk_render_background)
+STUB(gtk_render_check)
+STUB(gtk_render_expander)
+STUB(gtk_render_extension)
+STUB(gtk_render_focus)
+STUB(gtk_render_frame)
+STUB(gtk_render_frame_gap)
+STUB(gtk_render_handle)
+STUB(gtk_render_line)
+STUB(gtk_render_option)
+STUB(gtk_render_slider)
+STUB(gtk_style_context_add_class)
+STUB(gtk_style_context_add_region)
+STUB(gtk_style_context_get_background_color)
+STUB(gtk_style_context_get_border)
+STUB(gtk_style_context_get_border_color)
+STUB(gtk_style_context_get_color)
+STUB(gtk_style_context_get_margin)
+STUB(gtk_style_context_get_padding)
+STUB(gtk_style_context_new)
+STUB(gtk_style_context_remove_region)
+STUB(gtk_style_context_restore)
+STUB(gtk_style_context_save)
+STUB(gtk_style_context_set_path)
+STUB(gtk_style_context_set_state)
+STUB(gtk_tree_view_column_get_button)
+STUB(gtk_widget_get_style_context)
+STUB(gtk_widget_path_append_type)
+STUB(gtk_widget_path_new)
+STUB(gtk_widget_set_visual)
+#endif
+
+#ifdef GTK2_SYMBOLS
+STUB(gdk_drawable_get_screen)
+STUB(gdk_rgb_get_colormap)
+STUB(gdk_rgb_get_visual)
+STUB(gdk_window_lookup)
+STUB(gdk_window_set_back_pixmap)
+STUB(gdk_x11_colormap_foreign_new)
+STUB(gdk_x11_colormap_get_xcolormap)
+STUB(gdk_x11_drawable_get_xdisplay)
+STUB(gdk_x11_drawable_get_xid)
+STUB(gdk_x11_window_get_drawable_impl)
+STUB(gdkx_visual_get)
+STUB(gtk_object_get_type)
+#endif
new file mode 100644
--- /dev/null
+++ b/widget/gtk/mozgtk/stub/Makefile.in
@@ -0,0 +1,7 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+include $(topsrcdir)/config/rules.mk
+
+LDFLAGS += -Wl,-soname=$(DLL_PREFIX)mozgtk$(DLL_SUFFIX)
new file mode 100644
--- /dev/null
+++ b/widget/gtk/mozgtk/stub/moz.build
@@ -0,0 +1,16 @@
+# -*- 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/.
+
+SOURCES += [
+    '../mozgtk.c',
+]
+
+for var in ('COMMON_SYMBOLS', 'GTK2_SYMBOLS', 'GTK3_SYMBOLS'):
+    DEFINES[var] = True
+
+LIBRARY_NAME = 'mozgtk_stub'
+
+FORCE_SHARED_LIB = True
--- a/widget/gtkxtbin/Makefile.in
+++ b/widget/gtkxtbin/Makefile.in
@@ -1,12 +1,9 @@
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 include $(topsrcdir)/config/rules.mk
 
-ifdef MOZ_ENABLE_GTK2
 CFLAGS		+= $(MOZ_GTK2_CFLAGS)
-endif
-
--- a/widget/gtkxtbin/gtk2xtbin.c
+++ b/widget/gtkxtbin/gtk2xtbin.c
@@ -78,63 +78,53 @@ static gint             xt_polling_timer
 static guint            tag = 0;
 
 static gboolean
 xt_event_prepare (GSource*  source_data,
                    gint     *timeout)
 {   
   int mask;
 
-  GDK_THREADS_ENTER();
   mask = XPending(xtdisplay);
-  GDK_THREADS_LEAVE();
 
   return (gboolean)mask;
 }
 
 static gboolean
 xt_event_check (GSource*  source_data)
 {
-  GDK_THREADS_ENTER ();
-
   if (xt_event_poll_fd.revents & G_IO_IN) {
     int mask;
     mask = XPending(xtdisplay);
-    GDK_THREADS_LEAVE ();
     return (gboolean)mask;
   }
 
-  GDK_THREADS_LEAVE ();
   return FALSE;
 }   
 
 static gboolean
 xt_event_dispatch (GSource*  source_data,
                     GSourceFunc call_back,
                     gpointer  user_data)
 {
   XEvent event;
   XtAppContext ac;
   int i = 0;
 
   ac = XtDisplayToApplicationContext(xtdisplay);
 
-  GDK_THREADS_ENTER ();
-
   /* Process only real X traffic here.  We only look for data on the
    * pipe, limit it to XTBIN_MAX_EVENTS and only call
    * XtAppProcessEvent so that it will look for X events.  There's no
    * timer processing here since we already have a timer callback that
    * does it.  */
   for (i=0; i < XTBIN_MAX_EVENTS && XPending(xtdisplay); i++) {
     XtAppProcessEvent(ac, XtIMXEvent);
   }
 
-  GDK_THREADS_LEAVE ();
-
   return TRUE;  
 }
 
 static GSourceFuncs xt_event_funcs = {
   xt_event_prepare,
   xt_event_check,
   xt_event_dispatch,
   NULL,
--- a/widget/gtkxtbin/gtk2xtbin.h
+++ b/widget/gtkxtbin/gtk2xtbin.h
@@ -4,19 +4,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef __GTK_XTBIN_H__
 #define __GTK_XTBIN_H__
 
 #include <gtk/gtk.h>
-#if (MOZ_WIDGET_GTK == 3)
-#include <gtk/gtkx.h>
-#endif
 #include <X11/Intrinsic.h>
 #include <X11/Xutil.h>
 #include <X11/Xlib.h>
 #ifdef MOZILLA_CLIENT
 #include "nscore.h"
 #ifdef _IMPL_GTKXTBIN_API
 #define GTKXTBIN_API(type) NS_EXPORT_(type)
 #else
@@ -25,39 +22,41 @@
 #else
 #define GTKXTBIN_API(type) type
 #endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
+typedef struct _XtClient XtClient;
+
+struct _XtClient {
+  Display	*xtdisplay;
+  Widget	top_widget;    /* The toplevel widget */
+  Widget	child_widget;  /* The embedded widget */
+  Visual	*xtvisual;
+  int		xtdepth;
+  Colormap	xtcolormap;
+  Window	oldwindow;
+};
+
+#if (GTK_MAJOR_VERSION == 2)
 typedef struct _GtkXtBin GtkXtBin;
 typedef struct _GtkXtBinClass GtkXtBinClass;
 
 #define GTK_TYPE_XTBIN                  (gtk_xtbin_get_type ())
 #define GTK_XTBIN(obj)                  (G_TYPE_CHECK_INSTANCE_CAST  ((obj), \
                                          GTK_TYPE_XTBIN, GtkXtBin))
 #define GTK_XTBIN_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), \
                                          GTK_TYPE_XTBIN, GtkXtBinClass))
 #define GTK_IS_XTBIN(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
                                          GTK_TYPE_XTBIN))
 #define GTK_IS_XTBIN_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), \
                                          GTK_TYPE_XTBIN))
-typedef struct _XtClient XtClient;
-
-struct _XtClient {
-  Display	*xtdisplay;
-  Widget	top_widget;    /* The toplevel widget */
-  Widget	child_widget;  /* The embedded widget */
-  Visual	*xtvisual;
-  int		xtdepth;
-  Colormap	xtcolormap;
-  Window	oldwindow;
-};
 
 struct _GtkXtBin
 {
   GtkSocket      gsocket;
   GdkWindow     *parent_window;
   Display       *xtdisplay;        /* Xt Toolkit Display */
 
   Window         xtwindow;         /* Xt Toolkit XWindow */
@@ -66,16 +65,17 @@ struct _GtkXtBin
   
 struct _GtkXtBinClass
 {
   GtkSocketClass parent_class;
 };
 
 GTKXTBIN_API(GType)       gtk_xtbin_get_type (void);
 GTKXTBIN_API(GtkWidget *) gtk_xtbin_new (GdkWindow *parent_window, String *f);
+#endif
 
 typedef struct _XtTMRec {
     XtTranslations  translations;       /* private to Translation Manager    */
     XtBoundActions  proc_table;         /* procedure bindings for actions    */
     struct _XtStateRec *current_state;  /* Translation Manager state ptr     */
     unsigned long   lastEventTime;
 } XtTMRec, *XtTM;   
 
--- a/widget/gtkxtbin/moz.build
+++ b/widget/gtkxtbin/moz.build
@@ -3,16 +3,15 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
     'gtk2xtbin.h',
 ]
 
-if CONFIG['MOZ_ENABLE_GTK2']:
-    SOURCES += [
-        'gtk2xtbin.c',
-    ]
+SOURCES += [
+    'gtk2xtbin.c',
+]
 
 FINAL_LIBRARY = 'xul'
 
 DEFINES['_IMPL_GTKXTBIN_API'] = True