Merge m-c to b-i
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 22 Oct 2013 20:09:33 -0700
changeset 151774 78f2fa585ce782c3a07050aab5473f7f20c1bd01
parent 151773 9c73cb321afbffbd6edca04c92627c9bd2a87fa6 (current diff)
parent 151733 21d97baadc051f8d6beb76e335863ede46f96a36 (diff)
child 151775 4c7a2feefb4abf7840db6549efb841c46e00da68
push id25507
push usercbook@mozilla.com
push dateWed, 23 Oct 2013 12:52:10 +0000
treeherdermozilla-central@8803e8c0ee3e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to b-i
build/cl.py
intl/uconv/ucvcn/nsUnicodeToISO2022CN.cpp
intl/uconv/ucvcn/nsUnicodeToISO2022CN.h
js/src/build/cl.py
testing/mochitest/b2g.json
--- a/accessible/src/base/DocManager.cpp
+++ b/accessible/src/base/DocManager.cpp
@@ -324,17 +324,17 @@ DocManager::HandleDOMDocumentLoad(nsIDoc
 }
 
 void
 DocManager::AddListeners(nsIDocument* aDocument,
                          bool aAddDOMContentLoadedListener)
 {
   nsPIDOMWindow* window = aDocument->GetWindow();
   EventTarget* target = window->GetChromeEventHandler();
-  nsEventListenerManager* elm = target->GetListenerManager(true);
+  nsEventListenerManager* elm = target->GetOrCreateListenerManager();
   elm->AddEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
                               dom::TrustedEventsAtCapture());
 
 #ifdef A11Y_LOG
   if (logging::IsEnabled(logging::eDocCreate))
     logging::Text("added 'pagehide' listener");
 #endif
 
@@ -354,17 +354,17 @@ DocManager::RemoveListeners(nsIDocument*
   nsPIDOMWindow* window = aDocument->GetWindow();
   if (!window)
     return;
 
   EventTarget* target = window->GetChromeEventHandler();
   if (!target)
     return;
 
-  nsEventListenerManager* elm = target->GetListenerManager(true);
+  nsEventListenerManager* elm = target->GetOrCreateListenerManager();
   elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("pagehide"),
                                  dom::TrustedEventsAtCapture());
 
   elm->RemoveEventListenerByType(this, NS_LITERAL_STRING("DOMContentLoaded"),
                                  dom::TrustedEventsAtCapture());
 }
 
 DocAccessible*
--- a/accessible/src/base/Relation.h
+++ b/accessible/src/base/Relation.h
@@ -51,23 +51,16 @@ public:
 
   Relation& operator = (const RelationCopyHelper& aRH)
   {
     mFirstIter = aRH.mFirstIter;
     mLastIter = aRH.mLastIter;
     return *this;
   }
 
-  Relation& operator = (Relation& aRelation)
-  {
-    mFirstIter = aRelation.mFirstIter;
-    mLastIter = aRelation.mLastIter;
-    return *this;
-  }
-
   operator RelationCopyHelper()
   {
     return RelationCopyHelper(mFirstIter.forget(), mLastIter);
   }
 
   inline void AppendIter(AccIterable* aIter)
   {
     if (mLastIter)
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -41,17 +41,17 @@ using namespace mozilla;
 // nsCoreUtils
 ////////////////////////////////////////////////////////////////////////////////
 
 bool
 nsCoreUtils::HasClickListener(nsIContent *aContent)
 {
   NS_ENSURE_TRUE(aContent, false);
   nsEventListenerManager* listenerManager =
-    aContent->GetListenerManager(false);
+    aContent->GetExistingListenerManager();
 
   return listenerManager &&
     (listenerManager->HasListenersFor(nsGkAtoms::onclick) ||
      listenerManager->HasListenersFor(nsGkAtoms::onmousedown) ||
      listenerManager->HasListenersFor(nsGkAtoms::onmouseup));
 }
 
 void
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -809,16 +809,19 @@ pref("dom.mozInputMethod.enabled", true)
 // to communicate with a usb cable via adb forward
 pref("devtools.debugger.unix-domain-socket", "/data/local/debugger-socket");
 
 // enable Skia/GL (OpenGL-accelerated 2D drawing) for large enough 2d canvases,
 // falling back to Skia/software for smaller canvases
 pref("gfx.canvas.azure.backends", "skia");
 pref("gfx.canvas.azure.accelerated", true);
 
+// Turn on dynamic cache size for Skia
+pref("gfx.canvas.skiagl.dynamic-cache", true);
+
 // Enable Telephony API
 pref("dom.telephony.enabled", true);
 
 // Cell Broadcast API
 pref("dom.cellbroadcast.enabled", true);
 pref("ril.cellbroadcast.disabled", false);
 
 // ICC API
--- a/config/config.mk
+++ b/config/config.mk
@@ -211,18 +211,18 @@ endif
 endif
 
 OS_CONFIG	:= $(OS_ARCH)$(OS_RELEASE)
 
 MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
 MOZ_WIDGET_SUPPORT_LIBS    = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
 
 ifdef _MSC_VER
-CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
-CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
+CC_WRAPPER = $(call py_action,cl)
+CXX_WRAPPER = $(call py_action,cl)
 endif # _MSC_VER
 
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
 MKDIR ?= mkdir
 SLEEP ?= sleep
 TOUCH ?= touch
 
@@ -891,20 +891,8 @@ PLY_INCLUDE = -I$(topsrcdir)/other-licen
 
 export CL_INCLUDES_PREFIX
 
 ifdef MOZ_GTK2_CFLAGS
 MOZ_GTK2_CFLAGS := -I$(topsrcdir)/widget/gtk/compat $(MOZ_GTK2_CFLAGS)
 endif
 
 DEFINES += -DNO_NSPR_10_SUPPORT
-
-# Run a named Python build action. The first argument is the name of the build
-# action. The second argument are the arguments to pass to the action (space
-# delimited arguments). e.g.
-#
-#   libs::
-#       $(call py_action,purge_manifests,_build_manifests/purge/foo.manifest)
-ifdef .PYMAKE
-py_action = %mozbuild.action.$(1) main $(2)
-else
-py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
-endif
--- a/config/makefiles/functions.mk
+++ b/config/makefiles/functions.mk
@@ -15,8 +15,20 @@ ifdef INCLUDED_FUNCTIONS_MK
 $(error Do not include functions.mk twice!)
 endif
 INCLUDED_FUNCTIONS_MK = 1
 
 core_abspath = $(error core_abspath is unsupported, use $$(abspath) instead)
 core_realpath = $(error core_realpath is unsupported)
 
 core_winabspath = $(error core_winabspath is unsupported)
+
+# Run a named Python build action. The first argument is the name of the build
+# action. The second argument are the arguments to pass to the action (space
+# delimited arguments). e.g.
+#
+#   libs::
+#       $(call py_action,purge_manifests,_build_manifests/purge/foo.manifest)
+ifdef .PYMAKE
+py_action = %mozbuild.action.$(1) main $(2)
+else
+py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
+endif
--- a/configure.in
+++ b/configure.in
@@ -5364,17 +5364,17 @@ if test -n "$MOZ_VP8"; then
         LIBS=$_SAVE_LIBS
     fi
 fi
 
 AC_SUBST(MOZ_NATIVE_LIBVPX)
 AC_SUBST(MOZ_LIBVPX_CFLAGS)
 AC_SUBST(MOZ_LIBVPX_LIBS)
 
-if test "$MOZ_WEBM"; then
+if test "$MOZ_WEBM" -o "$MOZ_OGG"; then
     MOZ_CUBEB=1
     if test "$MOZ_SAMPLE_TYPE_FLOAT32"; then
         MOZ_VORBIS=1
     else
         MOZ_TREMOR=1
     fi
 fi
 
@@ -5486,20 +5486,33 @@ fi
 if test -n "$MOZ_SOUNDTOUCH"; then
     AC_DEFINE(MOZ_SOUNDTOUCH)
 fi
 
 if test -n "$MOZ_CUBEB"; then
     AC_DEFINE(MOZ_CUBEB)
 fi
 
+if test -n "$MOZ_OPUS" -a -z "$MOZ_OGG"; then
+    AC_MSG_ERROR([MOZ_OPUS requires MOZ_OGG which is disabled.])
+fi
+
+if test -n "$MOZ_VORBIS" -a -z "$MOZ_OGG"; then
+    AC_MSG_ERROR([MOZ_VORBIS requires MOZ_OGG which is disabled.
+Note that you need vorbis support for WebM playback.])
+fi
+
 if test -n "$MOZ_VORBIS" -a -n "$MOZ_TREMOR"; then
     AC_MSG_ERROR([MOZ_VORBIS and MOZ_TREMOR are mutually exclusive!  The build system should not allow them both to be set, but they are.  Please file a bug at https://bugzilla.mozilla.org/])
 fi
 
+if test -n "$MOZ_WEBRTC" -a -z "$MOZ_OPUS"; then
+    AC_MSG_ERROR([MOZ_WEBRTC requires MOZ_OPUS which is disabled.])
+fi
+
 if test -n "$MOZ_VORBIS"; then
     AC_DEFINE(MOZ_VORBIS)
 fi
 
 if test -n "$MOZ_TREMOR"; then
     AC_DEFINE(MOZ_TREMOR)
 fi
 
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1054,25 +1054,29 @@ public:
    *
    * @param aNode The node to traverse.
    * @param children The buffer to push a listener manager pointer into.
    */
   static void TraverseListenerManager(nsINode *aNode,
                                       nsCycleCollectionTraversalCallback &cb);
 
   /**
-   * Get the eventlistener manager for aNode. If a new eventlistener manager
-   * was created, aCreated is set to true.
+   * Get the eventlistener manager for aNode, creating it if it does not
+   * already exist.
    *
    * @param aNode The node for which to get the eventlistener manager.
-   * @param aCreateIfNotFound If false, returns a listener manager only if
-   *                          one already exists.
    */
-  static nsEventListenerManager* GetListenerManager(nsINode* aNode,
-                                                    bool aCreateIfNotFound);
+  static nsEventListenerManager* GetListenerManagerForNode(nsINode* aNode);
+  /**
+   * Get the eventlistener manager for aNode, returning null if it does not
+   * already exist.
+   *
+   * @param aNode The node for which to get the eventlistener manager.
+   */
+  static nsEventListenerManager* GetExistingListenerManagerForNode(const nsINode* aNode);
 
   static void UnmarkGrayJSListenersInCCGenerationDocuments(uint32_t aGeneration);
 
   /**
    * Remove the eventlistener manager for aNode.
    *
    * @param aNode The node for which to remove the eventlistener manager.
    */
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -795,16 +795,22 @@ public:
 #endif
     return node;
   }
 
   /**
    * See nsIDOMEventTarget
    */
   NS_DECL_NSIDOMEVENTTARGET
+
+  virtual nsEventListenerManager*
+  GetExistingListenerManager() const MOZ_OVERRIDE;
+  virtual nsEventListenerManager*
+  GetOrCreateListenerManager() MOZ_OVERRIDE;
+
   using mozilla::dom::EventTarget::RemoveEventListener;
   using nsIDOMEventTarget::AddEventListener;
   virtual void AddEventListener(const nsAString& aType,
                                 mozilla::dom::EventListener* aListener,
                                 bool aUseCapture,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
   using nsIDOMEventTarget::AddSystemEventListener;
--- a/content/base/src/Element.cpp
+++ b/content/base/src/Element.cpp
@@ -1808,17 +1808,17 @@ Element::SetMappedAttribute(nsIDocument*
   return false;
 }
 
 nsEventListenerManager*
 Element::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
                                         bool* aDefer)
 {
   *aDefer = true;
-  return GetListenerManager(true);
+  return GetOrCreateListenerManager();
 }
 
 Element::nsAttrInfo
 Element::GetAttrInfo(int32_t aNamespaceID, nsIAtom* aName) const
 {
   NS_ASSERTION(nullptr != aName, "must have attribute name");
   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
                "must have a real namespace ID!");
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -1219,17 +1219,17 @@ FragmentOrElement::MarkUserDataHandler(v
 void
 FragmentOrElement::MarkNodeChildren(nsINode* aNode)
 {
   JSObject* o = GetJSObjectChild(aNode);
   if (o) {
     JS::ExposeObjectToActiveJS(o);
   }
 
-  nsEventListenerManager* elm = aNode->GetListenerManager(false);
+  nsEventListenerManager* elm = aNode->GetExistingListenerManager();
   if (elm) {
     elm->MarkForCC();
   }
 
   if (aNode->HasProperties()) {
     nsIDocument* ownerDoc = aNode->OwnerDoc();
     ownerDoc->PropertyTable(DOM_USER_DATA)->
       Enumerate(aNode, FragmentOrElement::MarkUserData,
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -139,17 +139,17 @@ MarkMessageManagers()
         static_cast<nsFrameMessageManager*>(tabMM)->GetCallback();
       if (cb) {
         nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
         EventTarget* et = fl->GetTabChildGlobalAsEventTarget();
         if (!et) {
           continue;
         }
         static_cast<nsInProcessTabChildGlobal*>(et)->MarkForCC();
-        nsEventListenerManager* elm = et->GetListenerManager(false);
+        nsEventListenerManager* elm = et->GetExistingListenerManager();
         if (elm) {
           elm->MarkForCC();
         }
       }
     }
   }
   if (nsFrameMessageManager::sParentProcessManager) {
     nsFrameMessageManager::sParentProcessManager->MarkForCC();
@@ -183,23 +183,23 @@ MarkContentViewer(nsIContentViewer* aVie
     return;
   }
 
   nsIDocument *doc = aViewer->GetDocument();
   if (doc &&
       doc->GetMarkedCCGeneration() != nsCCUncollectableMarker::sGeneration) {
     doc->MarkUncollectableForCCGeneration(nsCCUncollectableMarker::sGeneration);
     if (aCleanupJS) {
-      nsEventListenerManager* elm = doc->GetListenerManager(false);
+      nsEventListenerManager* elm = doc->GetExistingListenerManager();
       if (elm) {
         elm->MarkForCC();
       }
       nsCOMPtr<EventTarget> win = do_QueryInterface(doc->GetInnerWindow());
       if (win) {
-        elm = win->GetListenerManager(false);
+        elm = win->GetExistingListenerManager();
         if (elm) {
           elm->MarkForCC();
         }
         static_cast<nsGlobalWindow*>(win.get())->UnmarkGrayTimers();
       }
 
       doc->PropertyTable(DOM_USER_DATA_HANDLER)->
         EnumerateAll(MarkUserDataHandler, &nsCCUncollectableMarker::sGeneration);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3628,28 +3628,28 @@ nsContentUtils::HasMutationListeners(nsI
   }
 
   doc->MayDispatchMutationEvent(aTargetForSubtreeModified);
 
   // If we have a window, we can check it for mutation listeners now.
   if (aNode->IsInDoc()) {
     nsCOMPtr<EventTarget> piTarget(do_QueryInterface(window));
     if (piTarget) {
-      nsEventListenerManager* manager = piTarget->GetListenerManager(false);
+      nsEventListenerManager* manager = piTarget->GetExistingListenerManager();
       if (manager && manager->HasMutationListeners()) {
         return true;
       }
     }
   }
 
   // If we have a window, we know a mutation listener is registered, but it
   // might not be in our chain.  If we don't have a window, we might have a
   // mutation listener.  Check quickly to see.
   while (aNode) {
-    nsEventListenerManager* manager = aNode->GetListenerManager(false);
+    nsEventListenerManager* manager = aNode->GetExistingListenerManager();
     if (manager && manager->HasMutationListeners()) {
       return true;
     }
 
     if (aNode->IsNodeOfType(nsINode::eCONTENT)) {
       nsIContent* content = static_cast<nsIContent*>(aNode);
       nsIContent* insertionParent = content->GetXBLInsertionParent();
       if (insertionParent) {
@@ -3761,41 +3761,25 @@ nsContentUtils::TraverseListenerManager(
                                         PL_DHASH_LOOKUP));
   if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
     CycleCollectionNoteChild(cb, entry->mListenerManager.get(),
                              "[via hash] mListenerManager");
   }
 }
 
 nsEventListenerManager*
-nsContentUtils::GetListenerManager(nsINode *aNode,
-                                   bool aCreateIfNotFound)
-{
-  if (!aCreateIfNotFound && !aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
-    return nullptr;
-  }
-  
+nsContentUtils::GetListenerManagerForNode(nsINode *aNode)
+{
   if (!sEventListenerManagersHash.ops) {
     // We're already shut down, don't bother creating an event listener
     // manager.
 
     return nullptr;
   }
 
-  if (!aCreateIfNotFound) {
-    EventListenerManagerMapEntry *entry =
-      static_cast<EventListenerManagerMapEntry *>
-                 (PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
-                                          PL_DHASH_LOOKUP));
-    if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
-      return entry->mListenerManager;
-    }
-    return nullptr;
-  }
-
   EventListenerManagerMapEntry *entry =
     static_cast<EventListenerManagerMapEntry *>
                (PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
                                         PL_DHASH_ADD));
 
   if (!entry) {
     return nullptr;
   }
@@ -3804,16 +3788,41 @@ nsContentUtils::GetListenerManager(nsINo
     entry->mListenerManager = new nsEventListenerManager(aNode);
 
     aNode->SetFlags(NODE_HAS_LISTENERMANAGER);
   }
 
   return entry->mListenerManager;
 }
 
+nsEventListenerManager*
+nsContentUtils::GetExistingListenerManagerForNode(const nsINode *aNode)
+{
+  if (!aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
+    return nullptr;
+  }
+  
+  if (!sEventListenerManagersHash.ops) {
+    // We're already shut down, don't bother creating an event listener
+    // manager.
+
+    return nullptr;
+  }
+
+  EventListenerManagerMapEntry *entry =
+    static_cast<EventListenerManagerMapEntry *>
+               (PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
+                                        PL_DHASH_LOOKUP));
+  if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
+    return entry->mListenerManager;
+  }
+
+  return nullptr;
+}
+
 /* static */
 void
 nsContentUtils::RemoveListenerManager(nsINode *aNode)
 {
   if (sEventListenerManagersHash.ops) {
     EventListenerManagerMapEntry *entry =
       static_cast<EventListenerManagerMapEntry *>
                  (PL_DHashTableOperate(&sEventListenerManagersHash, aNode,
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1654,17 +1654,17 @@ nsDocument::Release()
 NS_IMETHODIMP_(void)
 nsDocument::DeleteCycleCollectable()
 {
   delete this;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDocument)
   if (Element::CanSkip(tmp, aRemovingAllowed)) {
-    nsEventListenerManager* elm = tmp->GetListenerManager(false);
+    nsEventListenerManager* elm = tmp->GetExistingListenerManager();
     if (elm) {
       elm->MarkForCC();
     }
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDocument)
@@ -6966,27 +6966,33 @@ nsDocument::GetViewportInfo(const Screen
     }
 
     return nsViewportInfo(scaleFloat, scaleMinFloat, scaleMaxFloat, size,
                           mAutoSize, mAllowZoom);
   }
 }
 
 nsEventListenerManager*
-nsDocument::GetListenerManager(bool aCreateIfNotFound)
-{
-  if (!mListenerManager && aCreateIfNotFound) {
+nsDocument::GetOrCreateListenerManager()
+{
+  if (!mListenerManager) {
     mListenerManager =
       new nsEventListenerManager(static_cast<EventTarget*>(this));
     SetFlags(NODE_HAS_LISTENERMANAGER);
   }
 
   return mListenerManager;
 }
 
+nsEventListenerManager*
+nsDocument::GetExistingListenerManager() const
+{
+  return mListenerManager;
+}
+
 nsresult
 nsDocument::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
 {
   aVisitor.mCanHandle = true;
    // FIXME! This is a hack to make middle mouse paste working also in Editor.
    // Bug 329119
   aVisitor.mForceContentDispatch = true;
 
@@ -7670,18 +7676,17 @@ nsDocument::CanSavePresentation(nsIReque
   nsPIDOMWindow* win = GetInnerWindow();
   if (win && win->TimeoutSuspendCount()) {
     return false;
   }
 
   // Check our event listener manager for unload/beforeunload listeners.
   nsCOMPtr<EventTarget> piTarget = do_QueryInterface(mScriptGlobalObject);
   if (piTarget) {
-    nsEventListenerManager* manager =
-      piTarget->GetListenerManager(false);
+    nsEventListenerManager* manager = piTarget->GetExistingListenerManager();
     if (manager && manager->HasUnloadListeners()) {
       return false;
     }
   }
 
   // Check if we have pending network requests
   nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
   if (loadGroup) {
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -768,18 +768,18 @@ public:
   // nsIDOMXMLDocument
   NS_DECL_NSIDOMXMLDOCUMENT
 
   // nsIDOMDocumentXBL
   NS_DECL_NSIDOMDOCUMENTXBL
 
   // nsIDOMEventTarget
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
-  virtual nsEventListenerManager*
-    GetListenerManager(bool aCreateIfNotFound) MOZ_OVERRIDE;
+  virtual nsEventListenerManager* GetOrCreateListenerManager() MOZ_OVERRIDE;
+  virtual nsEventListenerManager* GetExistingListenerManager() const MOZ_OVERRIDE;
 
   // nsIScriptObjectPrincipal
   virtual nsIPrincipal* GetPrincipal() MOZ_OVERRIDE;
 
   // nsIApplicationCacheContainer
   NS_DECL_NSIAPPLICATIONCACHECONTAINER
 
   // nsIObserver
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1777,16 +1777,17 @@ GK_ATOM(processingInstructionTagName, "#
 GK_ATOM(textTagName, "#text")
 
 // Frame types
 GK_ATOM(bcTableCellFrame, "BCTableCellFrame") // table cell in border collapsing model
 GK_ATOM(blockFrame, "BlockFrame")
 GK_ATOM(boxFrame, "BoxFrame")
 GK_ATOM(brFrame, "BRFrame")
 GK_ATOM(bulletFrame, "BulletFrame")
+GK_ATOM(colorControlFrame, "colorControlFrame")
 GK_ATOM(columnSetFrame, "ColumnSetFrame")
 GK_ATOM(comboboxControlFrame, "ComboboxControlFrame")
 GK_ATOM(comboboxDisplayFrame, "ComboboxDisplayFrame")
 GK_ATOM(deckFrame, "DeckFrame")
 GK_ATOM(fieldSetFrame, "FieldSetFrame")
 GK_ATOM(flexContainerFrame, "FlexContainerFrame")
 GK_ATOM(formControlFrame, "FormControlFrame") // radio or checkbox
 GK_ATOM(frameSetFrame, "FrameSetFrame")
--- a/content/base/src/nsINode.cpp
+++ b/content/base/src/nsINode.cpp
@@ -1033,17 +1033,17 @@ nsINode::AddEventListener(const nsAStrin
                "explicit by making aOptionalArgc non-zero.");
 
   if (!aWantsUntrusted &&
       (aOptionalArgc < 2 &&
        !nsContentUtils::IsChromeDoc(OwnerDoc()))) {
     aWantsUntrusted = true;
   }
 
-  nsEventListenerManager* listener_manager = GetListenerManager(true);
+  nsEventListenerManager* listener_manager = GetOrCreateListenerManager();
   NS_ENSURE_STATE(listener_manager);
   listener_manager->AddEventListener(aType, aListener, aUseCapture,
                                      aWantsUntrusted);
   return NS_OK;
 }
 
 void
 nsINode::AddEventListener(const nsAString& aType,
@@ -1054,17 +1054,17 @@ nsINode::AddEventListener(const nsAStrin
 {
   bool wantsUntrusted;
   if (aWantsUntrusted.IsNull()) {
     wantsUntrusted = !nsContentUtils::IsChromeDoc(OwnerDoc());
   } else {
     wantsUntrusted = aWantsUntrusted.Value();
   }
 
-  nsEventListenerManager* listener_manager = GetListenerManager(true);
+  nsEventListenerManager* listener_manager = GetOrCreateListenerManager();
   if (!listener_manager) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
   listener_manager->AddEventListener(aType, aListener, aUseCapture,
                                      wantsUntrusted);
 }
 
@@ -1090,17 +1090,17 @@ nsINode::AddSystemEventListener(const ns
                                    aWantsUntrusted);
 }
 
 NS_IMETHODIMP
 nsINode::RemoveEventListener(const nsAString& aType,
                              nsIDOMEventListener* aListener,
                              bool aUseCapture)
 {
-  nsEventListenerManager* elm = GetListenerManager(false);
+  nsEventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
   return NS_OK;
 }
 
 NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsINode)
 
@@ -1152,19 +1152,25 @@ nsINode::DispatchDOMEvent(WidgetEvent* a
                           nsPresContext* aPresContext,
                           nsEventStatus* aEventStatus)
 {
   return nsEventDispatcher::DispatchDOMEvent(this, aEvent, aDOMEvent,
                                              aPresContext, aEventStatus);
 }
 
 nsEventListenerManager*
-nsINode::GetListenerManager(bool aCreateIfNotFound)
+nsINode::GetOrCreateListenerManager()
 {
-  return nsContentUtils::GetListenerManager(this, aCreateIfNotFound);
+  return nsContentUtils::GetListenerManagerForNode(this);
+}
+
+nsEventListenerManager*
+nsINode::GetExistingListenerManager() const
+{
+  return nsContentUtils::GetExistingListenerManagerForNode(this);
 }
 
 nsIScriptContext*
 nsINode::GetContextForEventHandlers(nsresult* aRv)
 {
   return nsContentUtils::GetContextForEventHandlers(this, aRv);
 }
 
@@ -2159,18 +2165,17 @@ nsINode::GetBoundMutationObservers(nsTAr
     }
   }
 }
 
 size_t
 nsINode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = 0;
-  nsEventListenerManager* elm =
-    const_cast<nsINode*>(this)->GetListenerManager(false);
+  nsEventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
     n += elm->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mNodeInfo
   // - mSlots
@@ -2178,23 +2183,23 @@ nsINode::SizeOfExcludingThis(MallocSizeO
   // The following members are not measured:
   // - mParent, mNextSibling, mPreviousSibling, mFirstChild: because they're
   //   non-owning
   return n;
 }
 
 #define EVENT(name_, id_, type_, struct_)                                    \
   EventHandlerNonNull* nsINode::GetOn##name_() {                             \
-    nsEventListenerManager *elm = GetListenerManager(false);                 \
+    nsEventListenerManager *elm = GetExistingListenerManager();              \
     return elm ? elm->GetEventHandler(nsGkAtoms::on##name_, EmptyString())   \
                : nullptr;                                                    \
   }                                                                          \
   void nsINode::SetOn##name_(EventHandlerNonNull* handler)                   \
   {                                                                          \
-    nsEventListenerManager *elm = GetListenerManager(true);                  \
+    nsEventListenerManager *elm = GetOrCreateListenerManager();              \
     if (elm) {                                                               \
       elm->SetEventHandler(nsGkAtoms::on##name_, EmptyString(), handler);    \
     }                                                                        \
   }                                                                          \
   NS_IMETHODIMP nsINode::GetOn##name_(JSContext *cx, JS::Value *vp) {        \
     EventHandlerNonNull* h = GetOn##name_();                                 \
     vp->setObjectOrNull(h ? h->Callable().get() : nullptr);                  \
     return NS_OK;                                                            \
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -226,17 +226,17 @@ nsNodeUtils::LastRelease(nsINode* aNode)
   }
   aNode->UnsetFlags(NODE_HAS_PROPERTIES);
 
   if (aNode->NodeType() != nsIDOMNode::DOCUMENT_NODE &&
       aNode->HasFlag(NODE_HAS_LISTENERMANAGER)) {
 #ifdef DEBUG
     if (nsContentUtils::IsInitialized()) {
       nsEventListenerManager* manager =
-        nsContentUtils::GetListenerManager(aNode, false);
+        nsContentUtils::GetExistingListenerManagerForNode(aNode);
       if (!manager) {
         NS_ERROR("Huh, our bit says we have a listener manager list, "
                  "but there's nothing in the hash!?!!");
       }
     }
 #endif
 
     nsContentUtils::RemoveListenerManager(aNode);
@@ -475,17 +475,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
       // XXX what if oldDoc is null, we don't know if this should be
       // registered or not! Can that really happen?
       if (wasRegistered) {
         newDoc->RegisterFreezableElement(aNode->AsElement());
       }
 
       nsPIDOMWindow* window = newDoc->GetInnerWindow();
       if (window) {
-        nsEventListenerManager* elm = aNode->GetListenerManager(false);
+        nsEventListenerManager* elm = aNode->GetExistingListenerManager();
         if (elm) {
           window->SetMutationListeners(elm->MutationListenerBits());
           if (elm->MayHavePaintEventListener()) {
             window->SetHasPaintEventListeners();
           }
           if (elm->MayHaveAudioAvailableEventListener()) {
             window->SetHasAudioAvailableEventListeners();
           }
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -2167,17 +2167,18 @@ nsXMLHttpRequest::OnStopRequest(nsIReque
   if (!mResponseXML) {
     ChangeStateToDone();
     return NS_OK;
   }
   if (mIsHtml) {
     NS_ASSERTION(!(mState & XML_HTTP_REQUEST_SYNCLOOPING),
       "We weren't supposed to support HTML parsing with XHR!");
     nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(mResponseXML);
-    nsEventListenerManager* manager = eventTarget->GetListenerManager(true);
+    nsEventListenerManager* manager =
+      eventTarget->GetOrCreateListenerManager();
     manager->AddEventListenerByType(new nsXHRParseEndListener(this),
                                     NS_LITERAL_STRING("DOMContentLoaded"),
                                     dom::TrustedEventsAtSystemGroupBubble());
     return NS_OK;
   }
   // We might have been sent non-XML data. If that was the case,
   // we should null out the document member. The idea in this
   // check here is that if there is no document element it is not
--- a/content/events/public/EventTarget.h
+++ b/content/events/public/EventTarget.h
@@ -21,18 +21,18 @@ class ErrorResult;
 namespace dom {
 
 class EventListener;
 class EventHandlerNonNull;
 template <class T> struct Nullable;
 
 // IID for the dom::EventTarget interface
 #define NS_EVENTTARGET_IID \
-{ 0x0a5aed21, 0x0bab, 0x48b3, \
- { 0xbe, 0x4b, 0xd4, 0xf9, 0xd4, 0xea, 0xc7, 0xdb } }
+{ 0xce3817d0, 0x177b, 0x402f, \
+ { 0xae, 0x75, 0xf8, 0x4e, 0xbe, 0x5a, 0x07, 0xc3 } }
 
 class EventTarget : public nsIDOMEventTarget,
                     public nsWrapperCache
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_EVENTTARGET_IID)
 
   // WebIDL API
@@ -65,16 +65,27 @@ public:
   virtual void EventListenerAdded(nsIAtom* aType) {}
   virtual void EventListenerRemoved(nsIAtom* aType) {}
 
   // Returns an outer window that corresponds to the inner window this event
   // target is associated with.  Will return null if the inner window is not the
   // current inner or if there is no window around at all.
   virtual nsIDOMWindow* GetOwnerGlobal() = 0;
 
+  /**
+   * Get the event listener manager, creating it if it does not already exist.
+   */
+  virtual nsEventListenerManager* GetOrCreateListenerManager() = 0;
+
+  /**
+   * Get the event listener manager, returning null if it does not already
+   * exist.
+   */
+  virtual nsEventListenerManager* GetExistingListenerManager() const = 0;
+
 protected:
   EventHandlerNonNull* GetEventHandler(nsIAtom* aType,
                                        const nsAString& aTypeString);
   void SetEventHandler(nsIAtom* aType, const nsAString& aTypeString,
                        EventHandlerNonNull* aHandler);
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(EventTarget, NS_EVENTTARGET_IID)
--- a/content/events/src/EventTarget.cpp
+++ b/content/events/src/EventTarget.cpp
@@ -11,26 +11,26 @@ namespace mozilla {
 namespace dom {
 
 void
 EventTarget::RemoveEventListener(const nsAString& aType,
                                  EventListener* aListener,
                                  bool aUseCapture,
                                  ErrorResult& aRv)
 {
-  nsEventListenerManager* elm = GetListenerManager(false);
+  nsEventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
 }
 
 EventHandlerNonNull*
 EventTarget::GetEventHandler(nsIAtom* aType, const nsAString& aTypeString)
 {
-  nsEventListenerManager* elm = GetListenerManager(false);
+  nsEventListenerManager* elm = GetExistingListenerManager();
   return elm ? elm->GetEventHandler(aType, aTypeString) : nullptr;
 }
 
 void
 EventTarget::SetEventHandler(const nsAString& aType,
                              EventHandlerNonNull* aHandler,
                              ErrorResult& aRv)
 {
@@ -47,13 +47,13 @@ EventTarget::SetEventHandler(const nsASt
                   Substring(aType, 2), // Remove "on"
                   aHandler);
 }
 
 void
 EventTarget::SetEventHandler(nsIAtom* aType, const nsAString& aTypeString,
                              EventHandlerNonNull* aHandler)
 {
-  GetListenerManager(true)->SetEventHandler(aType, aTypeString, aHandler);
+  GetOrCreateListenerManager()->SetEventHandler(aType, aTypeString, aHandler);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -149,17 +149,17 @@ nsDOMEventTargetHelper::DisconnectFromOw
   }
 }
 
 NS_IMETHODIMP
 nsDOMEventTargetHelper::RemoveEventListener(const nsAString& aType,
                                             nsIDOMEventListener* aListener,
                                             bool aUseCapture)
 {
-  nsEventListenerManager* elm = GetListenerManager(false);
+  nsEventListenerManager* elm = GetExistingListenerManager();
   if (elm) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
 
   return NS_OK;
 }
 
 NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsDOMEventTargetHelper)
@@ -176,17 +176,17 @@ nsDOMEventTargetHelper::AddEventListener
                "aWantsUntrusted to false or make the aWantsUntrusted "
                "explicit by making aOptionalArgc non-zero.");
 
   if (aOptionalArgc < 2) {
     nsresult rv = WantsUntrusted(&aWantsUntrusted);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  nsEventListenerManager* elm = GetListenerManager(true);
+  nsEventListenerManager* elm = GetOrCreateListenerManager();
   NS_ENSURE_STATE(elm);
   elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
   return NS_OK;
 }
 
 void
 nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
                                          EventListener* aListener,
@@ -200,17 +200,17 @@ nsDOMEventTargetHelper::AddEventListener
     if (NS_FAILED(rv)) {
       aRv.Throw(rv);
       return;
     }
   } else {
     wantsUntrusted = aWantsUntrusted.Value();
   }
 
-  nsEventListenerManager* elm = GetListenerManager(true);
+  nsEventListenerManager* elm = GetOrCreateListenerManager();
   if (!elm) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
   elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
 }
 
 NS_IMETHODIMP
@@ -314,25 +314,31 @@ nsDOMEventTargetHelper::DispatchDOMEvent
                                          nsEventStatus* aEventStatus)
 {
   return
     nsEventDispatcher::DispatchDOMEvent(this, aEvent, aDOMEvent, aPresContext,
                                         aEventStatus);
 }
 
 nsEventListenerManager*
-nsDOMEventTargetHelper::GetListenerManager(bool aCreateIfNotFound)
+nsDOMEventTargetHelper::GetOrCreateListenerManager()
 {
-  if (!mListenerManager && aCreateIfNotFound) {
+  if (!mListenerManager) {
     mListenerManager = new nsEventListenerManager(this);
   }
 
   return mListenerManager;
 }
 
+nsEventListenerManager*
+nsDOMEventTargetHelper::GetExistingListenerManager() const
+{
+  return mListenerManager;
+}
+
 nsIScriptContext*
 nsDOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
 {
   *aRv = CheckInnerWindowCorrectness();
   if (NS_FAILED(*aRv)) {
     return nullptr;
   }
   nsPIDOMWindow* owner = GetOwner();
--- a/content/events/src/nsDOMEventTargetHelper.h
+++ b/content/events/src/nsDOMEventTargetHelper.h
@@ -39,16 +39,22 @@ public:
     SetIsDOMBinding();
   }
 
   virtual ~nsDOMEventTargetHelper();
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsDOMEventTargetHelper)
 
   NS_DECL_NSIDOMEVENTTARGET
+
+  virtual nsEventListenerManager*
+  GetExistingListenerManager() const MOZ_OVERRIDE;
+  virtual nsEventListenerManager*
+  GetOrCreateListenerManager() MOZ_OVERRIDE;
+
   using mozilla::dom::EventTarget::RemoveEventListener;
   virtual void AddEventListener(const nsAString& aType,
                                 mozilla::dom::EventListener* aListener,
                                 bool aCapture,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMEVENTTARGETHELPER_IID)
@@ -214,24 +220,35 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsDOMEvent
     return _to WillHandleEvent(aVisitor); \
   } \
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor & aVisitor) { \
     return _to PostHandleEvent(aVisitor); \
   } \
   virtual nsresult DispatchDOMEvent(mozilla::WidgetEvent* aEvent, nsIDOMEvent* aDOMEvent, nsPresContext* aPresContext, nsEventStatus* aEventStatus) { \
     return _to DispatchDOMEvent(aEvent, aDOMEvent, aPresContext, aEventStatus); \
   } \
-  virtual nsEventListenerManager * GetListenerManager(bool aMayCreate) { \
-    return _to GetListenerManager(aMayCreate); \
+  virtual nsEventListenerManager * GetOrCreateListenerManager() { \
+    return _to GetOrCreateListenerManager(); \
+  } \
+  virtual nsEventListenerManager * GetExistingListenerManager() const { \
+    return _to GetExistingListenerManager(); \
   } \
   virtual nsIScriptContext * GetContextForEventHandlers(nsresult *aRv) { \
     return _to GetContextForEventHandlers(aRv); \
   } \
   virtual JSContext * GetJSContextForEventHandlers(void) { \
     return _to GetJSContextForEventHandlers(); \
   }
 
 #define NS_REALLY_FORWARD_NSIDOMEVENTTARGET(_class) \
   using _class::AddEventListener;                   \
   using _class::RemoveEventListener;                \
-  NS_FORWARD_NSIDOMEVENTTARGET(_class::)
+  NS_FORWARD_NSIDOMEVENTTARGET(_class::)            \
+  virtual nsEventListenerManager*                   \
+  GetOrCreateListenerManager() {                    \
+    return _class::GetOrCreateListenerManager();    \
+  }                                                 \
+  virtual nsEventListenerManager*                   \
+  GetExistingListenerManager() const {              \
+    return _class::GetExistingListenerManager();    \
+  }
 
 #endif // nsDOMEventTargetHelper_h_
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -180,18 +180,17 @@ public:
     }
     if (aVisitor.mEvent->mFlags.mPropagationStopped) {
       return NS_OK;
     }
     if (!mManager) {
       if (!MayHaveListenerManager() && !aCd.MayHaveNewListenerManager()) {
         return NS_OK;
       }
-      mManager =
-        static_cast<nsEventListenerManager*>(mTarget->GetListenerManager(false));
+      mManager = mTarget->GetExistingListenerManager();
     }
     if (mManager) {
       NS_ASSERTION(aVisitor.mEvent->currentTarget == nullptr,
                    "CurrentTarget should be null!");
       mManager->HandleEvent(aVisitor.mPresContext, aVisitor.mEvent,
                             &aVisitor.mDOMEvent,
                             CurrentTarget(),
                             &aVisitor.mEventStatus,
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -555,17 +555,18 @@ protected:
  */
 inline nsresult
 NS_AddSystemEventListener(mozilla::dom::EventTarget* aTarget,
                           const nsAString& aType,
                           nsIDOMEventListener *aListener,
                           bool aUseCapture,
                           bool aWantsUntrusted)
 {
-  nsEventListenerManager* listenerManager = aTarget->GetListenerManager(true);
+  nsEventListenerManager* listenerManager =
+    aTarget->GetOrCreateListenerManager();
   NS_ENSURE_STATE(listenerManager);
   mozilla::dom::EventListenerFlags flags;
   flags.mInSystemGroup = true;
   flags.mCapture = aUseCapture;
   flags.mAllowUntrustedEvents = aWantsUntrusted;
   listenerManager->AddEventListenerByType(aListener, aType, flags);
   return NS_OK;
 }
--- a/content/events/src/nsEventListenerService.cpp
+++ b/content/events/src/nsEventListenerService.cpp
@@ -157,18 +157,21 @@ NS_IMETHODIMP
 nsEventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget,
                                            uint32_t* aCount,
                                            nsIEventListenerInfo*** aOutArray)
 {
   NS_ENSURE_ARG_POINTER(aEventTarget);
   *aCount = 0;
   *aOutArray = nullptr;
   nsCOMArray<nsIEventListenerInfo> listenerInfos;
-  nsEventListenerManager* elm =
-    aEventTarget->GetListenerManager(false);
+
+  nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
+  NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
+
+  nsEventListenerManager* elm = eventTarget->GetExistingListenerManager();
   if (elm) {
     elm->GetListenerInfo(&listenerInfos);
   }
 
   int32_t count = listenerInfos.Count();
   if (count == 0) {
     return NS_OK;
   }
@@ -216,31 +219,37 @@ nsEventListenerService::GetEventTargetCh
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventListenerService::HasListenersFor(nsIDOMEventTarget* aEventTarget,
                                         const nsAString& aType,
                                         bool* aRetVal)
 {
-  nsEventListenerManager* elm = aEventTarget->GetListenerManager(false);
+  nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
+  NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
+
+  nsEventListenerManager* elm = eventTarget->GetExistingListenerManager();
   *aRetVal = elm && elm->HasListenersFor(aType);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventListenerService::AddSystemEventListener(nsIDOMEventTarget *aTarget,
                                                const nsAString& aType,
                                                nsIDOMEventListener* aListener,
                                                bool aUseCapture)
 {
   NS_PRECONDITION(aTarget, "Missing target");
   NS_PRECONDITION(aListener, "Missing listener");
 
-  nsEventListenerManager* manager = aTarget->GetListenerManager(true);
+  nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
+  NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
+
+  nsEventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
   NS_ENSURE_STATE(manager);
 
   EventListenerFlags flags =
     aUseCapture ? TrustedEventsAtSystemGroupCapture() :
                   TrustedEventsAtSystemGroupBubble();
   manager->AddEventListenerByType(aListener, aType, flags);
   return NS_OK;
 }
@@ -249,17 +258,20 @@ NS_IMETHODIMP
 nsEventListenerService::RemoveSystemEventListener(nsIDOMEventTarget *aTarget,
                                                   const nsAString& aType,
                                                   nsIDOMEventListener* aListener,
                                                   bool aUseCapture)
 {
   NS_PRECONDITION(aTarget, "Missing target");
   NS_PRECONDITION(aListener, "Missing listener");
 
-  nsEventListenerManager* manager = aTarget->GetListenerManager(false);
+  nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
+  NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
+
+  nsEventListenerManager* manager = eventTarget->GetExistingListenerManager();
   if (manager) {
     EventListenerFlags flags =
       aUseCapture ? TrustedEventsAtSystemGroupCapture() :
                     TrustedEventsAtSystemGroupBubble();
     manager->RemoveEventListenerByType(aListener, aType, flags);
   }
 
   return NS_OK;
@@ -268,31 +280,39 @@ nsEventListenerService::RemoveSystemEven
 NS_IMETHODIMP
 nsEventListenerService::AddListenerForAllEvents(nsIDOMEventTarget* aTarget,
                                                 nsIDOMEventListener* aListener,
                                                 bool aUseCapture,
                                                 bool aWantsUntrusted,
                                                 bool aSystemEventGroup)
 {
   NS_ENSURE_STATE(aTarget && aListener);
-  nsEventListenerManager* manager = aTarget->GetListenerManager(true);
+
+  nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
+  NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
+
+  nsEventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
   NS_ENSURE_STATE(manager);
   manager->AddListenerForAllEvents(aListener, aUseCapture, aWantsUntrusted,
                                aSystemEventGroup);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsEventListenerService::RemoveListenerForAllEvents(nsIDOMEventTarget* aTarget,
                                                    nsIDOMEventListener* aListener,
                                                    bool aUseCapture,
                                                    bool aSystemEventGroup)
 {
   NS_ENSURE_STATE(aTarget && aListener);
-  nsEventListenerManager* manager = aTarget->GetListenerManager(false);
+
+  nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
+  NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
+
+  nsEventListenerManager* manager = eventTarget->GetExistingListenerManager();
   if (manager) {
     manager->RemoveListenerForAllEvents(aListener, aUseCapture, aSystemEventGroup);
   }
   return NS_OK;
 }
 
 nsresult
 NS_NewEventListenerService(nsIEventListenerService** aResult)
--- a/content/html/content/src/HTMLInputElement.cpp
+++ b/content/html/content/src/HTMLInputElement.cpp
@@ -2672,16 +2672,24 @@ HTMLInputElement::SetValueInternal(const
       } else {
         mInputData.mValue = ToNewUnicode(value);
         if (aSetValueChanged) {
           SetValueChanged(true);
         }
         OnValueChanged(!mParserCreating);
       }
 
+      // Call parent's SetAttr for color input so its control frame is notified
+      // and updated
+      if (mType == NS_FORM_INPUT_COLOR) {
+        return nsGenericHTMLFormElement::SetAttr(kNameSpaceID_None,
+                                                 nsGkAtoms::value, aValue,
+                                                 true);
+      }
+
       return NS_OK;
     }
 
     case VALUE_MODE_DEFAULT:
     case VALUE_MODE_DEFAULT_ON:
       // If the value of a hidden input was changed, we mark it changed so that we
       // will know we need to save / restore the value.  Yes, we are overloading
       // the meaning of ValueChanged just a teensy bit to save a measly byte of
@@ -3525,16 +3533,17 @@ HTMLInputElement::PostHandleEvent(nsEven
                   break;  // If we are submitting, do not send click event
                 }
                 // else fall through and treat Space like click...
               }
               case NS_FORM_INPUT_BUTTON:
               case NS_FORM_INPUT_RESET:
               case NS_FORM_INPUT_SUBMIT:
               case NS_FORM_INPUT_IMAGE: // Bug 34418
+              case NS_FORM_INPUT_COLOR:
               {
                 WidgetMouseEvent event(aVisitor.mEvent->mFlags.mIsTrusted,
                                        NS_MOUSE_CLICK, nullptr,
                                        WidgetMouseEvent::eReal);
                 event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
                 nsEventStatus status = nsEventStatus_eIgnore;
 
                 nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this),
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -837,17 +837,17 @@ nsGenericHTMLElement::GetEventListenerMa
     // XXXbz sXBL/XBL2 issue: should we instead use GetCurrentDoc() here,
     // override BindToTree for those classes and munge event listeners there?
     nsIDocument *document = OwnerDoc();
 
     *aDefer = false;
     if ((win = document->GetInnerWindow())) {
       nsCOMPtr<EventTarget> piTarget(do_QueryInterface(win));
 
-      return piTarget->GetListenerManager(true);
+      return piTarget->GetOrCreateListenerManager();
     }
 
     return nullptr;
   }
 
   return nsGenericHTMLElementBase::GetEventListenerManagerForAttr(aAttrName,
                                                                   aDefer);
 }
@@ -1004,18 +1004,17 @@ nsGenericHTMLElement::UnsetAttr(int32_t 
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aAttribute == nsGkAtoms::accesskey) {
       // Have to unregister before clearing flag. See UnregAccessKey
       UnregAccessKey();
       UnsetFlags(NODE_HAS_ACCESSKEY);
     }
     else if (IsEventAttributeName(aAttribute)) {
-      nsEventListenerManager* manager = GetListenerManager(false);
-      if (manager) {
+      if (nsEventListenerManager* manager = GetExistingListenerManager()) {
         manager->RemoveEventHandler(aAttribute, EmptyString());
       }
     }
   }
 
   nsresult rv = nsGenericHTMLElementBase::UnsetAttr(aNameSpaceID, aAttribute,
                                                     aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -1557,18 +1557,17 @@ nsTextEditorState::UnbindFromFrame(nsTex
     mSelCon = nullptr;
   }
 
   if (mTextListener)
   {
     mTextListener->SetFrame(nullptr);
 
     nsCOMPtr<EventTarget> target = do_QueryInterface(mTextCtrlElement);
-    nsEventListenerManager* manager =
-      target->GetListenerManager(false);
+    nsEventListenerManager* manager = target->GetExistingListenerManager();
     if (manager) {
       manager->RemoveEventListenerByType(mTextListener,
         NS_LITERAL_STRING("keydown"),
         dom::TrustedEventsAtSystemGroupBubble());
       manager->RemoveEventListenerByType(mTextListener,
         NS_LITERAL_STRING("keypress"),
         dom::TrustedEventsAtSystemGroupBubble());
       manager->RemoveEventListenerByType(mTextListener,
@@ -1965,17 +1964,17 @@ nsTextEditorState::SetValue(const nsAStr
   mTextCtrlElement->OnValueChanged(!!mRootNode);
 }
 
 void
 nsTextEditorState::InitializeKeyboardEventListeners()
 {
   //register key listeners
   nsCOMPtr<EventTarget> target = do_QueryInterface(mTextCtrlElement);
-  nsEventListenerManager* manager = target->GetListenerManager(true);
+  nsEventListenerManager* manager = target->GetOrCreateListenerManager();
   if (manager) {
     manager->AddEventListenerByType(mTextListener,
                                     NS_LITERAL_STRING("keydown"),
                                     dom::TrustedEventsAtSystemGroupBubble());
     manager->AddEventListenerByType(mTextListener,
                                     NS_LITERAL_STRING("keypress"),
                                     dom::TrustedEventsAtSystemGroupBubble());
     manager->AddEventListenerByType(mTextListener,
--- a/content/smil/nsSMILTimeValueSpec.cpp
+++ b/content/smil/nsSMILTimeValueSpec.cpp
@@ -367,17 +367,17 @@ nsSMILTimeValueSpec::GetEventListenerMan
       return nullptr;
     target = do_QueryInterface(win);
   } else {
     target = aTarget;
   }
   if (!target)
     return nullptr;
 
-  return target->GetListenerManager(true);
+  return target->GetOrCreateListenerManager();
 }
 
 void
 nsSMILTimeValueSpec::HandleEvent(nsIDOMEvent* aEvent)
 {
   NS_ABORT_IF_FALSE(mEventListener, "Got event without an event listener");
   NS_ABORT_IF_FALSE(IsEventBased(),
                     "Got event for non-event nsSMILTimeValueSpec");
--- a/content/svg/content/src/SVGEllipseElement.cpp
+++ b/content/svg/content/src/SVGEllipseElement.cpp
@@ -91,18 +91,14 @@ SVGEllipseElement::GetLengthInfo()
 void
 SVGEllipseElement::ConstructPath(gfxContext *aCtx)
 {
   float x, y, rx, ry;
 
   GetAnimatedLengthValues(&x, &y, &rx, &ry, nullptr);
 
   if (rx > 0.0f && ry > 0.0f) {
-    aCtx->Save();
-    aCtx->Translate(gfxPoint(x, y));
-    aCtx->Scale(rx, ry);
-    aCtx->Arc(gfxPoint(0, 0), 1, 0, 2 * M_PI);
-    aCtx->Restore();
+    aCtx->Ellipse(gfxPoint(x, y), gfxSize(2.0*rx, 2.0*ry));
   }
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/svg/content/src/SVGPreserveAspectRatio.h
+++ b/content/svg/content/src/SVGPreserveAspectRatio.h
@@ -1,15 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#pragma once
+#ifndef MOZILLA_CONTENT_SVGPRESERVEASPECTRATIO_H_
+#define MOZILLA_CONTENT_SVGPRESERVEASPECTRATIO_H_
 
+#include "mozilla/HashFunctions.h"  // for HashGeneric
 #include "mozilla/TypedEnum.h"
 
 #include "nsWrapperCache.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "mozilla/ErrorResult.h"
 #include "nsSVGElement.h"
 
@@ -93,16 +95,20 @@ public:
   void SetDefer(bool aDefer) {
     mDefer = aDefer;
   }
 
   bool GetDefer() const {
     return mDefer;
   }
 
+  uint32_t Hash() const {
+    return HashGeneric(mAlign, mMeetOrSlice, mDefer);
+  }
+
 private:
   // We can't use enum types here because some compilers fail to pack them.
   uint8_t mAlign;
   uint8_t mMeetOrSlice;
   bool mDefer;
 };
 
 namespace dom {
@@ -136,8 +142,10 @@ public:
 protected:
   SVGAnimatedPreserveAspectRatio* mVal; // kept alive because it belongs to mSVGElement
   nsRefPtr<nsSVGElement> mSVGElement;
   const bool mIsBaseValue;
 };
 
 } //namespace dom
 } //namespace mozilla
+
+#endif // MOZILLA_CONTENT_SVGPRESERVEASPECTRATIO_H_
--- a/content/svg/content/src/moz.build
+++ b/content/svg/content/src/moz.build
@@ -3,16 +3,17 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MODULE = 'content'
 
 EXPORTS += [
     'SVGAttrValueWrapper.h',
+    'SVGPreserveAspectRatio.h',
     'SVGStringList.h',
     'nsSVGClass.h',
     'nsSVGElement.h',
     'nsSVGFeatures.h',
 ]
 
 EXPORTS.mozilla.dom += [
     'SVGAElement.h',
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -659,17 +659,17 @@ nsSVGElement::UnsetAttrInternal(int32_t 
   // Maybe consolidate?
 
   if (aNamespaceID == kNameSpaceID_None) {
     // If this is an svg presentation attribute, remove rule to force an update
     if (IsAttributeMapped(aName))
       mContentStyleRule = nullptr;
 
     if (IsEventAttributeName(aName)) {
-      nsEventListenerManager* manager = GetListenerManager(false);
+      nsEventListenerManager* manager = GetExistingListenerManager();
       if (manager) {
         nsIAtom* eventName = GetEventNameForAttr(aName);
         manager->RemoveEventHandler(eventName, EmptyString());
       }
       return;
     }
     
     // Check if this is a length attribute going away
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -493,18 +493,17 @@ void
 nsXBLBinding::InstallEventHandlers()
 {
   // Don't install handlers if scripts aren't allowed.
   if (AllowScripts()) {
     // Fetch the handlers prototypes for this binding.
     nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
 
     if (handlerChain) {
-      nsEventListenerManager* manager =
-        mBoundElement->GetListenerManager(true);
+      nsEventListenerManager* manager = mBoundElement->GetOrCreateListenerManager();
       if (!manager)
         return;
 
       bool isChromeDoc =
         nsContentUtils::IsChromeDoc(mBoundElement->OwnerDoc());
       bool isChromeBinding = mPrototypeBinding->IsChrome();
       nsXBLPrototypeHandler* curr;
       for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
@@ -643,17 +642,17 @@ nsXBLBinding::ExecuteDetachedHandler()
 
 void
 nsXBLBinding::UnhookEventHandlers()
 {
   nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
 
   if (handlerChain) {
     nsEventListenerManager* manager =
-      mBoundElement->GetListenerManager(false);
+      mBoundElement->GetExistingListenerManager();
     if (!manager) {
       return;
     }
                                       
     bool isChromeBinding = mPrototypeBinding->IsChrome();
     nsXBLPrototypeHandler* curr;
     for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
       nsXBLEventHandler* handler = curr->GetCachedEventHandler();
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -556,17 +556,17 @@ nsXBLService::AttachGlobalKeyHandler(Eve
   nsCOMPtr<nsIContent> contentNode(do_QueryInterface(aTarget));
   if (contentNode) {
     // Only attach if we're really in a document
     nsCOMPtr<nsIDocument> doc = contentNode->GetCurrentDoc();
     if (doc)
       piTarget = doc; // We're a XUL keyset. Attach to our document.
   }
 
-  nsEventListenerManager* manager = piTarget->GetListenerManager(true);
+  nsEventListenerManager* manager = piTarget->GetOrCreateListenerManager();
 
   if (!piTarget || !manager)
     return NS_ERROR_FAILURE;
 
   // the listener already exists, so skip this
   if (contentNode && contentNode->GetProperty(nsGkAtoms::listener))
     return NS_OK;
 
@@ -606,17 +606,17 @@ nsXBLService::DetachGlobalKeyHandler(Eve
   if (!contentNode) // detaching is only supported for content nodes
     return NS_ERROR_FAILURE;
 
   // Only attach if we're really in a document
   nsCOMPtr<nsIDocument> doc = contentNode->GetCurrentDoc();
   if (doc)
     piTarget = do_QueryInterface(doc);
 
-  nsEventListenerManager* manager = piTarget->GetListenerManager(true);
+  nsEventListenerManager* manager = piTarget->GetOrCreateListenerManager();
 
   if (!piTarget || !manager)
     return NS_ERROR_FAILURE;
 
   nsIDOMEventListener* handler =
     static_cast<nsIDOMEventListener*>(contentNode->GetProperty(nsGkAtoms::listener));
   if (!handler)
     return NS_ERROR_FAILURE;
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -491,17 +491,17 @@ nsXULElement::GetEventListenerManagerFor
     nsPIDOMWindow *window;
     Element *root = doc->GetRootElement();
     if ((!root || root == this) && !mNodeInfo->Equals(nsGkAtoms::overlay) &&
         (window = doc->GetInnerWindow())) {
 
         nsCOMPtr<EventTarget> piTarget = do_QueryInterface(window);
 
         *aDefer = false;
-        return piTarget->GetListenerManager(true);
+        return piTarget->GetOrCreateListenerManager();
     }
 
     return nsStyledElement::GetEventListenerManagerForAttr(aAttrName, aDefer);
 }
 
 // returns true if the element is not a list
 static bool IsNonList(nsINodeInfo* aNodeInfo)
 {
@@ -1665,17 +1665,17 @@ nsXULElement::AddPopupListener(nsIAtom* 
     if (HasFlag(listenerFlag)) {
         return NS_OK;
     }
 
     nsCOMPtr<nsIDOMEventListener> listener =
       new nsXULPopupListener(this, isContext);
 
     // Add the popup as a listener on this element.
-    nsEventListenerManager* manager = GetListenerManager(true);
+    nsEventListenerManager* manager = GetOrCreateListenerManager();
     SetFlags(listenerFlag);
 
     if (isContext) {
       manager->AddEventListenerByType(listener,
                                       NS_LITERAL_STRING("contextmenu"),
                                       dom::TrustedEventsAtSystemGroupBubble());
     } else {
       manager->AddEventListenerByType(listener,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -200,16 +200,17 @@
 #include "mozilla/dom/StructuredCloneTags.h"
 
 #ifdef MOZ_GAMEPAD
 #include "mozilla/dom/GamepadService.h"
 #endif
 
 #include "nsRefreshDriver.h"
 
+#include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
 #include "nsLocation.h"
 #include "nsHTMLDocument.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsDOMEventTargetHelper.h"
 #include "prrng.h"
 #include "nsSandboxFlags.h"
 #include "TimeChangeObserver.h"
@@ -1565,18 +1566,17 @@ MarkXBLHandlers(nsXBLPrototypeHandler* a
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
   if (tmp->IsBlackForCC()) {
     if (tmp->mCachedXBLPrototypeHandlers) {
       tmp->mCachedXBLPrototypeHandlers->Enumerate(MarkXBLHandlers, nullptr);
     }
-    nsEventListenerManager* elm = tmp->GetListenerManager(false);
-    if (elm) {
+    if (nsEventListenerManager* elm = tmp->GetExistingListenerManager()) {
       elm->MarkForCC();
     }
     tmp->UnmarkGrayTimers();
     return true;
   }
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
 
 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindow)
@@ -8063,18 +8063,17 @@ nsGlobalWindow::Btoa(const nsAString& aB
 // nsGlobalWindow::nsIDOMEventTarget
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsGlobalWindow::RemoveEventListener(const nsAString& aType,
                                     nsIDOMEventListener* aListener,
                                     bool aUseCapture)
 {
-  nsRefPtr<nsEventListenerManager> elm = GetListenerManager(false);
-  if (elm) {
+  if (nsRefPtr<nsEventListenerManager> elm = GetExistingListenerManager()) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
   return NS_OK;
 }
 
 NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsGlobalWindow)
 
 NS_IMETHODIMP
@@ -8119,17 +8118,17 @@ nsGlobalWindow::AddEventListener(const n
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   if (!aWantsUntrusted &&
       (aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
     aWantsUntrusted = true;
   }
 
-  nsEventListenerManager* manager = GetListenerManager(true);
+  nsEventListenerManager* manager = GetOrCreateListenerManager();
   NS_ENSURE_STATE(manager);
   manager->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
   return NS_OK;
 }
 
 void
 nsGlobalWindow::AddEventListener(const nsAString& aType,
                                  EventListener* aListener,
@@ -8145,17 +8144,17 @@ nsGlobalWindow::AddEventListener(const n
 
   bool wantsUntrusted;
   if (aWantsUntrusted.IsNull()) {
     wantsUntrusted = !nsContentUtils::IsChromeDoc(mDoc);
   } else {
     wantsUntrusted = aWantsUntrusted.Value();
   }
 
-  nsEventListenerManager* manager = GetListenerManager(true);
+  nsEventListenerManager* manager = GetOrCreateListenerManager();
   if (!manager) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
   manager->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
 }
 
 NS_IMETHODIMP
@@ -8180,28 +8179,36 @@ nsGlobalWindow::AddSystemEventListener(c
     aWantsUntrusted = true;
   }
 
   return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
                                    aWantsUntrusted);
 }
 
 nsEventListenerManager*
-nsGlobalWindow::GetListenerManager(bool aCreateIfNotFound)
-{
-  FORWARD_TO_INNER_CREATE(GetListenerManager, (aCreateIfNotFound), nullptr);
-
-  if (!mListenerManager && aCreateIfNotFound) {
+nsGlobalWindow::GetOrCreateListenerManager()
+{
+  FORWARD_TO_INNER_CREATE(GetOrCreateListenerManager, (), nullptr);
+
+  if (!mListenerManager) {
     mListenerManager =
       new nsEventListenerManager(static_cast<EventTarget*>(this));
   }
 
   return mListenerManager;
 }
 
+nsEventListenerManager*
+nsGlobalWindow::GetExistingListenerManager() const
+{
+  FORWARD_TO_INNER(GetExistingListenerManager, (), nullptr);
+
+  return mListenerManager;
+}
+
 nsIScriptContext*
 nsGlobalWindow::GetContextForEventHandlers(nsresult* aRv)
 {
   *aRv = NS_ERROR_UNEXPECTED;
   if (IsInnerWindow()) {
     nsPIDOMWindow* outer = GetOuterWindow();
     NS_ENSURE_TRUE(outer && outer->GetCurrentInnerWindow() == this, nullptr);
   }
@@ -8389,17 +8396,17 @@ void nsGlobalWindow::MaybeUpdateTouchSta
   fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
 
   if(this == focusedWindow) {
     UpdateTouchState();
   }
 
   if (mMayHaveTouchEventListener) {
     nsCOMPtr<nsIObserverService> observerService =
-      do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+      services::GetObserverService();
 
     if (observerService) {
       observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
                                        DOM_TOUCH_LISTENER_ADDED,
                                        nullptr);
     }
   }
 }
@@ -11539,18 +11546,17 @@ SizeOfEventTargetObjectsEntryExcludingTh
 }
 
 void
 nsGlobalWindow::AddSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
 {
   aWindowSizes->mDOMOther += aWindowSizes->mMallocSizeOf(this);
 
   if (IsInnerWindow()) {
-    nsEventListenerManager* elm =
-      const_cast<nsGlobalWindow*>(this)->GetListenerManager(false);
+    nsEventListenerManager* elm = GetExistingListenerManager();
     if (elm) {
       aWindowSizes->mDOMOther +=
         elm->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
     }
     if (mDoc) {
       mDoc->DocAddSizeOfIncludingThis(aWindowSizes);
     }
   }
@@ -12079,61 +12085,61 @@ nsGlobalWindow::DisableNetworkEvent(uint
       handler = new EventHandlerNonNull(callable);                           \
     }                                                                        \
     SetOn##name_(handler);                                                   \
     return NS_OK;                                                            \
   }
 #define ERROR_EVENT(name_, id_, type_, struct_)                              \
   NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx,                  \
                                              JS::Value *vp) {                \
-    nsEventListenerManager *elm = GetListenerManager(false);                 \
+    nsEventListenerManager *elm = GetExistingListenerManager();              \
     if (elm) {                                                               \
       OnErrorEventHandlerNonNull* h = elm->GetOnErrorEventHandler();         \
       if (h) {                                                               \
         *vp = JS::ObjectValue(*h->Callable());                               \
         return NS_OK;                                                        \
       }                                                                      \
     }                                                                        \
     *vp = JSVAL_NULL;                                                        \
     return NS_OK;                                                            \
   }                                                                          \
   NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx,                  \
                                              const JS::Value &v) {           \
-    nsEventListenerManager *elm = GetListenerManager(true);                  \
+    nsEventListenerManager *elm = GetOrCreateListenerManager();              \
     if (!elm) {                                                              \
       return NS_ERROR_OUT_OF_MEMORY;                                         \
     }                                                                        \
                                                                              \
     nsRefPtr<OnErrorEventHandlerNonNull> handler;                            \
     JSObject *callable;                                                      \
     if (v.isObject() &&                                                      \
         JS_ObjectIsCallable(cx, callable = &v.toObject())) {                 \
       handler = new OnErrorEventHandlerNonNull(callable);                    \
     }                                                                        \
     elm->SetEventHandler(handler);                                           \
     return NS_OK;                                                            \
   }
 #define BEFOREUNLOAD_EVENT(name_, id_, type_, struct_)                       \
   NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx,                  \
                                              JS::Value *vp) {                \
-    nsEventListenerManager *elm = GetListenerManager(false);                 \
+    nsEventListenerManager *elm = GetExistingListenerManager();              \
     if (elm) {                                                               \
       BeforeUnloadEventHandlerNonNull* h =                                   \
         elm->GetOnBeforeUnloadEventHandler();                                \
       if (h) {                                                               \
         *vp = JS::ObjectValue(*h->Callable());                               \
         return NS_OK;                                                        \
       }                                                                      \
     }                                                                        \
     *vp = JSVAL_NULL;                                                        \
     return NS_OK;                                                            \
   }                                                                          \
   NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx,                  \
                                              const JS::Value &v) {           \
-    nsEventListenerManager *elm = GetListenerManager(true);                  \
+    nsEventListenerManager *elm = GetOrCreateListenerManager();              \
     if (!elm) {                                                              \
       return NS_ERROR_OUT_OF_MEMORY;                                         \
     }                                                                        \
                                                                              \
     nsRefPtr<BeforeUnloadEventHandlerNonNull> handler;                       \
     JSObject *callable;                                                      \
     if (v.isObject() &&                                                      \
         JS_ObjectIsCallable(cx, callable = &v.toObject())) {                 \
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -366,16 +366,23 @@ public:
   // nsIDOMWindowPerformance
   NS_DECL_NSIDOMWINDOWPERFORMANCE
 
   // nsIDOMJSWindow
   NS_DECL_NSIDOMJSWINDOW
 
   // nsIDOMEventTarget
   NS_DECL_NSIDOMEVENTTARGET
+
+  virtual nsEventListenerManager*
+  GetExistingListenerManager() const MOZ_OVERRIDE;
+
+  virtual nsEventListenerManager*
+  GetOrCreateListenerManager() MOZ_OVERRIDE;
+
   using mozilla::dom::EventTarget::RemoveEventListener;
   virtual void AddEventListener(const nsAString& aType,
                                 mozilla::dom::EventListener* aListener,
                                 bool aUseCapture,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
   virtual nsIDOMWindow* GetOwnerGlobal() MOZ_OVERRIDE
   {
@@ -547,17 +554,17 @@ public:
     return mContext;
   }
 
   nsGlobalWindow *GetOuterWindowInternal()
   {
     return static_cast<nsGlobalWindow *>(GetOuterWindow());
   }
 
-  nsGlobalWindow *GetCurrentInnerWindowInternal()
+  nsGlobalWindow *GetCurrentInnerWindowInternal() const
   {
     return static_cast<nsGlobalWindow *>(mInnerWindow);
   }
 
   nsGlobalWindow *EnsureInnerWindowInternal()
   {
     return static_cast<nsGlobalWindow *>(EnsureInnerWindow());
   }
@@ -703,49 +710,49 @@ public:
   // Enable/disable updates for gamepad input.
   void EnableGamepadUpdates();
   void DisableGamepadUpdates();
 
 
 #define EVENT(name_, id_, type_, struct_)                                     \
   mozilla::dom::EventHandlerNonNull* GetOn##name_()                           \
   {                                                                           \
-    nsEventListenerManager *elm = GetListenerManager(false);                  \
+    nsEventListenerManager *elm = GetExistingListenerManager();               \
     return elm ? elm->GetEventHandler(nsGkAtoms::on##name_, EmptyString())    \
                : nullptr;                                                     \
   }                                                                           \
   void SetOn##name_(mozilla::dom::EventHandlerNonNull* handler)               \
   {                                                                           \
-    nsEventListenerManager *elm = GetListenerManager(true);                   \
+    nsEventListenerManager *elm = GetOrCreateListenerManager();               \
     if (elm) {                                                                \
       elm->SetEventHandler(nsGkAtoms::on##name_, EmptyString(), handler);     \
     }                                                                         \
   }
 #define ERROR_EVENT(name_, id_, type_, struct_)                               \
   mozilla::dom::OnErrorEventHandlerNonNull* GetOn##name_()                    \
   {                                                                           \
-    nsEventListenerManager *elm = GetListenerManager(false);                  \
+    nsEventListenerManager *elm = GetExistingListenerManager();               \
     return elm ? elm->GetOnErrorEventHandler() : nullptr;                     \
   }                                                                           \
   void SetOn##name_(mozilla::dom::OnErrorEventHandlerNonNull* handler)        \
   {                                                                           \
-    nsEventListenerManager *elm = GetListenerManager(true);                   \
+    nsEventListenerManager *elm = GetOrCreateListenerManager();               \
     if (elm) {                                                                \
       elm->SetEventHandler(handler);                                          \
     }                                                                         \
   }
 #define BEFOREUNLOAD_EVENT(name_, id_, type_, struct_)                        \
   mozilla::dom::BeforeUnloadEventHandlerNonNull* GetOn##name_()               \
   {                                                                           \
-    nsEventListenerManager *elm = GetListenerManager(false);                  \
+    nsEventListenerManager *elm = GetExistingListenerManager();               \
     return elm ? elm->GetOnBeforeUnloadEventHandler() : nullptr;              \
   }                                                                           \
   void SetOn##name_(mozilla::dom::BeforeUnloadEventHandlerNonNull* handler)   \
   {                                                                           \
-    nsEventListenerManager *elm = GetListenerManager(true);                   \
+    nsEventListenerManager *elm = GetOrCreateListenerManager();               \
     if (elm) {                                                                \
       elm->SetEventHandler(handler);                                          \
     }                                                                         \
   }
 #define WINDOW_ONLY_EVENT EVENT
 #define TOUCH_EVENT EVENT
 #include "nsEventNameList.h"
 #undef TOUCH_EVENT
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -59,18 +59,17 @@ NS_INTERFACE_MAP_END
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsWindowRoot)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsWindowRoot)
 
 NS_IMPL_DOMTARGET_DEFAULTS(nsWindowRoot)
 
 NS_IMETHODIMP
 nsWindowRoot::RemoveEventListener(const nsAString& aType, nsIDOMEventListener* aListener, bool aUseCapture)
 {
-  nsRefPtr<nsEventListenerManager> elm = GetListenerManager(false);
-  if (elm) {
+  if (nsRefPtr<nsEventListenerManager> elm = GetExistingListenerManager()) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
   }
   return NS_OK;
 }
 
 NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsWindowRoot)
 
 NS_IMETHODIMP
@@ -100,31 +99,31 @@ nsWindowRoot::AddEventListener(const nsA
                                bool aUseCapture, bool aWantsUntrusted,
                                uint8_t aOptionalArgc)
 {
   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
                "Won't check if this is chrome, you want to set "
                "aWantsUntrusted to false or make the aWantsUntrusted "
                "explicit by making optional_argc non-zero.");
 
-  nsEventListenerManager* elm = GetListenerManager(true);
+  nsEventListenerManager* elm = GetOrCreateListenerManager();
   NS_ENSURE_STATE(elm);
   elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
   return NS_OK;
 }
 
 void
 nsWindowRoot::AddEventListener(const nsAString& aType,
                                 EventListener* aListener,
                                 bool aUseCapture,
                                 const Nullable<bool>& aWantsUntrusted,
                                 ErrorResult& aRv)
 {
   bool wantsUntrusted = !aWantsUntrusted.IsNull() && aWantsUntrusted.Value();
-  nsEventListenerManager* elm = GetListenerManager(true);
+  nsEventListenerManager* elm = GetOrCreateListenerManager();
   if (!elm) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
   elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
 }
 
 
@@ -140,26 +139,32 @@ nsWindowRoot::AddSystemEventListener(con
                "aWantsUntrusted to false or make the aWantsUntrusted "
                "explicit by making optional_argc non-zero.");
 
   return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
                                    aWantsUntrusted);
 }
 
 nsEventListenerManager*
-nsWindowRoot::GetListenerManager(bool aCreateIfNotFound)
+nsWindowRoot::GetOrCreateListenerManager()
 {
-  if (!mListenerManager && aCreateIfNotFound) {
+  if (!mListenerManager) {
     mListenerManager =
       new nsEventListenerManager(static_cast<EventTarget*>(this));
   }
 
   return mListenerManager;
 }
 
+nsEventListenerManager*
+nsWindowRoot::GetExistingListenerManager() const
+{
+  return mListenerManager;
+}
+
 nsIScriptContext*
 nsWindowRoot::GetContextForEventHandlers(nsresult* aRv)
 {
   *aRv = NS_OK;
   return nullptr;
 }
 
 nsresult
--- a/dom/base/nsWindowRoot.h
+++ b/dom/base/nsWindowRoot.h
@@ -23,16 +23,22 @@ class nsEventChainPostVisitor;
 class nsWindowRoot : public nsPIWindowRoot
 {
 public:
   nsWindowRoot(nsPIDOMWindow* aWindow);
   virtual ~nsWindowRoot();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMEVENTTARGET
+
+  virtual nsEventListenerManager*
+  GetExistingListenerManager() const MOZ_OVERRIDE;
+  virtual nsEventListenerManager*
+  GetOrCreateListenerManager() MOZ_OVERRIDE;
+
   using mozilla::dom::EventTarget::RemoveEventListener;
   virtual void AddEventListener(const nsAString& aType,
                                 mozilla::dom::EventListener* aListener,
                                 bool aUseCapture,
                                 const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                                 mozilla::ErrorResult& aRv) MOZ_OVERRIDE;
 
   // nsPIWindowRoot
--- a/dom/devicestorage/DeviceStorage.h
+++ b/dom/devicestorage/DeviceStorage.h
@@ -152,16 +152,21 @@ public:
   typedef nsTArray<nsString> VolumeNameArray;
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIDOMDEVICESTORAGE
 
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIDOMEVENTTARGET
 
+  virtual nsEventListenerManager*
+  GetExistingListenerManager() const MOZ_OVERRIDE;
+  virtual nsEventListenerManager*
+  GetOrCreateListenerManager() MOZ_OVERRIDE;
+
   virtual void
   AddEventListener(const nsAString& aType,
                    mozilla::dom::EventListener* aListener,
                    bool aUseCapture,
                    const mozilla::dom::Nullable<bool>& aWantsUntrusted,
                    ErrorResult& aRv) MOZ_OVERRIDE;
 
   virtual void RemoveEventListener(const nsAString& aType,
--- a/dom/devicestorage/nsDeviceStorage.cpp
+++ b/dom/devicestorage/nsDeviceStorage.cpp
@@ -3471,19 +3471,25 @@ nsDOMDeviceStorage::DispatchDOMEvent(Wid
 {
   return nsDOMEventTargetHelper::DispatchDOMEvent(aEvent,
                                                   aDOMEvent,
                                                   aPresContext,
                                                   aEventStatus);
 }
 
 nsEventListenerManager *
-nsDOMDeviceStorage::GetListenerManager(bool aMayCreate)
+nsDOMDeviceStorage::GetOrCreateListenerManager()
 {
-  return nsDOMEventTargetHelper::GetListenerManager(aMayCreate);
+  return nsDOMEventTargetHelper::GetOrCreateListenerManager();
+}
+
+nsEventListenerManager *
+nsDOMDeviceStorage::GetExistingListenerManager() const
+{
+  return nsDOMEventTargetHelper::GetExistingListenerManager();
 }
 
 nsIScriptContext *
 nsDOMDeviceStorage::GetContextForEventHandlers(nsresult *aRv)
 {
   return nsDOMEventTargetHelper::GetContextForEventHandlers(aRv);
 }
 
--- a/dom/interfaces/events/nsIDOMEventTarget.idl
+++ b/dom/interfaces/events/nsIDOMEventTarget.idl
@@ -40,17 +40,17 @@ class nsEventListenerManager;
 [ptr] native JSContextPtr(JSContext);
 [ptr] native nsEventListenerManagerPtr(nsEventListenerManager);
 [ptr] native EventTargetPtr(mozilla::dom::EventTarget);
 
 interface nsIScriptContext;
 interface nsIDOMEventListener;
 interface nsIDOMEvent;
 
-[scriptable, builtinclass, uuid(31e92e56-4d23-4a4a-9cfe-a6d12cf434bc)]
+[scriptable, builtinclass, uuid(b128448c-7b53-4769-92cb-cd6eafee676c)]
 interface nsIDOMEventTarget : nsISupports
 {
   /**
    * This method allows the registration of event listeners on the event target.
    * If an EventListener is added to an EventTarget while it is processing an
    * event, it will not be triggered by the current actions but may be 
    * triggered during a later stage of event flow, such as the bubbling phase.
    * 
@@ -263,25 +263,16 @@ interface nsIDOMEventTarget : nsISupport
    */
   [noscript, nostdcall]
   void DispatchDOMEvent(in WidgetEventPtr aEvent,
                         in nsIDOMEvent aDOMEvent,
                         in nsPresContextPtr aPresContext,
                         in nsEventStatusPtr aEventStatus);
 
   /**
-   * Get the event listener manager, the guy you talk to to register for events
-   * on this node.
-   * @param aMayCreate If PR_FALSE, returns a listener manager only if
-   *                   one already exists.
-   */
-  [notxpcom, nostdcall]
-  nsEventListenerManagerPtr GetListenerManager(in boolean aMayCreate);
-
-  /**
    * Get the script context in which the event handlers should be run.
    * May return null.
    * @note Caller *must* check the value of aRv.
    */
   [notxpcom, nostdcall]
   nsIScriptContext GetContextForEventHandlers(out nsresult aRv);
 
   /**
@@ -300,17 +291,17 @@ nsresult _class::WillHandleEvent(nsEvent
 JSContext* _class::GetJSContextForEventHandlers() { return nullptr; }
 
 #define NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(aClass) \
 NS_IMETHODIMP \
 aClass::RemoveSystemEventListener(const nsAString& aType, \
                                   nsIDOMEventListener *aListener, \
                                   bool aUseCapture) \
 { \
-  nsEventListenerManager* listenerManager = GetListenerManager(false); \
+  nsEventListenerManager* listenerManager = GetExistingListenerManager(); \
   if (!listenerManager) { \
     return NS_OK; \
   } \
   mozilla::dom::EventListenerFlags flags; \
   flags.mInSystemGroup = true; \
   flags.mCapture = aUseCapture; \
   listenerManager->RemoveEventListenerByType(aListener, aType, flags); \
   return NS_OK; \
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -19,16 +19,17 @@
 #include "mozilla/ipc/DocumentRendererChild.h"
 #include "mozilla/ipc/FileDescriptorUtils.h"
 #include "mozilla/layers/AsyncPanZoomController.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "mozilla/layout/RenderFrameChild.h"
 #include "mozilla/MouseEvents.h"
+#include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "mozilla/unused.h"
 #include "mozIApplication.h"
 #include "nsContentUtils.h"
 #include "nsCxPusher.h"
 #include "nsEmbedCID.h"
@@ -1197,17 +1198,17 @@ TabChild::~TabChild()
 
     nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(mWebNav);
     if (webBrowser) {
       webBrowser->SetContainerWindow(nullptr);
     }
     mGlobal = nullptr;
 
     if (mTabChildGlobal) {
-      nsEventListenerManager* elm = mTabChildGlobal->GetListenerManager(false);
+      nsEventListenerManager* elm = mTabChildGlobal->GetExistingListenerManager();
       if (elm) {
         elm->Disconnect();
       }
       mTabChildGlobal->mTabChild = nullptr;
     }
 }
 
 void
@@ -2098,17 +2099,17 @@ TabChild::RecvDestroy()
   if (mTabChildGlobal) {
     // Let the frame scripts know the child is being closed
     nsContentUtils::AddScriptRunner(
       new UnloadScriptEvent(this, mTabChildGlobal)
     );
   }
 
   nsCOMPtr<nsIObserverService> observerService =
-    do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+    mozilla::services::GetObserverService();
 
   observerService->RemoveObserver(this, CANCEL_DEFAULT_PAN_ZOOM);
   observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
   observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
   observerService->RemoveObserver(this, DETECT_SCROLLABLE_SUBFRAME);
 
   const InfallibleTArray<PIndexedDBChild*>& idbActors =
     ManagedPIndexedDBChild();
@@ -2235,17 +2236,17 @@ TabChild::InitRenderingState()
     NS_ABORT_IF_FALSE(lf && lf->HasShadowManager(),
                       "PuppetWidget should have shadow manager");
     lf->IdentifyTextureHost(mTextureFactoryIdentifier);
     ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
 
     mRemoteFrame = remoteFrame;
 
     nsCOMPtr<nsIObserverService> observerService =
-        do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+        mozilla::services::GetObserverService();
 
     if (observerService) {
         observerService->AddObserver(this,
                                      CANCEL_DEFAULT_PAN_ZOOM,
                                      false);
         observerService->AddObserver(this,
                                      BROWSER_ZOOM_TO_RECT,
                                      false);
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ b/dom/system/gonk/SystemWorkerManager.cpp
@@ -33,16 +33,17 @@
 #include "mozilla/ipc/Ril.h"
 #include "mozilla/ipc/KeyStore.h"
 #include "nsIObserverService.h"
 #include "nsCxPusher.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsRadioInterfaceLayer.h"
 #include "WifiWorker.h"
+#include "mozilla/Services.h"
 
 USING_WORKERS_NAMESPACE
 
 using namespace mozilla::dom::gonk;
 using namespace mozilla::ipc;
 #ifdef MOZ_WIDGET_GONK
 using namespace mozilla::system;
 #endif
@@ -348,18 +349,17 @@ SystemWorkerManager::Init()
   InitAutoMounter();
   InitializeTimeZoneSettingObserver();
   rv = InitNetd(cx);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIAudioManager> audioManager =
     do_GetService(NS_AUDIOMANAGER_CONTRACTID);
 #endif
 
-  nsCOMPtr<nsIObserverService> obs =
-    do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs) {
     NS_WARNING("Failed to get observer service!");
     return NS_ERROR_FAILURE;
   }
 
   rv = obs->AddObserver(this, WORKERS_SHUTDOWN_TOPIC, false);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to initialize worker shutdown event!");
@@ -394,18 +394,17 @@ SystemWorkerManager::Shutdown()
 
   nsCOMPtr<nsIWifi> wifi(do_QueryInterface(mWifiWorker));
   if (wifi) {
     wifi->Shutdown();
     wifi = nullptr;
   }
   mWifiWorker = nullptr;
 
-  nsCOMPtr<nsIObserverService> obs =
-    do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->RemoveObserver(this, WORKERS_SHUTDOWN_TOPIC);
   }
 }
 
 // static
 already_AddRefed<SystemWorkerManager>
 SystemWorkerManager::FactoryCreate()
--- a/dom/workers/test/test_transferable.html
+++ b/dom/workers/test/test_transferable.html
@@ -17,30 +17,35 @@ Tests of DOM Worker transferable objects
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" language="javascript">
 
   function test1(sizes) {
     if (!sizes.length) {
-      SimpleTest.finish();
+      runTests();
       return;
     }
 
     var size = sizes.pop();
 
     var worker = new Worker("transferable_worker.js");
     worker.onmessage = function(event) {
       ok(event.data.status, event.data.event);
       if (!event.data.status) {
-        SimpleTest.finish();
+        runTests();
         return;
       }
 
+      if ("notEmpty" in event.data && "byteLength" in event.data.notEmpty) {
+        ok(event.data.notEmpty.byteLength != 0,
+           "P: NotEmpty object received: " + event.data.notEmpty.byteLength);
+      }
+
       if (!event.data.last)
         return;
 
       test1(sizes);
     }
     worker.onerror = function(event) {
       ok(false, "No errors!");
     }
@@ -55,21 +60,64 @@ Tests of DOM Worker transferable objects
     try {
       ab = new ArrayBuffer(size);
       worker.postMessage(42,[ab, ab]);
       ok(false, "P: PostMessage - Exception for duplicate");
     } catch(e) {
       ok(true, "P: PostMessage - Exception for duplicate");
     }
 
-    ab = new ArrayBuffer(size);
+    var ab = new ArrayBuffer(size);
     ok(ab.byteLength == size, "P: The size is: " + size + " == " + ab.byteLength);
     worker.postMessage({ data: 0, timeout: 0, ab: ab, cb: ab, size: size }, [ab]);
     ok(ab.byteLength == 0, "P: PostMessage - The size is: 0 == " + ab.byteLength)
   }
 
-  test1([1024 * 1024 * 32, 128, 4]);
+  function test2() {
+    var worker = new Worker("transferable_worker.js");
+    worker.onmessage = function(event) {
+      ok(event.data.status, event.data.event);
+      if (!event.data.status) {
+        runTests();
+        return;
+      }
+
+      if ("notEmpty" in event.data && "byteLength" in event.data.notEmpty) {
+        ok(event.data.notEmpty.byteLength != 0,
+           "P: NotEmpty object received: " + event.data.notEmpty.byteLength);
+      }
+
+      if (event.data.last) {
+        runTests();
+      }
+    }
+    worker.onerror = function(event) {
+      ok(false, "No errors!");
+    }
+
+    var f = new Float32Array([0,1,2,3]);
+    ok(f.byteLength != 0, "P: The size is: " + f.byteLength + " is not 0");
+    worker.postMessage({ event: "P: postMessage with Float32Array", status: true,
+                         size: 4, notEmpty: f, bc: [ f, f, { dd: f } ] }, [f.buffer]);
+    ok(f.byteLength == 0, "P: The size is: " + f.byteLength + " is 0");
+  }
+
+  var tests = [
+    function() { test1([1024 * 1024 * 32, 128, 4]); },
+    test2
+  ];
+  function runTests() {
+    if (!tests.length) {
+      SimpleTest.finish();
+      return;
+    }
+
+    var test = tests.shift();
+    test();
+  }
+
   SimpleTest.waitForExplicitFinish();
+  runTests();
 
 </script>
 </pre>
 </body>
 </html>
--- a/dom/workers/test/transferable_worker.js
+++ b/dom/workers/test/transferable_worker.js
@@ -1,33 +1,23 @@
 /**
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 onmessage = function(event) {
-  if (event.data.data == 0) {
-    ab = new ArrayBuffer(event.data.size);
-    postMessage({ event: "W: The size is: " + event.data.size + " == " + ab.byteLength,
-                  status: ab.byteLength == event.data.size, last: false });
+  if ("notEmpty" in event.data && "byteLength" in event.data.notEmpty) {
+    postMessage({ event: "W: NotEmpty object received: " + event.data.notEmpty.byteLength,
+                  status: event.data.notEmpty.byteLength != 0, last: false });
+  }
 
-    postMessage({ event: "W: postMessage with arrayBuffer", status: true,
-                  ab: ab, bc: [ ab, ab, { dd: ab } ] }, [ab]);
-
-    postMessage({ event: "W: The size is: 0 == " + ab.byteLength,
-                  status: ab.byteLength == 0, last: false });
-
-    postMessage({ event: "last one!", status: true, last: true });
+  var ab = new ArrayBuffer(event.data.size);
+  postMessage({ event: "W: The size is: " + event.data.size + " == " + ab.byteLength,
+                status: ab.byteLength == event.data.size, last: false });
 
-  } else {
-    var worker = new Worker('sync_worker.js');
-    worker.onmessage = function(event) {
-      postMessage(event.data);
-    }
-    worker.onsyncmessage = function(event) {
-      var v = postSyncMessage(event.data, null, 500);
-      event.reply(v);
-    }
+  postMessage({ event: "W: postMessage with arrayBuffer", status: true,
+                notEmpty: ab, ab: ab, bc: [ ab, ab, { dd: ab } ] }, [ab]);
 
-    --event.data.data;
-    worker.postMessage(event.data);
-  }
+  postMessage({ event: "W: The size is: 0 == " + ab.byteLength,
+                status: ab.byteLength == 0, last: false });
+
+  postMessage({ event: "W: last one!", status: true, last: true });
 }
--- a/editor/libeditor/base/nsEditor.h
+++ b/editor/libeditor/base/nsEditor.h
@@ -67,16 +67,17 @@ class nsRange;
 class nsString;
 class nsTransactionManager;
 
 namespace mozilla {
 class Selection;
 
 namespace dom {
 class Element;
+class EventTarget;
 }  // namespace dom
 }  // namespace mozilla
 
 namespace mozilla {
 namespace widget {
 struct IMEState;
 } // namespace widget
 } // namespace mozilla
@@ -655,17 +656,17 @@ public:
                                     nsISelection *aSelection,
                                     nsIDOMNode *previousSelectedNode,
                                     int32_t previousSelectedOffset,
                                     nsIDOMNode *aStartNode,
                                     int32_t aStartOffset,
                                     nsIDOMNode *aEndNode,
                                     int32_t aEndOffset);
 
-  virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget() = 0;
+  virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget() = 0;
 
   // Fast non-refcounting editor root element accessor
   mozilla::dom::Element *GetRoot();
 
   // Likewise, but gets the editor's root instead, which is different for HTML
   // editors
   virtual mozilla::dom::Element* GetEditorRoot();
 
@@ -811,17 +812,17 @@ protected:
   nsCString mContentMIMEType;       // MIME type of the doc we are editing.
 
   nsCOMPtr<nsIInlineSpellChecker> mInlineSpellChecker;
 
   nsRefPtr<nsTransactionManager> mTxnMgr;
   nsCOMPtr<mozilla::dom::Element> mRootElement; // cached root node
   nsCOMPtr<nsIPrivateTextRangeList> mIMETextRangeList; // IME special selection ranges
   nsCOMPtr<nsIDOMCharacterData>     mIMETextNode;      // current IME text node
-  nsCOMPtr<nsIDOMEventTarget> mEventTarget; // The form field as an event receiver
+  nsCOMPtr<mozilla::dom::EventTarget> mEventTarget; // The form field as an event receiver
   nsCOMPtr<nsIDOMEventListener> mEventListener;
   nsWeakPtr        mSelConWeak;          // weak reference to the nsISelectionController
   nsWeakPtr        mPlaceHolderTxn;      // weak reference to placeholder for begin/end batch purposes
   nsWeakPtr        mDocWeak;             // weak reference to the nsIDOMDocument
   nsIAtom          *mPlaceHolderName;    // name of placeholder transaction
   nsSelectionState *mSelState;           // saved selection state for placeholder txn batching
   nsString         *mPhonetic;
 
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=4 sw=2 et tw=78: */
 /* 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 "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/Preferences.h"        // for Preferences
 #include "mozilla/dom/Element.h"        // for Element
+#include "mozilla/dom/EventTarget.h"    // for EventTarget
 #include "nsAString.h"
 #include "nsCaret.h"                    // for nsCaret
 #include "nsDebug.h"                    // for NS_ENSURE_TRUE, etc
 #include "nsEditor.h"                   // for nsEditor, etc
 #include "nsEditorEventListener.h"
 #include "nsEventListenerManager.h"     // for nsEventListenerManager
 #include "nsFocusManager.h"             // for nsFocusManager
 #include "nsGkAtoms.h"                  // for nsGkAtoms, nsGkAtoms::input
@@ -50,16 +51,17 @@
 #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
 #include "nsContentUtils.h"             // for nsContentUtils, etc
 #include "nsIBidiKeyboard.h"            // for nsIBidiKeyboard
 #endif
 
 class nsPresContext;
 
 using namespace mozilla;
+using mozilla::dom::EventTarget;
 
 nsEditorEventListener::nsEditorEventListener() :
   mEditor(nullptr), mCommitText(false),
   mInTransaction(false)
 #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
   , mHaveBidiKeyboards(false)
   , mShouldSwitchTextDirection(false)
   , mSwitchToRTL(false)
@@ -98,21 +100,21 @@ nsEditorEventListener::Connect(nsEditor*
   return rv;
 }
 
 nsresult
 nsEditorEventListener::InstallToEditor()
 {
   NS_PRECONDITION(mEditor, "The caller must set mEditor");
 
-  nsCOMPtr<nsIDOMEventTarget> piTarget = mEditor->GetDOMEventTarget();
+  nsCOMPtr<EventTarget> piTarget = mEditor->GetDOMEventTarget();
   NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
 
   // register the event listeners with the listener manager
-  nsEventListenerManager* elmP = piTarget->GetListenerManager(true);
+  nsEventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
   NS_ENSURE_STATE(elmP);
 
 #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("keydown"),
                                dom::TrustedEventsAtSystemGroupBubble());
   elmP->AddEventListenerByType(this,
                                NS_LITERAL_STRING("keyup"),
@@ -176,23 +178,22 @@ nsEditorEventListener::Disconnect()
   }
   UninstallFromEditor();
   mEditor = nullptr;
 }
 
 void
 nsEditorEventListener::UninstallFromEditor()
 {
-  nsCOMPtr<nsIDOMEventTarget> piTarget = mEditor->GetDOMEventTarget();
+  nsCOMPtr<EventTarget> piTarget = mEditor->GetDOMEventTarget();
   if (!piTarget) {
     return;
   }
 
-  nsEventListenerManager* elmP =
-    piTarget->GetListenerManager(true);
+  nsEventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
   if (!elmP) {
     return;
   }
 
 #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
   elmP->RemoveEventListenerByType(this,
                                   NS_LITERAL_STRING("keydown"),
                                   dom::TrustedEventsAtSystemGroupBubble());
--- a/editor/libeditor/html/nsHTMLEditor.cpp
+++ b/editor/libeditor/html/nsHTMLEditor.cpp
@@ -65,16 +65,17 @@
 #include "nsWSRunObject.h"
 #include "nsGkAtoms.h"
 #include "nsIWidget.h"
 
 #include "nsIFrame.h"
 #include "nsIParserService.h"
 #include "mozilla/Selection.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/EventTarget.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "nsTextFragment.h"
 
 using namespace mozilla;
 using namespace mozilla::widget;
 
 // Some utilities to handle annoying overloading of "A" tag for link and named anchor
 static char hrefText[] = "href";
@@ -5213,24 +5214,24 @@ nsHTMLEditor::GetActiveEditingHost()
   // we're not active.
   if (!content->HasFlag(NODE_IS_EDITABLE) ||
       content->HasIndependentSelection()) {
     return nullptr;
   }
   return content->GetEditingHost();
 }
 
-already_AddRefed<nsIDOMEventTarget>
+already_AddRefed<mozilla::dom::EventTarget>
 nsHTMLEditor::GetDOMEventTarget()
 {
   // Don't use getDocument here, because we have no way of knowing
   // whether Init() was ever called.  So we need to get the document
   // ourselves, if it exists.
   NS_PRECONDITION(mDocWeak, "This editor has not been initialized yet");
-  nsCOMPtr<nsIDOMEventTarget> target = do_QueryReferent(mDocWeak.get());
+  nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryReferent(mDocWeak);
   return target.forget();
 }
 
 bool
 nsHTMLEditor::ShouldReplaceRootElement()
 {
   if (!mRootElement) {
     // If we don't know what is our root element, we should find our root.
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -101,17 +101,17 @@ public:
 
   /* ------------ nsPlaintextEditor overrides -------------- */
   NS_IMETHOD GetIsDocumentEditable(bool *aIsDocumentEditable);
   NS_IMETHOD BeginningOfDocument();
   virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
   virtual already_AddRefed<nsIContent> GetFocusedContent();
   virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
   virtual bool IsActiveInDOMWindow();
-  virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget();
+  virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget();
   virtual mozilla::dom::Element* GetEditorRoot() MOZ_OVERRIDE;
   virtual already_AddRefed<nsIContent> FindSelectionRoot(nsINode *aNode);
   virtual bool IsAcceptableInputEvent(nsIDOMEvent* aEvent);
   virtual already_AddRefed<nsIContent> GetInputEventTargetContent();
   virtual bool IsEditable(nsIContent *aNode);
   using nsEditor::IsEditable;
 
   /* ------------ nsStubMutationObserver overrides --------- */
--- a/editor/libeditor/text/nsPlaintextEditor.cpp
+++ b/editor/libeditor/text/nsPlaintextEditor.cpp
@@ -1580,20 +1580,20 @@ nsPlaintextEditor::SelectEntireDocument(
     nsCOMPtr<nsIDOMNode> parentNode = GetNodeLocation(childNode, &parentOffset);
 
     return aSelection->Extend(parentNode, parentOffset);
   }
 
   return NS_OK;
 }
 
-already_AddRefed<nsIDOMEventTarget>
+already_AddRefed<mozilla::dom::EventTarget>
 nsPlaintextEditor::GetDOMEventTarget()
 {
-  nsCOMPtr<nsIDOMEventTarget> copy = mEventTarget;
+  nsCOMPtr<mozilla::dom::EventTarget> copy = mEventTarget;
   return copy.forget();
 }
 
 
 nsresult
 nsPlaintextEditor::SetAttributeOrEquivalent(nsIDOMElement * aElement,
                                             const nsAString & aAttribute,
                                             const nsAString & aValue,
--- a/editor/libeditor/text/nsPlaintextEditor.h
+++ b/editor/libeditor/text/nsPlaintextEditor.h
@@ -115,17 +115,17 @@ public:
    *  with a call to EndOperation */
   NS_IMETHOD EndOperation();
 
   /** make the given selection span the entire document */
   NS_IMETHOD SelectEntireDocument(nsISelection *aSelection);
 
   virtual nsresult HandleKeyPressEvent(nsIDOMKeyEvent* aKeyEvent);
 
-  virtual already_AddRefed<nsIDOMEventTarget> GetDOMEventTarget();
+  virtual already_AddRefed<mozilla::dom::EventTarget> GetDOMEventTarget();
 
   virtual nsresult BeginIMEComposition();
   virtual nsresult UpdateIMEComposition(const nsAString &aCompositionString,
                                         nsIPrivateTextRangeList *aTextRange);
 
   virtual already_AddRefed<nsIContent> GetInputEventTargetContent();
 
   /* ------------ Utility Routines, not part of public API -------------- */
--- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
@@ -860,17 +860,17 @@ nsDocShellTreeOwner::AddChromeListeners(
         rv = NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   // register dragover and drop event listeners with the listener manager
   nsCOMPtr<EventTarget> target;
   GetDOMEventTarget(mWebBrowser, getter_AddRefs(target));
 
-  nsEventListenerManager* elmP = target->GetListenerManager(true);
+  nsEventListenerManager* elmP = target->GetOrCreateListenerManager();
   if (elmP) {
     elmP->AddEventListenerByType(this, NS_LITERAL_STRING("dragover"),
                                  dom::TrustedEventsAtSystemGroupBubble());
     elmP->AddEventListenerByType(this, NS_LITERAL_STRING("drop"),
                                  dom::TrustedEventsAtSystemGroupBubble());
   }
 
   return rv;
@@ -890,17 +890,17 @@ nsDocShellTreeOwner::RemoveChromeListene
     NS_RELEASE(mChromeContextMenuListener);
   }
 
   nsCOMPtr<EventTarget> piTarget;
   GetDOMEventTarget(mWebBrowser, getter_AddRefs(piTarget));
   if (!piTarget)
     return NS_OK;
 
-  nsEventListenerManager* elmP = piTarget->GetListenerManager(true);
+  nsEventListenerManager* elmP = piTarget->GetOrCreateListenerManager();
   if (elmP)
   {
     elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("dragover"),
                                     dom::TrustedEventsAtSystemGroupBubble());
     elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("drop"),
                                     dom::TrustedEventsAtSystemGroupBubble());
   }
 
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -993,16 +993,19 @@ public:
   static void SetGlobalEventRecorder(DrawEventRecorder *aRecorder);
 
 #ifdef USE_SKIA_GPU
   static TemporaryRef<DrawTarget>
     CreateDrawTargetSkiaWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext,
                                                       GrGLInterface* aGrGLInterface,
                                                       const IntSize &aSize,
                                                       SurfaceFormat aFormat);
+
+  static void
+    SetGlobalSkiaCacheLimits(int aCount, int aSizeInBytes);
 #endif
 
 #if defined(USE_SKIA) && defined(MOZ_ENABLE_FREETYPE)
   static TemporaryRef<GlyphRenderingOptions>
     CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting);
 #endif
   static TemporaryRef<DrawTarget>
     CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB);
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -507,23 +507,20 @@ DrawTargetCairo::DrawSurface(SourceSurfa
   cairo_surface_destroy(surf);
 
   cairo_pattern_set_matrix(pat, &src_mat);
   cairo_pattern_set_filter(pat, GfxFilterToCairoFilter(aSurfOptions.mFilter));
   cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
 
   cairo_set_antialias(mContext, GfxAntialiasToCairoAntialias(aOptions.mAntialiasMode));
 
-  double clipX1, clipY1, clipX2, clipY2;
-  cairo_clip_extents(mContext, &clipX1, &clipY1, &clipX2, &clipY2);
-  Rect clip(clipX1, clipY1, clipX2 - clipX1, clipY2 - clipY1); // Narrowing of doubles to floats
   // If the destination rect covers the entire clipped area, then unbounded and bounded
   // operations are identical, and we don't need to push a group.
   bool needsGroup = !IsOperatorBoundByMask(aOptions.mCompositionOp) &&
-                    !aDest.Contains(clip);
+                    !aDest.Contains(GetUserSpaceClip());
 
   cairo_translate(mContext, aDest.X(), aDest.Y());
 
   if (needsGroup) {
     cairo_push_group(mContext);
       cairo_new_path(mContext);
       cairo_rectangle(mContext, 0, 0, aDest.Width(), aDest.Height());
       cairo_set_source(mContext, pat);
@@ -633,35 +630,32 @@ DrawTargetCairo::DrawPattern(const Patte
   cairo_set_source(mContext, pat);
 
   cairo_set_antialias(mContext, GfxAntialiasToCairoAntialias(aOptions.mAntialiasMode));
 
   if (NeedIntermediateSurface(aPattern, aOptions) ||
       (!IsOperatorBoundByMask(aOptions.mCompositionOp) && !aPathBoundsClip)) {
     cairo_push_group_with_content(mContext, CAIRO_CONTENT_COLOR_ALPHA);
 
-    ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
-
     // Don't want operators to be applied twice
     cairo_set_operator(mContext, CAIRO_OPERATOR_OVER);
 
     if (aDrawType == DRAW_STROKE) {
       SetCairoStrokeOptions(mContext, aStrokeOptions);
       cairo_stroke_preserve(mContext);
     } else {
       cairo_fill_preserve(mContext);
     }
 
     cairo_pop_group_to_source(mContext);
 
     // Now draw the content using the desired operator
     cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
     cairo_paint_with_alpha(mContext, aOptions.mAlpha);
   } else {
-    ClearSurfaceForUnboundedSource(aOptions.mCompositionOp);
     cairo_set_operator(mContext, GfxOpToCairoOp(aOptions.mCompositionOp));
 
     if (aDrawType == DRAW_STROKE) {
       SetCairoStrokeOptions(mContext, aStrokeOptions);
       cairo_stroke_preserve(mContext);
     } else {
       cairo_fill_preserve(mContext);
     }
@@ -677,23 +671,17 @@ DrawTargetCairo::FillRect(const Rect &aR
 {
   AutoPrepareForDrawing prep(this, mContext);
 
   cairo_new_path(mContext);
   cairo_rectangle(mContext, aRect.x, aRect.y, aRect.Width(), aRect.Height());
 
   bool pathBoundsClip = false;
 
-  double cexts[4];
-  cairo_clip_extents(mContext, &cexts[0], &cexts[1], &cexts[2], &cexts[3]);
-  Rect clipRect(cexts[0], cexts[1], cexts[2] - cexts[0], cexts[3] - cexts[1]);
-  double pexts[4];
-  cairo_path_extents(mContext, &pexts[0], &pexts[1], &pexts[2], &pexts[3]);
-  Rect pathRect(pexts[0], pexts[1], pexts[2] - pexts[0], pexts[3] - pexts[1]);
-  if (pathRect.Contains(clipRect)) {
+  if (aRect.Contains(GetUserSpaceClip())) {
     pathBoundsClip = true;
   }
 
   DrawPattern(aPattern, StrokeOptions(), aOptions, DRAW_FILL, pathBoundsClip);
 }
 
 void
 DrawTargetCairo::CopySurfaceInternal(cairo_surface_t* aSurface,
@@ -1187,16 +1175,24 @@ DrawTargetCairo::SetTransform(const Matr
 {
   mTransform = aTransform;
 
   cairo_matrix_t mat;
   GfxMatrixToCairoMatrix(mTransform, mat);
   cairo_set_matrix(mContext, &mat);
 }
 
+Rect
+DrawTargetCairo::GetUserSpaceClip()
+{
+  double clipX1, clipY1, clipX2, clipY2;
+  cairo_clip_extents(mContext, &clipX1, &clipY1, &clipX2, &clipY2);
+  return Rect(clipX1, clipY1, clipX2 - clipX1, clipY2 - clipY1); // Narrowing of doubles to floats
+}
+
 cairo_t*
 BorrowedCairoContext::BorrowCairoContextFromDrawTarget(DrawTarget* aDT)
 {
   if (aDT->GetType() != BACKEND_CAIRO || aDT->IsDualDrawTarget()) {
     return nullptr;
   }
   DrawTargetCairo* cairoDT = static_cast<DrawTargetCairo*>(aDT);
 
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -167,16 +167,18 @@ private: // methods
                    const DrawOptions& aOptions,
                    DrawPatternType aDrawType,
                    bool aPathBoundsClip = false);
 
   void CopySurfaceInternal(cairo_surface_t* aSurface,
                            const IntRect& aSource,
                            const IntPoint& aDest);
 
+  Rect GetUserSpaceClip();
+
   // Call before you make any changes to the backing surface with which this
   // context is associated. Pass the path you're going to be using if you have
   // one.
   void WillChange(const Path* aPath = nullptr);
 
   // Call if there is any reason to disassociate the snapshot from this draw
   // target; for example, because we're going to be destroyed.
   void MarkSnapshotIndependent();
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -71,66 +71,68 @@ public:
 
   std::vector<SkColor> mColors;
   std::vector<SkScalar> mPositions;
   int mCount;
   ExtendMode mExtendMode;
 };
 
 #ifdef USE_SKIA_GPU
+int DrawTargetSkia::sTextureCacheCount = 256;
+int DrawTargetSkia::sTextureCacheSizeInBytes = 96*1024*1024;
 
 static std::vector<DrawTargetSkia*>&
 GLDrawTargets()
 {
   static std::vector<DrawTargetSkia*> targets;
   return targets;
 }
 
-#define SKIA_MAX_CACHE_ITEMS 256
-
-// 64MB was chosen because it seems we can pass all of our tests
-// on the current hardware (Tegra2) without running out of memory
-#define SKIA_TOTAL_CACHE_SIZE 64*1024*1024
-
-static void
-SetCacheLimits()
+void
+DrawTargetSkia::RebalanceCacheLimits()
 {
+  // Divide the global cache limits equally between all currently active GL-backed
+  // Skia DrawTargets.
   std::vector<DrawTargetSkia*>& targets = GLDrawTargets();
-  uint32_t size = targets.size();
-  if (size == 0)
+  uint32_t targetCount = targets.size();
+  if (targetCount == 0)
     return;
 
-  int individualCacheSize = SKIA_TOTAL_CACHE_SIZE / size;
-  for (uint32_t i = 0; i < size; i++) {
-    targets[i]->SetCacheLimits(SKIA_MAX_CACHE_ITEMS, individualCacheSize);
+  int individualCacheSize = sTextureCacheSizeInBytes / targetCount;
+  for (uint32_t i = 0; i < targetCount; i++) {
+    targets[i]->SetCacheLimits(sTextureCacheCount, individualCacheSize);
   }
-
 }
 
-#undef SKIA_MAX_CACHE_ITEMS
-#undef SKIA_TOTAL_CACHE_SIZE
-
 static void
 AddGLDrawTarget(DrawTargetSkia* target)
 {
   GLDrawTargets().push_back(target);
-  SetCacheLimits();
+  DrawTargetSkia::RebalanceCacheLimits();
 }
 
 static void
 RemoveGLDrawTarget(DrawTargetSkia* target)
 {
   std::vector<DrawTargetSkia*>& targets = GLDrawTargets();
   std::vector<DrawTargetSkia*>::iterator it = std::find(targets.begin(), targets.end(), target);
   if (it != targets.end()) {
     targets.erase(it);
-    SetCacheLimits();
+    DrawTargetSkia::RebalanceCacheLimits();
   }
 }
 
+void
+DrawTargetSkia::SetGlobalCacheLimits(int aCount, int aSizeInBytes)
+{
+  sTextureCacheCount = aCount;
+  sTextureCacheSizeInBytes = aSizeInBytes;
+
+  DrawTargetSkia::RebalanceCacheLimits();
+}
 #endif
 
 DrawTargetSkia::DrawTargetSkia()
   : mSnapshot(nullptr)
 {
 }
 
 DrawTargetSkia::~DrawTargetSkia()
@@ -727,17 +729,16 @@ DrawTargetSkia::InitWithGLContextAndGrGL
 }
 
 void
 DrawTargetSkia::SetCacheLimits(int aCount, int aSizeInBytes)
 {
   MOZ_ASSERT(mGrContext, "No GrContext!");
   mGrContext->setTextureCacheLimits(aCount, aSizeInBytes);
 }
-
 #endif
 
 void
 DrawTargetSkia::Init(unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat)
 {
   bool isOpaque = false;
   if (aFormat == FORMAT_B8G8R8X8) {
     // We have to manually set the A channel to be 255 as Skia doesn't understand BGRX
--- a/gfx/2d/DrawTargetSkia.h
+++ b/gfx/2d/DrawTargetSkia.h
@@ -100,17 +100,19 @@ public:
 
 #ifdef USE_SKIA_GPU
   virtual GenericRefCountedBase* GetGLContext() const MOZ_OVERRIDE { return mGLContext; }
   void InitWithGLContextAndGrGLInterface(GenericRefCountedBase* aGLContext,
                                          GrGLInterface* aGrGLInterface,
                                          const IntSize &aSize,
                                          SurfaceFormat aFormat) MOZ_OVERRIDE;
 
-  void SetCacheLimits(int number, int sizeInBytes);
+  void SetCacheLimits(int aCount, int aSizeInBytes);
+  static void SetGlobalCacheLimits(int aCount, int aSizeInBytes);
+  static void RebalanceCacheLimits();
 #endif
 
   operator std::string() const {
     std::stringstream stream;
     stream << "DrawTargetSkia(" << this << ")";
     return stream.str();
   }
 
@@ -125,16 +127,19 @@ private:
    * These members have inter-dependencies, but do not keep each other alive, so
    * destruction order is very important here: mGrContext uses mGrGLInterface, and
    * through it, uses mGLContext, so it is important that they be declared in the
    * present order.
    */
   RefPtr<GenericRefCountedBase> mGLContext;
   SkRefPtr<GrGLInterface> mGrGLInterface;
   SkRefPtr<GrContext> mGrContext;
+
+  static int sTextureCacheCount;
+  static int sTextureCacheSizeInBytes;
 #endif
 
   IntSize mSize;
   SkRefPtr<SkCanvas> mCanvas;
   SourceSurfaceSkia* mSnapshot;
 };
 
 }
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -508,16 +508,22 @@ Factory::CreateDrawTargetSkiaWithGLConte
                                                            const IntSize &aSize,
                                                            SurfaceFormat aFormat)
 {
   DrawTargetSkia* newDrawTargetSkia = new DrawTargetSkia();
   newDrawTargetSkia->InitWithGLContextAndGrGLInterface(aGLContext, aGrGLInterface, aSize, aFormat);
   RefPtr<DrawTarget> newTarget = newDrawTargetSkia;
   return newTarget;
 }
+
+void
+Factory::SetGlobalSkiaCacheLimits(int aCount, int aSizeInBytes)
+{
+    DrawTargetSkia::SetGlobalCacheLimits(aCount, aSizeInBytes);
+}
 #endif // USE_SKIA_GPU
 
 #ifdef USE_SKIA_FREETYPE
 TemporaryRef<GlyphRenderingOptions>
 Factory::CreateCairoGlyphRenderingOptions(FontHinting aHinting, bool aAutoHinting)
 {
   RefPtr<GlyphRenderingOptionsCairo> options =
     new GlyphRenderingOptionsCairo();
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -57,16 +57,17 @@
 #include "GLContext.h"
 #include "GLContextProvider.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "TexturePoolOGL.h"
 #endif
 
 #ifdef USE_SKIA
+#include "mozilla/Hal.h"
 #include "skia/SkGraphics.h"
 #endif
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Mutex.h"
 
@@ -272,16 +273,20 @@ gfxPlatform::gfxPlatform()
                                  false);
     Preferences::AddBoolVarCache(&mDrawBigImageBorders,
                                  "layers.draw-bigimage-borders",
                                  false);
 
     uint32_t canvasMask = (1 << BACKEND_CAIRO) | (1 << BACKEND_SKIA);
     uint32_t contentMask = 1 << BACKEND_CAIRO;
     InitBackendPrefs(canvasMask, contentMask);
+
+#ifdef USE_SKIA
+    InitializeSkiaCaches();
+#endif
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
     if (!gPlatform) {
         Init();
     }
@@ -805,16 +810,49 @@ gfxPlatform::SupportsAzureContentForDraw
 
 bool
 gfxPlatform::UseAcceleratedSkiaCanvas()
 {
   return Preferences::GetBool("gfx.canvas.azure.accelerated", false) &&
          mPreferredCanvasBackend == BACKEND_SKIA;
 }
 
+void
+gfxPlatform::InitializeSkiaCaches()
+{
+#ifdef USE_SKIA_GPU
+  if (UseAcceleratedSkiaCanvas()) {
+    bool usingDynamicCache = Preferences::GetBool("gfx.canvas.skiagl.dynamic-cache", false);
+
+    int cacheItemLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-items", 256);
+    int cacheSizeLimit = Preferences::GetInt("gfx.canvas.skiagl.cache-size", 96);
+
+    // Prefs are in megabytes, but we want the sizes in bytes
+    cacheSizeLimit *= 1024*1024;
+
+    if (usingDynamicCache) {
+      uint32_t totalMemory = mozilla::hal::GetTotalSystemMemory();
+
+      if (totalMemory <= 256*1024*1024) {
+        // We need a very minimal cache on 256 meg devices
+        cacheSizeLimit = 2*1024*1024;
+      } else if (totalMemory > 0) {
+        cacheSizeLimit = totalMemory / 16;
+      }
+    }
+
+#ifdef DEBUG
+    printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit);
+#endif
+
+    Factory::SetGlobalSkiaCacheLimits(cacheItemLimit, cacheSizeLimit);
+  }
+#endif
+}
+
 already_AddRefed<gfxASurface>
 gfxPlatform::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
 {
   if (aTarget->GetType() == BACKEND_CAIRO) {
     cairo_surface_t* csurf =
       static_cast<cairo_surface_t*>(aTarget->GetNativeSurface(NATIVE_SURFACE_CAIRO_SURFACE));
     return gfxASurface::Wrap(csurf);
   }
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -273,16 +273,18 @@ public:
     bool SupportsAzureContentForDrawTarget(mozilla::gfx::DrawTarget* aTarget);
 
     bool SupportsAzureContentForType(mozilla::gfx::BackendType aType) {
       return (1 << aType) & mContentBackendBitmask;
     }
 
     virtual bool UseAcceleratedSkiaCanvas();
 
+    virtual void InitializeSkiaCaches();
+
     void GetAzureBackendInfo(mozilla::widget::InfoObject &aObj) {
       aObj.DefineProperty("AzureCanvasBackend", GetBackendName(mPreferredCanvasBackend));
       aObj.DefineProperty("AzureSkiaAccelerated", UseAcceleratedSkiaCanvas());
       aObj.DefineProperty("AzureFallbackCanvasBackend", GetBackendName(mFallbackCanvasBackend));
       aObj.DefineProperty("AzureContentBackend", GetBackendName(mContentBackend));
     }
 
     mozilla::gfx::BackendType GetPreferredCanvasBackend() {
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -1190,10 +1190,17 @@ StartDiskSpaceWatcher()
 void
 StopDiskSpaceWatcher()
 {
   AssertMainProcess();
   AssertMainThread();
   PROXY_IF_SANDBOXED(StopDiskSpaceWatcher());
 }
 
+uint32_t
+GetTotalSystemMemory()
+{
+  return hal_impl::GetTotalSystemMemory();
+}
+
+
 } // namespace hal
 } // namespace mozilla
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -592,16 +592,23 @@ void StartDiskSpaceWatcher();
 
 /**
  * Stop monitoring disk space for low space situations.
  *
  * This API is currently only allowed to be used from the main process.
  */
 void StopDiskSpaceWatcher();
 
+/**
+ * Get total system memory of device being run on in bytes.
+ *
+ * Returns 0 if we are unable to determine this information from /proc/meminfo.
+ */
+uint32_t GetTotalSystemMemory();
+
 } // namespace MOZ_HAL_NAMESPACE
 } // namespace mozilla
 
 #ifdef MOZ_DEFINED_HAL_NAMESPACE
 # undef MOZ_DEFINED_HAL_NAMESPACE
 # undef MOZ_HAL_NAMESPACE
 #endif
 
new file mode 100644
--- /dev/null
+++ b/hal/fallback/FallbackMemory.cpp
@@ -0,0 +1,20 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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 "Hal.h"
+
+namespace mozilla {
+namespace hal_impl {
+
+uint32_t
+GetTotalSystemMemory()
+{
+	return 0;
+}
+
+} // namespace hal_impl
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/hal/linux/LinuxMemory.cpp
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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 <stdio.h>
+#include "Hal.h"
+
+namespace mozilla {
+namespace hal_impl {
+
+uint32_t
+GetTotalSystemMemory()
+{
+  static uint32_t sTotalMemory;
+  static bool sTotalMemoryObtained = false;
+
+  if (!sTotalMemoryObtained) {
+    sTotalMemoryObtained = true;
+
+    FILE* fd = fopen("/proc/meminfo", "r");
+    if (!fd) {
+      return 0;
+    }
+
+    int rv = fscanf(fd, "MemTotal: %i kB", &sTotalMemory);
+
+    if (fclose(fd) || rv != 1) {
+      return 0;
+    }
+  }
+
+  return sTotalMemory * 1024;
+}
+
+} // namespace hal_impl
+} // namespace mozilla
--- a/hal/moz.build
+++ b/hal/moz.build
@@ -45,34 +45,37 @@ elif CONFIG['MOZ_GAMEPAD_BACKEND'] == 'l
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
     CPP_SOURCES += [
         'android/AndroidHal.cpp',
         'android/AndroidSensor.cpp',
         'fallback/FallbackPower.cpp',
         'fallback/FallbackAlarm.cpp',
+        'linux/LinuxMemory.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     CPP_SOURCES += [
         'gonk/GonkDiskSpaceWatcher.cpp',
         'gonk/GonkFMRadio.cpp',
         'gonk/GonkHal.cpp',
         'gonk/GonkSensor.cpp',
         'gonk/GonkSwitch.cpp',
         'gonk/UeventPoller.cpp',
         'linux/LinuxPower.cpp',
+        'linux/LinuxMemory.cpp',
     ]
 elif CONFIG['OS_TARGET'] == 'Linux':
     CPP_SOURCES += [
         'fallback/FallbackAlarm.cpp',
         'fallback/FallbackScreenConfiguration.cpp',
         'fallback/FallbackSensor.cpp',
         'fallback/FallbackVibration.cpp',
         'linux/LinuxPower.cpp',
+        'linux/LinuxMemory.cpp',
     ]
     if CONFIG['MOZ_ENABLE_DBUS']:
         CPP_SOURCES += [
             'linux/UPowerClient.cpp',
         ]
     else:
         CPP_SOURCES += [
             'fallback/FallbackBattery.cpp',
@@ -80,32 +83,35 @@ elif CONFIG['OS_TARGET'] == 'Linux':
 elif CONFIG['OS_TARGET'] == 'WINNT':
     CPP_SOURCES += [
         'fallback/FallbackAlarm.cpp',
         'fallback/FallbackPower.cpp',
         'fallback/FallbackScreenConfiguration.cpp',
         'fallback/FallbackVibration.cpp',
         'windows/WindowsBattery.cpp',
         'windows/WindowsSensor.cpp',
+        'fallback/FallbackMemory.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     CPP_SOURCES += [
         'cocoa/CocoaBattery.cpp',
         'fallback/FallbackAlarm.cpp',
         'fallback/FallbackPower.cpp',
         'fallback/FallbackScreenConfiguration.cpp',
         'fallback/FallbackVibration.cpp',
+        'fallback/FallbackMemory.cpp',
     ]
 elif CONFIG['OS_TARGET'] in ('OpenBSD', 'NetBSD', 'FreeBSD', 'DragonFly'):
     CPP_SOURCES += [
         'fallback/FallbackAlarm.cpp',
         'fallback/FallbackPower.cpp',
         'fallback/FallbackScreenConfiguration.cpp',
         'fallback/FallbackSensor.cpp',
         'fallback/FallbackVibration.cpp',
+        'fallback/FallbackMemory.cpp',
     ]
     if CONFIG['MOZ_ENABLE_DBUS']:
         CPP_SOURCES += [
             'linux/UPowerClient.cpp',
         ]
     else:
         CPP_SOURCES += [
             'fallback/FallbackBattery.cpp',
@@ -113,16 +119,17 @@ elif CONFIG['OS_TARGET'] in ('OpenBSD', 
 else:
     CPP_SOURCES += [
         'fallback/FallbackAlarm.cpp',
         'fallback/FallbackBattery.cpp',
         'fallback/FallbackPower.cpp',
         'fallback/FallbackScreenConfiguration.cpp',
         'fallback/FallbackSensor.cpp',
         'fallback/FallbackVibration.cpp',
+        'fallback/FallbackMemory.cpp',
     ]
 
 # Fallbacks for backends implemented on Gonk only.
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
     CPP_SOURCES += [
         'fallback/FallbackDiskSpaceWatcher.cpp',
         'fallback/FallbackFMRadio.cpp',
         'fallback/FallbackFactoryReset.cpp',
--- a/image/build/nsImageModule.cpp
+++ b/image/build/nsImageModule.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 "mozilla/ModuleUtils.h"
 #include "nsMimeTypes.h"
 
 #include "ImageFactory.h"
 #include "RasterImage.h"
+#include "SurfaceCache.h"
 
 #include "imgLoader.h"
 #include "imgRequest.h"
 #include "imgRequestProxy.h"
 #include "imgTools.h"
 #include "DiscardTracker.h"
 
 #include "nsICOEncoder.h"
@@ -79,24 +80,26 @@ static const mozilla::Module::CategoryEn
 };
 
 static nsresult
 imglib_Initialize()
 {
   mozilla::image::DiscardTracker::Initialize();
   mozilla::image::ImageFactory::Initialize();
   mozilla::image::RasterImage::Initialize();
+  mozilla::image::SurfaceCache::Initialize();
   imgLoader::GlobalInit();
   return NS_OK;
 }
 
 static void
 imglib_Shutdown()
 {
   imgLoader::Shutdown();
+  mozilla::image::SurfaceCache::Shutdown();
   mozilla::image::DiscardTracker::Shutdown();
 }
 
 static const mozilla::Module kImageModule = {
   mozilla::Module::kVersion,
   kImageCIDs,
   kImageContracts,
   kImageCategories,
new file mode 100644
--- /dev/null
+++ b/image/src/SurfaceCache.cpp
@@ -0,0 +1,559 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * SurfaceCache is a service for caching temporary surfaces in imagelib.
+ */
+
+#include "SurfaceCache.h"
+
+#include <algorithm>
+#include "mozilla/Attributes.h"  // for MOZ_THIS_IN_INITIALIZER_LIST
+#include "mozilla/DebugOnly.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/RefPtr.h"
+#include "mozilla/Util.h"  // for Maybe
+#include "gfxASurface.h"
+#include "gfxPattern.h"  // Workaround for flaw in bug 921753 part 2.
+#include "gfxDrawable.h"
+#include "gfxPlatform.h"
+#include "nsAutoPtr.h"
+#include "nsExpirationTracker.h"
+#include "nsHashKeys.h"
+#include "nsRefPtrHashtable.h"
+#include "nsSize.h"
+#include "nsTArray.h"
+#include "prsystem.h"
+#include "SVGImageContext.h"
+
+using std::max;
+using std::min;
+using mozilla::gfx::DrawTarget;
+
+/**
+ * Hashtable key class to use with objects for which Hash() and operator==()
+ * are defined.
+ * XXX(seth): This will get moved to xpcom/glue/nsHashKeys.h in a followup bug.
+ */
+template <typename T>
+class nsGenericHashKey : public PLDHashEntryHdr
+{
+public:
+  typedef const T& KeyType;
+  typedef const T* KeyTypePointer;
+
+  nsGenericHashKey(KeyTypePointer aKey) : mKey(*aKey) { }
+  nsGenericHashKey(const nsGenericHashKey<T>& aOther) : mKey(aOther.mKey) { }
+
+  KeyType GetKey() const { return mKey; }
+  bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mKey; }
+
+  static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
+  static PLDHashNumber HashKey(KeyTypePointer aKey) { return aKey->Hash(); }
+  enum { ALLOW_MEMMOVE = true };
+
+private:
+  T mKey;
+};
+
+namespace mozilla {
+namespace image {
+
+class CachedSurface;
+class SurfaceCacheImpl;
+
+///////////////////////////////////////////////////////////////////////////////
+// Static Data
+///////////////////////////////////////////////////////////////////////////////
+
+// The single surface cache instance.
+static SurfaceCacheImpl* sInstance = nullptr;
+
+
+///////////////////////////////////////////////////////////////////////////////
+// SurfaceCache Implementation
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Cost models the cost of storing a surface in the cache. Right now, this is
+ * simply an estimate of the size of the surface in bytes, but in the future it
+ * may be worth taking into account the cost of rematerializing the surface as
+ * well.
+ */
+typedef size_t Cost;
+
+static Cost ComputeCost(const nsIntSize aSize)
+{
+  return aSize.width * aSize.height * 4;  // width * height * 4 bytes (32bpp)
+}
+
+/*
+ * Since we want to be able to make eviction decisions based on cost, we need to
+ * be able to look up the CachedSurface which has a certain cost as well as the
+ * cost associated with a certain CachedSurface. To make this possible, in data
+ * structures we actually store a CostEntry, which contains a weak pointer to
+ * its associated surface.
+ *
+ * To make usage of the weak pointer safe, SurfaceCacheImpl always calls
+ * StartTracking after a surface is stored in the cache and StopTracking before
+ * it is removed.
+ */
+class CostEntry
+{
+public:
+  CostEntry(CachedSurface* aSurface, Cost aCost)
+    : mSurface(aSurface)
+    , mCost(aCost)
+  {
+    MOZ_ASSERT(aSurface, "Must have a surface");
+  }
+
+  CachedSurface* GetSurface() const { return mSurface; }
+  Cost GetCost() const { return mCost; }
+
+  bool operator==(const CostEntry& aOther) const
+  {
+    return mSurface == aOther.mSurface &&
+           mCost == aOther.mCost;
+  }
+
+  bool operator<(const CostEntry& aOther) const
+  {
+    return mCost < aOther.mCost ||
+           (mCost == aOther.mCost && mSurface < aOther.mSurface);
+  }
+
+private:
+  CachedSurface* mSurface;
+  Cost           mCost;
+};
+
+/*
+ * A CachedSurface associates a surface with a key that uniquely identifies that
+ * surface.
+ */
+class CachedSurface : public RefCounted<CachedSurface>
+{
+public:
+  CachedSurface(DrawTarget*       aTarget,
+                const nsIntSize   aTargetSize,
+                const Cost        aCost,
+                const ImageKey    aImageKey,
+                const SurfaceKey& aSurfaceKey)
+    : mTarget(aTarget)
+    , mTargetSize(aTargetSize)
+    , mCost(aCost)
+    , mImageKey(aImageKey)
+    , mSurfaceKey(aSurfaceKey)
+  {
+    MOZ_ASSERT(mTarget, "Must have a valid DrawTarget");
+    MOZ_ASSERT(mImageKey, "Must have a valid image key");
+  }
+
+  already_AddRefed<gfxDrawable> Drawable() const
+  {
+    nsRefPtr<gfxASurface> surface =
+      gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mTarget);
+    nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(surface, mTargetSize);
+    return drawable.forget();
+  }
+
+  ImageKey GetImageKey() const { return mImageKey; }
+  SurfaceKey GetSurfaceKey() const { return mSurfaceKey; }
+  CostEntry GetCostEntry() { return image::CostEntry(this, mCost); }
+  nsExpirationState* GetExpirationState() { return &mExpirationState; }
+
+private:
+  nsExpirationState       mExpirationState;
+  nsRefPtr<DrawTarget>    mTarget;
+  const nsIntSize         mTargetSize;
+  const Cost              mCost;
+  const ImageKey          mImageKey;
+  const SurfaceKey        mSurfaceKey;
+};
+
+/*
+ * An ImageSurfaceCache is a per-image surface cache. For correctness we must be
+ * able to remove all surfaces associated with an image when the image is
+ * destroyed or invalidated. Since this will happen frequently, it makes sense
+ * to make it cheap by storing the surfaces for each image separately.
+ */
+class ImageSurfaceCache : public RefCounted<ImageSurfaceCache>
+{
+public:
+  typedef nsRefPtrHashtable<nsGenericHashKey<SurfaceKey>, CachedSurface> SurfaceTable;
+
+  bool IsEmpty() const { return mSurfaces.Count() == 0; }
+  
+  void Insert(const SurfaceKey& aKey, CachedSurface* aSurface)
+  {
+    MOZ_ASSERT(aSurface, "Should have a surface");
+    mSurfaces.Put(aKey, aSurface);
+  }
+
+  void Remove(CachedSurface* aSurface)
+  {
+    MOZ_ASSERT(aSurface, "Should have a surface");
+    MOZ_ASSERT(mSurfaces.GetWeak(aSurface->GetSurfaceKey()),
+        "Should not be removing a surface we don't have");
+
+    mSurfaces.Remove(aSurface->GetSurfaceKey());
+  }
+
+  already_AddRefed<CachedSurface> Lookup(const SurfaceKey& aSurfaceKey)
+  {
+    nsRefPtr<CachedSurface> surface;
+    mSurfaces.Get(aSurfaceKey, getter_AddRefs(surface));
+    return surface.forget();
+  }
+
+  void ForEach(SurfaceTable::EnumReadFunction aFunction, void* aData)
+  {
+    mSurfaces.EnumerateRead(aFunction, aData);
+  }
+
+private:
+  SurfaceTable mSurfaces;
+};
+
+/*
+ * SurfaceCacheImpl is responsible for determining which surfaces will be cached
+ * and managing the surface cache data structures. Rather than interact with
+ * SurfaceCacheImpl directly, client code interacts with SurfaceCache, which
+ * maintains high-level invariants and encapsulates the details of the surface
+ * cache's implementation.
+ */
+class SurfaceCacheImpl
+{
+public:
+  SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS,
+                   uint32_t aSurfaceCacheSize)
+    : mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
+                         aSurfaceCacheExpirationTimeMS)
+    , mReporter(new SurfaceCacheReporter)
+    , mMemoryPressureObserver(new MemoryPressureObserver)
+    , mMaxCost(aSurfaceCacheSize)
+    , mAvailableCost(aSurfaceCacheSize)
+  {
+    NS_RegisterMemoryReporter(mReporter);
+
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    if (os)
+      os->AddObserver(mMemoryPressureObserver, "memory-pressure", false);
+  }
+
+  ~SurfaceCacheImpl()
+  {
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    if (os)
+      os->RemoveObserver(mMemoryPressureObserver, "memory-pressure");
+
+    NS_UnregisterMemoryReporter(mReporter);
+  }
+
+  void Insert(DrawTarget*       aTarget,
+              nsIntSize         aTargetSize,
+              const Cost        aCost,
+              const ImageKey    aImageKey,
+              const SurfaceKey& aSurfaceKey)
+  {
+    MOZ_ASSERT(!Lookup(aImageKey, aSurfaceKey).get(),
+               "Inserting a duplicate drawable into the SurfaceCache");
+
+    // If this is bigger than the maximum cache size, refuse to cache it.
+    if (!CanHold(aCost))
+      return;
+
+    nsRefPtr<CachedSurface> surface =
+      new CachedSurface(aTarget, aTargetSize, aCost, aImageKey, aSurfaceKey);
+
+    // Remove elements in order of cost until we can fit this in the cache.
+    while (aCost > mAvailableCost) {
+      MOZ_ASSERT(!mCosts.IsEmpty(), "Removed everything and it still won't fit");
+      Remove(mCosts.LastElement().GetSurface());
+    }
+
+    // Locate the appropriate per-image cache. If there's not an existing cache
+    // for this image, create it.
+    nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
+    if (!cache) {
+      cache = new ImageSurfaceCache;
+      mImageCaches.Put(aImageKey, cache);
+    }
+
+    // Insert.
+    MOZ_ASSERT(aCost <= mAvailableCost, "Inserting despite too large a cost");
+    cache->Insert(aSurfaceKey, surface);
+    StartTracking(surface);
+  }
+
+  void Remove(CachedSurface* aSurface)
+  {
+    MOZ_ASSERT(aSurface, "Should have a surface");
+    const ImageKey imageKey = aSurface->GetImageKey();
+
+    nsRefPtr<ImageSurfaceCache> cache = GetImageCache(imageKey);
+    MOZ_ASSERT(cache, "Shouldn't try to remove a surface with no image cache");
+
+    StopTracking(aSurface);
+    cache->Remove(aSurface);
+
+    // Remove the per-image cache if it's unneeded now.
+    if (cache->IsEmpty()) {
+      mImageCaches.Remove(imageKey);
+    }
+  }
+
+  void StartTracking(CachedSurface* aSurface)
+  {
+    CostEntry costEntry = aSurface->GetCostEntry();
+    MOZ_ASSERT(costEntry.GetCost() <= mAvailableCost,
+               "Cost too large and the caller didn't catch it");
+
+    mAvailableCost -= costEntry.GetCost();
+    mCosts.InsertElementSorted(costEntry);
+    mExpirationTracker.AddObject(aSurface);
+  }
+
+  void StopTracking(CachedSurface* aSurface)
+  {
+    MOZ_ASSERT(aSurface, "Should have a surface");
+    CostEntry costEntry = aSurface->GetCostEntry();
+
+    mExpirationTracker.RemoveObject(aSurface);
+    DebugOnly<bool> foundInCosts = mCosts.RemoveElementSorted(costEntry);
+    mAvailableCost += costEntry.GetCost();
+
+    MOZ_ASSERT(foundInCosts, "Lost track of costs for this surface");
+    MOZ_ASSERT(mAvailableCost <= mMaxCost, "More available cost than we started with");
+  }
+
+  already_AddRefed<gfxDrawable> Lookup(const ImageKey    aImageKey,
+                                       const SurfaceKey& aSurfaceKey)
+  {
+    nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
+    if (!cache)
+      return nullptr;  // No cached surfaces for this image.
+    
+    nsRefPtr<CachedSurface> surface = cache->Lookup(aSurfaceKey);
+    if (!surface)
+      return nullptr;  // Lookup in the per-image cache missed.
+    
+    mExpirationTracker.MarkUsed(surface);
+    return surface->Drawable();
+  }
+
+  bool CanHold(const Cost aCost) const
+  {
+    return aCost <= mMaxCost;
+  }
+
+  void Discard(const ImageKey aImageKey)
+  {
+    nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
+    if (!cache)
+      return;  // No cached surfaces for this image, so nothing to do.
+
+    // Discard all of the cached surfaces for this image.
+    // XXX(seth): This is O(n^2) since for each item in the cache we are
+    // removing an element from the costs array. Since n is expected to be
+    // small, performance should be good, but if usage patterns change we should
+    // change the data structure used for mCosts.
+    cache->ForEach(DoStopTracking, this);
+
+    // The per-image cache isn't needed anymore, so remove it as well.
+    mImageCaches.Remove(aImageKey);
+  }
+
+  void DiscardAll()
+  {
+    // Remove in order of cost because mCosts is an array and the other data
+    // structures are all hash tables.
+    while (!mCosts.IsEmpty()) {
+      Remove(mCosts.LastElement().GetSurface());
+    }
+  }
+
+  static PLDHashOperator DoStopTracking(const SurfaceKey&,
+                                        CachedSurface*    aSurface,
+                                        void*             aCache)
+  {
+    static_cast<SurfaceCacheImpl*>(aCache)->StopTracking(aSurface);
+    return PL_DHASH_NEXT;
+  }
+
+  int64_t SizeOfSurfacesEstimate() const
+  {
+    return int64_t(mMaxCost - mAvailableCost);
+  }
+
+private:
+  already_AddRefed<ImageSurfaceCache> GetImageCache(const ImageKey aImageKey)
+  {
+    nsRefPtr<ImageSurfaceCache> imageCache;
+    mImageCaches.Get(aImageKey, getter_AddRefs(imageCache));
+    return imageCache.forget();
+  }
+
+  struct SurfaceTracker : public nsExpirationTracker<CachedSurface, 2>
+  {
+    SurfaceTracker(SurfaceCacheImpl* aCache, uint32_t aSurfaceCacheExpirationTimeMS)
+      : nsExpirationTracker<CachedSurface, 2>(aSurfaceCacheExpirationTimeMS)
+      , mCache(aCache)
+    { }
+
+  protected:
+    virtual void NotifyExpired(CachedSurface* aSurface) MOZ_OVERRIDE
+    {
+      if (mCache) {
+        mCache->Remove(aSurface);
+      }
+    }
+
+  private:
+    SurfaceCacheImpl* const mCache;  // Weak pointer to owner.
+  };
+
+  // XXX(seth): This is currently only an estimate and, since we don't know which
+  // surfaces are in GPU memory and which aren't, it's reported as KIND_OTHER and
+  // will also show up in heap-unclassified. Bug 923302 will make this nicer.
+  struct SurfaceCacheReporter : public MemoryUniReporter
+  {
+    SurfaceCacheReporter()
+      : MemoryUniReporter("imagelib-surface-cache",
+                          KIND_OTHER,
+                          UNITS_BYTES,
+                          "Memory used by the imagelib temporary surface cache.")
+    { }
+
+  protected:
+    int64_t Amount() MOZ_OVERRIDE
+    {
+      return sInstance ? sInstance->SizeOfSurfacesEstimate() : 0;
+    }
+  };
+
+  struct MemoryPressureObserver : public nsIObserver
+  {
+    NS_DECL_ISUPPORTS
+
+    virtual ~MemoryPressureObserver() { }
+
+    NS_IMETHOD Observe(nsISupports*, const char* aTopic, const PRUnichar*)
+    {
+      if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
+        sInstance->DiscardAll();
+      }
+      return NS_OK;
+    }
+  };
+
+
+  nsTArray<CostEntry>                                       mCosts;
+  nsRefPtrHashtable<nsPtrHashKey<Image>, ImageSurfaceCache> mImageCaches;
+  SurfaceTracker                                            mExpirationTracker;
+  nsRefPtr<SurfaceCacheReporter>                            mReporter;
+  nsRefPtr<MemoryPressureObserver>                          mMemoryPressureObserver;
+  const Cost                                                mMaxCost;
+  Cost                                                      mAvailableCost;
+};
+
+NS_IMPL_ISUPPORTS1(SurfaceCacheImpl::MemoryPressureObserver, nsIObserver)
+
+///////////////////////////////////////////////////////////////////////////////
+// Public API
+///////////////////////////////////////////////////////////////////////////////
+
+/* static */ void
+SurfaceCache::Initialize()
+{
+  // Initialize preferences.
+  MOZ_ASSERT(!sInstance, "Shouldn't initialize more than once");
+
+  // Length of time before an unused surface is removed from the cache, in milliseconds.
+  // The default value gives an expiration time of 1 minute.
+  uint32_t surfaceCacheExpirationTimeMS =
+    Preferences::GetUint("image.mem.surfacecache.min_expiration_ms", 60 * 1000);
+
+  // Maximum size of the surface cache, in kilobytes.
+  // The default is 100MB. (But we may override this for e.g. B2G.)
+  uint32_t surfaceCacheMaxSizeKB =
+    Preferences::GetUint("image.mem.surfacecache.max_size_kb", 100 * 1024);
+
+  // A knob determining the actual size of the surface cache. Currently the
+  // cache is (size of main memory) / (surface cache size factor) KB
+  // or (surface cache max size) KB, whichever is smaller. The formula
+  // may change in the future, though.
+  // The default value is 64, which yields a 64MB cache on a 4GB machine.
+  // The smallest machines we are likely to run this code on have 256MB
+  // of memory, which would yield a 4MB cache on the default setting.
+  uint32_t surfaceCacheSizeFactor =
+    Preferences::GetUint("image.mem.surfacecache.size_factor", 64);
+
+  // Clamp to avoid division by zero below.
+  surfaceCacheSizeFactor = max(surfaceCacheSizeFactor, 1u);
+
+  // Compute the size of the surface cache.
+  uint32_t proposedSize = PR_GetPhysicalMemorySize() / surfaceCacheSizeFactor;
+  uint32_t surfaceCacheSizeBytes = min(proposedSize, surfaceCacheMaxSizeKB * 1024);
+
+  // Create the surface cache singleton with the requested expiration time and
+  // size. Note that the size is a limit that the cache may not grow beyond, but
+  // we do not actually allocate any storage for surfaces at this time.
+  sInstance = new SurfaceCacheImpl(surfaceCacheExpirationTimeMS,
+                                   surfaceCacheSizeBytes);
+}
+
+/* static */ void
+SurfaceCache::Shutdown()
+{
+  MOZ_ASSERT(sInstance, "No singleton - was Shutdown() called twice?");
+  delete sInstance;
+  sInstance = nullptr;
+}
+
+/* static */ already_AddRefed<gfxDrawable>
+SurfaceCache::Lookup(const ImageKey    aImageKey,
+                     const SurfaceKey& aSurfaceKey)
+{
+  MOZ_ASSERT(sInstance, "Should be initialized");
+  MOZ_ASSERT(NS_IsMainThread());
+
+  return sInstance->Lookup(aImageKey, aSurfaceKey);
+}
+
+/* static */ void
+SurfaceCache::Insert(DrawTarget*       aTarget,
+                     const ImageKey    aImageKey,
+                     const SurfaceKey& aSurfaceKey)
+{
+  MOZ_ASSERT(sInstance, "Should be initialized");
+  MOZ_ASSERT(NS_IsMainThread());
+
+  Cost cost = ComputeCost(aSurfaceKey.Size());
+  return sInstance->Insert(aTarget, aSurfaceKey.Size(), cost, aImageKey, aSurfaceKey);
+}
+
+/* static */ bool
+SurfaceCache::CanHold(const nsIntSize& aSize)
+{
+  MOZ_ASSERT(sInstance, "Should be initialized");
+  MOZ_ASSERT(NS_IsMainThread());
+
+  Cost cost = ComputeCost(aSize);
+  return sInstance->CanHold(cost);
+}
+
+/* static */ void
+SurfaceCache::Discard(Image* aImageKey)
+{
+  MOZ_ASSERT(sInstance, "Should be initialized");
+  MOZ_ASSERT(NS_IsMainThread());
+
+  return sInstance->Discard(aImageKey);
+}
+
+} // namespace image
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/image/src/SurfaceCache.h
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * SurfaceCache is a service for caching temporary surfaces in imagelib.
+ */
+
+#ifndef MOZILLA_IMAGELIB_SURFACECACHE_H_
+#define MOZILLA_IMAGELIB_SURFACECACHE_H_
+
+#include "mozilla/HashFunctions.h"  // for HashGeneric and AddToHash
+#include "gfxPoint.h"               // for gfxSize
+#include "nsCOMPtr.h"               // for already_AddRefed
+#include "nsSize.h"                 // for nsIntSize
+#include "SVGImageContext.h"        // for SVGImageContext
+
+class gfxDrawable;
+
+namespace mozilla {
+
+namespace gfx {
+class DrawTarget;
+} // namespace gfx
+
+namespace image {
+
+class Image;
+
+/*
+ * ImageKey contains the information we need to look up all cached surfaces for
+ * a particular image.
+ */
+typedef Image* ImageKey;
+
+/*
+ * SurfaceKey contains the information we need to look up a specific cached
+ * surface. Together with an ImageKey, this uniquely identifies the surface.
+ *
+ * XXX(seth): Right now this is specialized to the needs of VectorImage. We'll
+ * generalize it in bug 919071.
+ */
+class SurfaceKey
+{
+public:
+  SurfaceKey(const nsIntSize aSize,
+             const gfxSize aScale,
+             const SVGImageContext* aSVGContext,
+             const float aAnimationTime,
+             const uint32_t aFlags)
+    : mSize(aSize)
+    , mScale(aScale)
+    , mSVGContextIsValid(aSVGContext != nullptr)
+    , mAnimationTime(aAnimationTime)
+    , mFlags(aFlags)
+  {
+    // XXX(seth): Would love to use Maybe<T> here, but see bug 913586.
+    if (mSVGContextIsValid)
+      mSVGContext = *aSVGContext;
+  }
+
+  bool operator==(const SurfaceKey& aOther) const
+  {
+    bool matchesSVGContext = aOther.mSVGContextIsValid == mSVGContextIsValid &&
+                             (!mSVGContextIsValid || aOther.mSVGContext == mSVGContext);
+    return aOther.mSize == mSize &&
+           aOther.mScale == mScale &&
+           matchesSVGContext &&
+           aOther.mAnimationTime == mAnimationTime &&
+           aOther.mFlags == mFlags;
+  }
+
+  uint32_t Hash() const
+  {
+    uint32_t hash = HashGeneric(mSize.width, mSize.height);
+    hash = AddToHash(hash, mScale.width, mScale.height);
+    hash = AddToHash(hash, mSVGContextIsValid, mSVGContext.Hash());
+    hash = AddToHash(hash, mAnimationTime, mFlags);
+    return hash;
+  }
+
+  nsIntSize Size() const { return mSize; }
+
+private:
+  nsIntSize       mSize;
+  gfxSize         mScale;
+  SVGImageContext mSVGContext;
+  bool            mSVGContextIsValid;
+  float           mAnimationTime;
+  uint32_t        mFlags;
+};
+
+/**
+ * SurfaceCache is an imagelib-global service that allows caching of temporary
+ * surfaces. Surfaces expire from the cache automatically if they go too long
+ * without being accessed.
+ *
+ * SurfaceCache is not thread-safe; it should only be accessed from the main
+ * thread.
+ */
+struct SurfaceCache
+{
+  /*
+   * Initialize static data. Called during imagelib module initialization.
+   */
+  static void Initialize();
+
+  /*
+   * Release static data. Called during imagelib module shutdown.
+   */
+  static void Shutdown();
+
+  /*
+   * Look up a surface in the cache.
+   *
+   * @param aImageKey    Key data identifying which image the surface belongs to.
+   * @param aSurfaceKey  Key data which uniquely identifies the requested surface.
+   *
+   * @return the requested surface, or nullptr if not found.
+   */
+  static already_AddRefed<gfxDrawable> Lookup(const ImageKey    aImageKey,
+                                              const SurfaceKey& aSurfaceKey);
+
+  /*
+   * Insert a surface into the cache. It is an error to call this function
+   * without first calling Lookup to verify that the surface is not already in
+   * the cache.
+   *
+   * @param aTarget      The new surface (in the form of a DrawTarget) to insert
+   *                     into the cache.
+   * @param aImageKey    Key data identifying which image the surface belongs to.
+   * @param aSurfaceKey  Key data which uniquely identifies the requested surface.
+   */
+  static void Insert(mozilla::gfx::DrawTarget* aTarget,
+                     const ImageKey            aImageKey,
+                     const SurfaceKey&         aSurfaceKey);
+
+  /*
+   * Checks if a surface of a given size could possibly be stored in the cache.
+   * If CanHold() returns false, Insert() will always fail to insert the
+   * surface, but the inverse is not true: Insert() may take more information
+   * into account than just image size when deciding whether to cache the
+   * surface, so Insert() may still fail even if CanHold() returns true.
+   *
+   * Use CanHold() to avoid the need to create a temporary surface when we know
+   * for sure the cache can't hold it.
+   *
+   * @param aSize  The dimensions of a surface in pixels.
+   *
+   * @return false if the surface cache can't hold a surface of that size.
+   */
+  static bool CanHold(const nsIntSize& aSize);
+
+  /*
+   * Evicts any cached surfaces associated with the given image from the cache.
+   * This MUST be called, at a minimum, when the image is destroyed. If
+   * another image were allocated at the same address it could result in
+   * subtle, difficult-to-reproduce bugs.
+   *
+   * @param aImageKey  The image which should be removed from the cache.
+   */
+  static void Discard(const ImageKey aImageKey);
+
+private:
+  virtual ~SurfaceCache() = 0;  // Forbid instantiation.
+};
+
+} // namespace image
+} // namespace mozilla
+
+#endif // MOZILLA_IMAGELIB_SURFACECACHE_H_
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -2,32 +2,34 @@
 /* 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 "VectorImage.h"
 
 #include "gfxContext.h"
 #include "gfxDrawable.h"
+#include "gfxPlatform.h"
 #include "gfxUtils.h"
 #include "imgDecoderObserver.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/SVGSVGElement.h"
 #include "nsIDOMEvent.h"
 #include "nsIPresShell.h"
 #include "nsIStreamListener.h"
 #include "nsMimeTypes.h"
 #include "nsPresContext.h"
 #include "nsRect.h"
 #include "nsStubDocumentObserver.h"
 #include "nsSVGEffects.h" // for nsSVGRenderingObserver
 #include "Orientation.h"
 #include "SVGDocumentWrapper.h"
 #include "nsIDOMEventListener.h"
+#include "SurfaceCache.h"
 
 namespace mozilla {
 
 using namespace dom;
 using namespace layers;
 
 namespace image {
 
@@ -311,16 +313,17 @@ VectorImage::VectorImage(imgStatusTracke
   mHasPendingInvalidation(false)
 {
   mStatusTrackerInit = new imgStatusTrackerInit(this, aStatusTracker);
 }
 
 VectorImage::~VectorImage()
 {
   CancelAllListeners();
+  SurfaceCache::Discard(this);
 }
 
 //------------------------------------------------------------------------------
 // Methods inherited from Image.h
 
 nsresult
 VectorImage::Init(const char* aMimeType,
                   uint32_t aFlags)
@@ -482,16 +485,19 @@ VectorImage::RequestRefresh(const mozill
   EvaluateAnimation();
 
   if (mHasPendingInvalidation && mStatusTracker) {
     // This method is called under the Tick() of an observing document's
     // refresh driver. We send out the following notifications here rather than
     // under WillRefresh() (which would be called by our own refresh driver) so
     // that we only send these notifications if we actually have a document
     // that is observing us.
+    // XXX(seth): We may need to duplicate this code so that non-animated images
+    // get handled correctly. See bug 922899.
+    SurfaceCache::Discard(this);
     mStatusTracker->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
     mStatusTracker->OnStopFrame();
   }
 
   mHasPendingInvalidation = false;
 }
 
 //******************************************************************************
@@ -671,16 +677,75 @@ VectorImage::GetFrame(uint32_t aWhichFra
 NS_IMETHODIMP
 VectorImage::GetImageContainer(LayerManager* aManager,
                                mozilla::layers::ImageContainer** _retval)
 {
   *_retval = nullptr;
   return NS_OK;
 }
 
+struct SVGDrawingParameters
+{
+  SVGDrawingParameters(gfxContext* aContext,
+                       GraphicsFilter aFilter,
+                       const gfxMatrix& aUserSpaceToImageSpace,
+                       const gfxRect& aFill,
+                       const nsIntRect& aSubimage,
+                       const nsIntSize& aViewportSize,
+                       const SVGImageContext* aSVGContext,
+                       float aAnimationTime,
+                       uint32_t aFlags)
+    : context(aContext)
+    , filter(aFilter)
+    , fill(aFill)
+    , viewportSize(aViewportSize)
+    , animationTime(aAnimationTime)
+    , svgContext(aSVGContext)
+    , flags(aFlags)
+  {
+    // gfxUtils::DrawPixelSnapped may rasterize this image to a temporary surface
+    // if we hit the tiling path. Unfortunately, the temporary surface isn't
+    // created at the size at which we'll ultimately draw, causing fuzzy output.
+    // To fix this we pre-apply the transform's scaling to the drawing parameters
+    // and remove the scaling from the transform, so the fact that temporary
+    // surfaces won't take the scaling into account doesn't matter. (Bug 600207.)
+    scale = aUserSpaceToImageSpace.ScaleFactors(true);
+    gfxPoint translation(aUserSpaceToImageSpace.GetTranslation());
+
+    // Remove the scaling from the transform.
+    gfxMatrix unscale;
+    unscale.Translate(gfxPoint(translation.x / scale.width,
+                               translation.y / scale.height));
+    unscale.Scale(1.0 / scale.width, 1.0 / scale.height);
+    unscale.Translate(-translation);
+    userSpaceToImageSpace = aUserSpaceToImageSpace * unscale;
+
+    // Rescale drawing parameters.
+    gfxIntSize drawableSize(aViewportSize.width / scale.width,
+                            aViewportSize.height / scale.height);
+    sourceRect = userSpaceToImageSpace.Transform(aFill);
+    imageRect = nsIntRect(0, 0, drawableSize.width, drawableSize.height);
+    subimage = gfxRect(aSubimage.x, aSubimage.y, aSubimage.width, aSubimage.height);
+    subimage.ScaleRoundOut(1.0 / scale.width, 1.0 / scale.height);
+  }
+
+  gfxContext* context;
+  GraphicsFilter filter;
+  gfxMatrix userSpaceToImageSpace;
+  gfxRect fill;
+  gfxRect subimage;
+  gfxRect sourceRect;
+  nsIntRect imageRect;
+  nsIntSize viewportSize;
+  gfxSize scale;
+  float animationTime;
+  const SVGImageContext* svgContext;
+  uint32_t flags;
+};
+
 //******************************************************************************
 /* [noscript] void draw(in gfxContext aContext,
  *                      in gfxGraphicsFilter aFilter,
  *                      [const] in gfxMatrix aUserSpaceToImageSpace,
  *                      [const] in gfxRect aFill,
  *                      [const] in nsIntRect aSubimage,
  *                      [const] in nsIntSize aViewportSize,
  *                      [const] in SVGImageContext aSVGContext,
@@ -711,68 +776,140 @@ VectorImage::Draw(gfxContext* aContext,
 
   if (mAnimationConsumers == 0 && mStatusTracker) {
     mStatusTracker->OnUnlockedDraw();
   }
 
   AutoRestore<bool> autoRestoreIsDrawing(mIsDrawing);
   mIsDrawing = true;
 
-  float time = aWhichFrame == FRAME_FIRST ? 0.0f
-                                          : mSVGDocumentWrapper->GetCurrentTime();
-  AutoSVGRenderingState autoSVGState(aSVGContext,
-                                     time,
+  float animTime = (aWhichFrame == FRAME_FIRST) ? 0.0f
+                                                : mSVGDocumentWrapper->GetCurrentTime();
+  AutoSVGRenderingState autoSVGState(aSVGContext, animTime,
                                      mSVGDocumentWrapper->GetRootSVGElem());
 
-  // gfxUtils::DrawPixelSnapped may rasterize this image to a temporary surface
-  // if we hit the tiling path. Unfortunately, the temporary surface isn't
-  // created at the size at which we'll ultimately draw, causing fuzzy output.
-  // To fix this we pre-apply the transform's scaling to the drawing parameters
-  // and remove the scaling from the transform, so the fact that temporary
-  // surfaces won't take the scaling into account doesn't matter. (Bug 600207.)
-  gfxSize scale(aUserSpaceToImageSpace.ScaleFactors(true));
-  gfxPoint translation(aUserSpaceToImageSpace.GetTranslation());
+  // Pack up the drawing parameters.
+  SVGDrawingParameters params(aContext, aFilter, aUserSpaceToImageSpace, aFill,
+                              aSubimage, aViewportSize, aSVGContext, animTime, aFlags);
+
+  // Check the cache.
+  nsRefPtr<gfxDrawable> drawable =
+    SurfaceCache::Lookup(ImageKey(this),
+                         SurfaceKey(params.imageRect.Size(), params.scale,
+                                    aSVGContext, animTime, aFlags));
 
-  // Remove the scaling from the transform.
-  gfxMatrix unscale;
-  unscale.Translate(gfxPoint(translation.x / scale.width,
-                             translation.y / scale.height));
-  unscale.Scale(1.0 / scale.width, 1.0 / scale.height);
-  unscale.Translate(-translation);
-  gfxMatrix unscaledTransform(aUserSpaceToImageSpace * unscale);
+  // Draw.
+  if (drawable) {
+    Show(drawable, params);
+  } else {
+    CreateDrawableAndShow(params);
+  }
 
-  mSVGDocumentWrapper->UpdateViewportBounds(aViewportSize);
+  return NS_OK;
+}
+
+void
+VectorImage::CreateDrawableAndShow(const SVGDrawingParameters& aParams)
+{
+  mSVGDocumentWrapper->UpdateViewportBounds(aParams.viewportSize);
   mSVGDocumentWrapper->FlushImageTransformInvalidation();
 
-  // Rescale drawing parameters.
-  gfxIntSize drawableSize(aViewportSize.width / scale.width,
-                          aViewportSize.height / scale.height);
-  gfxRect drawableSourceRect = unscaledTransform.Transform(aFill);
-  gfxRect drawableImageRect(0, 0, drawableSize.width, drawableSize.height);
-  gfxRect drawableSubimage(aSubimage.x, aSubimage.y,
-                           aSubimage.width, aSubimage.height);
-  drawableSubimage.ScaleRoundOut(1.0 / scale.width, 1.0 / scale.height);
-
   nsRefPtr<gfxDrawingCallback> cb =
     new SVGDrawingCallback(mSVGDocumentWrapper,
-                           nsIntRect(nsIntPoint(0, 0), aViewportSize),
-                           scale,
-                           aFlags);
+                           nsIntRect(nsIntPoint(0, 0), aParams.viewportSize),
+                           aParams.scale,
+                           aParams.flags);
+
+  nsRefPtr<gfxDrawable> svgDrawable = new gfxCallbackDrawable(cb, aParams.imageRect.Size());
+
+  // Refuse to cache animated images.
+  // XXX(seth): We may remove this restriction in bug 922893.
+  if (mHaveAnimations)
+    return Show(svgDrawable, aParams);
+
+  // If the image is too big to fit in the cache, don't go any further.
+  if (!SurfaceCache::CanHold(aParams.imageRect.Size()))
+    return Show(svgDrawable, aParams);
+
+  // Try to create an offscreen surface.
+  mozilla::RefPtr<mozilla::gfx::DrawTarget> target;
+  nsRefPtr<gfxContext> ctx;
+  nsRefPtr<gfxASurface> surface;
+
+  if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
+    target = gfxPlatform::GetPlatform()->
+      CreateOffscreenContentDrawTarget(aParams.imageRect.Size(), gfx::FORMAT_B8G8R8A8);
+
+    // XXX(seth): All of this ugliness (the backend check, |surface|, the
+    // GetThebesSurfaceForDrawTarget call) is needed because we can't use Moz2D
+    // for drawing in all cases yet. See bug 923341.
+    if (target) {
+      switch (target->GetType()) {
+        case mozilla::gfx::BACKEND_DIRECT2D:
+        case mozilla::gfx::BACKEND_DIRECT2D1_1:
+        case mozilla::gfx::BACKEND_SKIA:
+          // Can't cache on this backend.
+          return Show(svgDrawable, aParams);
 
-  nsRefPtr<gfxDrawable> drawable = new gfxCallbackDrawable(cb, drawableSize);
+        default:
+          surface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(target);
+          ctx = new gfxContext(target);
+      }
+    }
+  } else {
+    target = gfxPlatform::GetPlatform()->
+      CreateOffscreenCanvasDrawTarget(aParams.imageRect.Size(), gfx::FORMAT_B8G8R8A8);
+    surface = target ? gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(target)
+                     : nullptr;
+    ctx = surface ? new gfxContext(surface) : nullptr;
+  }
+
+  // If we couldn't create the draw target, it was probably because it would end
+  // up way too big. Generally it also wouldn't fit in the cache, but the prefs
+  // could be set such that the cache isn't the limiting factor. If we couldn't
+  // create the surface, we are on a platform that does not support
+  // GetThebesSurfaceForDrawTarget. This will be fixed in bug 923341.
+  if (!target || !surface)
+    return Show(svgDrawable, aParams);
 
-  gfxUtils::DrawPixelSnapped(aContext, drawable, unscaledTransform,
-                             drawableSubimage, drawableSourceRect,
-                             drawableImageRect, aFill,
-                             gfxImageFormatARGB32, aFilter, aFlags);
+  // Actually draw. (We use FILTER_NEAREST since we never scale here.)
+  gfxUtils::DrawPixelSnapped(ctx, svgDrawable, gfxMatrix(),
+                             aParams.imageRect, aParams.imageRect,
+                             aParams.imageRect, aParams.imageRect,
+                             gfxImageFormatARGB32,
+                             GraphicsFilter::FILTER_NEAREST, aParams.flags);
+
+  // Attempt to cache the resulting surface.
+  SurfaceCache::Insert(target,
+                       ImageKey(this),
+                       SurfaceKey(aParams.imageRect.Size(), aParams.scale,
+                                  aParams.svgContext, aParams.animationTime,
+                                  aParams.flags));
+
+  // Draw. Note that if SurfaceCache::Insert failed for whatever reason,
+  // then |target| is all that is keeping the pixel data alive, so we have
+  // to draw before returning from this function.
+  nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(surface, aParams.imageRect.Size());
+  Show(drawable, aParams);
+}
+
+
+void
+VectorImage::Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams)
+{
+  MOZ_ASSERT(aDrawable, "Should have a gfxDrawable by now");
+  gfxUtils::DrawPixelSnapped(aParams.context, aDrawable,
+                             aParams.userSpaceToImageSpace,
+                             aParams.subimage, aParams.sourceRect,
+                             aParams.imageRect, aParams.fill,
+                             gfxImageFormatARGB32,
+                             aParams.filter, aParams.flags);
 
   MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now");
   mRenderingObserver->ResumeHonoringInvalidations();
-
-  return NS_OK;
 }
 
 //******************************************************************************
 /* void requestDecode() */
 NS_IMETHODIMP
 VectorImage::RequestDecode()
 {
   // Nothing to do for SVG images
@@ -810,17 +947,17 @@ VectorImage::UnlockImage()
   return NS_OK;
 }
 
 //******************************************************************************
 /* void requestDiscard() */
 NS_IMETHODIMP
 VectorImage::RequestDiscard()
 {
-  // This method is for image-discarding, which only applies to RasterImages.
+  SurfaceCache::Discard(this);
   return NS_OK;
 }
 
 //******************************************************************************
 /* void resetAnimation (); */
 NS_IMETHODIMP
 VectorImage::ResetAnimation()
 {
--- a/image/src/VectorImage.h
+++ b/image/src/VectorImage.h
@@ -6,28 +6,30 @@
 #ifndef mozilla_imagelib_VectorImage_h_
 #define mozilla_imagelib_VectorImage_h_
 
 #include "Image.h"
 #include "nsIStreamListener.h"
 #include "mozilla/MemoryReporting.h"
 
 class nsIRequest;
+class gfxDrawable;
 
 namespace mozilla {
 namespace layers {
 class LayerManager;
 class ImageContainer;
 }
 namespace image {
 
-class SVGDocumentWrapper;
-class SVGRootRenderingObserver;
-class SVGLoadEventListener;
-class SVGParseCompleteListener;
+struct SVGDrawingParameters;
+class  SVGDocumentWrapper;
+class  SVGRootRenderingObserver;
+class  SVGLoadEventListener;
+class  SVGParseCompleteListener;
 
 class VectorImage : public ImageResource,
                     public nsIStreamListener
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
@@ -77,16 +79,19 @@ public:
 protected:
   VectorImage(imgStatusTracker* aStatusTracker = nullptr,
               ImageURL* aURI = nullptr);
 
   virtual nsresult StartAnimation();
   virtual nsresult StopAnimation();
   virtual bool     ShouldAnimate();
 
+  void CreateDrawableAndShow(const SVGDrawingParameters& aParams);
+  void Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams);
+
 private:
   void CancelAllListeners();
 
   nsRefPtr<SVGDocumentWrapper>       mSVGDocumentWrapper;
   nsRefPtr<SVGRootRenderingObserver> mRenderingObserver;
   nsRefPtr<SVGLoadEventListener>     mLoadEventListener;
   nsRefPtr<SVGParseCompleteListener> mParseCompleteListener;
 
--- a/image/src/moz.build
+++ b/image/src/moz.build
@@ -26,16 +26,17 @@ CPP_SOURCES += [
     'ImageFactory.cpp',
     'ImageMetadata.cpp',
     'ImageOps.cpp',
     'ImageWrapper.cpp',
     'OrientedImage.cpp',
     'RasterImage.cpp',
     'SVGDocumentWrapper.cpp',
     'ScriptedNotificationObserver.cpp',
+    'SurfaceCache.cpp',
     'VectorImage.cpp',
     'imgFrame.cpp',
     'imgLoader.cpp',
     'imgRequest.cpp',
     'imgRequestProxy.cpp',
     'imgStatusTracker.cpp',
     'imgTools.cpp',
 ]
new file mode 100644
--- /dev/null
+++ b/intl/uconv/src/UnifiedUCV.cpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsCP1252ToUnicode.cpp"
+#include "nsCharsetConverterManager.cpp"
+#include "nsConverterInputStream.cpp"
+#include "nsConverterOutputStream.cpp"
+#include "nsISO88591ToUnicode.cpp"
+#include "nsMacRomanToUnicode.cpp"
+#include "nsScriptableUConv.cpp"
+#include "nsTextToSubURI.cpp"
+#include "nsUConvModule.cpp"
+#include "nsUTF8ConverterService.cpp"
+#include "nsUTF8ToUnicode.cpp"
+#include "nsUnicodeToCP1252.cpp"
+#include "nsUnicodeToISO88591.cpp"
+#include "nsUnicodeToMacRoman.cpp"
+#include "nsUnicodeToUTF8.cpp"
+
--- a/intl/uconv/src/moz.build
+++ b/intl/uconv/src/moz.build
@@ -2,31 +2,17 @@
 # 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/.
 
 MODULE = 'uconv'
 
 CPP_SOURCES += [
-    'nsCP1252ToUnicode.cpp',
-    'nsCharsetConverterManager.cpp',
-    'nsConverterInputStream.cpp',
-    'nsConverterOutputStream.cpp',
-    'nsISO88591ToUnicode.cpp',
-    'nsMacRomanToUnicode.cpp',
-    'nsScriptableUConv.cpp',
-    'nsTextToSubURI.cpp',
-    'nsUConvModule.cpp',
-    'nsUTF8ConverterService.cpp',
-    'nsUTF8ToUnicode.cpp',
-    'nsUnicodeToCP1252.cpp',
-    'nsUnicodeToISO88591.cpp',
-    'nsUnicodeToMacRoman.cpp',
-    'nsUnicodeToUTF8.cpp',
+    'UnifiedUCV.cpp',
 ]
 
 if CONFIG['INTEL_ARCHITECTURE']:
     CPP_SOURCES += [
         'nsUTF8ToUnicodeSSE2.cpp',
     ]
 
 LIBRARY_NAME = 'uconv'
--- a/intl/uconv/src/nsCP1252ToUnicode.cpp
+++ b/intl/uconv/src/nsCP1252ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1252ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1252.ut"
-};
-
 nsresult
 nsCP1252ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1252.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/src/nsConverterInputStream.cpp
+++ b/intl/uconv/src/nsConverterInputStream.cpp
@@ -10,25 +10,26 @@
 #include "nsStreamUtils.h"
 #include "nsServiceManagerUtils.h"
 #include <algorithm>
 
 #define CONVERTER_BUFFER_SIZE 8192
 
 NS_IMPL_ISUPPORTS3(nsConverterInputStream, nsIConverterInputStream,
                    nsIUnicharInputStream, nsIUnicharLineInputStream)
-    
-static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
+
 
 NS_IMETHODIMP
 nsConverterInputStream::Init(nsIInputStream* aStream,
                              const char *aCharset,
                              int32_t aBufferSize,
                              PRUnichar aReplacementChar)
 {
+    static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
+
     if (!aCharset)
         aCharset = "UTF-8";
 
     nsresult rv;
 
     if (aBufferSize <=0) aBufferSize=CONVERTER_BUFFER_SIZE;
     
     // get the decoder
--- a/intl/uconv/src/nsConverterInputStream.h
+++ b/intl/uconv/src/nsConverterInputStream.h
@@ -1,13 +1,16 @@
 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifndef nsConverterInputStream_h
+#define nsConverterInputStream_h
+
 #include "nsIInputStream.h"
 #include "nsIConverterInputStream.h"
 #include "nsIUnicharLineInputStream.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsReadLine.h"
@@ -53,8 +56,11 @@ class nsConverterInputStream : public ns
     nsresult  mLastErrorCode;
     uint32_t  mLeftOverBytes;
     uint32_t  mUnicharDataOffset;
     uint32_t  mUnicharDataLength;
     PRUnichar mReplacementChar;
 
     nsAutoPtr<nsLineBuffer<PRUnichar> > mLineBuffer;
 };
+
+#endif
+
--- a/intl/uconv/src/nsISO88591ToUnicode.cpp
+++ b/intl/uconv/src/nsISO88591ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO88591ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1252.ut"
-};
-
 nsresult
 nsISO88591ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1252.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/src/nsMacRomanToUnicode.cpp
+++ b/intl/uconv/src/nsMacRomanToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacRomanToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_MacRomanMappingTable[] = {
-#include "macroman.ut"
-};
-
 nsresult
 nsMacRomanToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult)
 {
+  static const uint16_t g_MacRomanMappingTable[] = {
+#include "macroman.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_MacRomanMappingTable,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/src/nsUnicodeToCP1252.cpp
+++ b/intl/uconv/src/nsUnicodeToCP1252.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1252.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1252.uf"
-};
-
 nsresult
 nsUnicodeToCP1252Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult)
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1252.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/src/nsUnicodeToISO88591.cpp
+++ b/intl/uconv/src/nsUnicodeToISO88591.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88591.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-1.uf"
-};
-
 nsresult
 nsUnicodeToISO88591Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult)
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-1.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/src/nsUnicodeToMacRoman.cpp
+++ b/intl/uconv/src/nsUnicodeToMacRoman.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacRoman.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_MacRomanMappingTable[] = {
-#include "macroman.uf"
-};
-
 nsresult
 nsUnicodeToMacRomanConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult)
 {
+  static const uint16_t g_MacRomanMappingTable[] = {
+#include "macroman.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_MacRomanMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
new file mode 100644
--- /dev/null
+++ b/intl/uconv/ucvcn/UnifiedUCVCN.cpp
@@ -0,0 +1,13 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsGBKConvUtil.cpp"
+#include "nsGBKToUnicode.cpp"
+#include "nsHZToUnicode.cpp"
+#include "nsISO2022CNToUnicode.cpp"
+#include "nsUnicodeToGB2312V2.cpp"
+#include "nsUnicodeToGBK.cpp"
+#include "nsUnicodeToHZ.cpp"
+
--- a/intl/uconv/ucvcn/moz.build
+++ b/intl/uconv/ucvcn/moz.build
@@ -6,24 +6,17 @@
 
 MODULE = 'ucvcn'
 
 EXPORTS += [
     'nsUCvCnCID.h',
 ]
 
 CPP_SOURCES += [
-    'nsGBKConvUtil.cpp',
-    'nsGBKToUnicode.cpp',
-    'nsHZToUnicode.cpp',
-    'nsISO2022CNToUnicode.cpp',
-    'nsUnicodeToGB2312V2.cpp',
-    'nsUnicodeToGBK.cpp',
-    'nsUnicodeToHZ.cpp',
-    'nsUnicodeToISO2022CN.cpp',
+    'UnifiedUCVCN.cpp',
 ]
 
 LIBRARY_NAME = 'ucvcn_s'
 
 LIBXUL_LIBRARY = True
 
 LOCAL_INCLUDES += [
     '../util',
deleted file mode 100644
--- a/intl/uconv/ucvcn/nsUnicodeToISO2022CN.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
deleted file mode 100644
--- a/intl/uconv/ucvcn/nsUnicodeToISO2022CN.h
+++ /dev/null
@@ -1,4 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
new file mode 100644
--- /dev/null
+++ b/intl/uconv/ucvibm/UnifiedUCVIBM.cpp
@@ -0,0 +1,17 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsCP850ToUnicode.cpp"
+#include "nsCP852ToUnicode.cpp"
+#include "nsCP855ToUnicode.cpp"
+#include "nsCP857ToUnicode.cpp"
+#include "nsCP862ToUnicode.cpp"
+#include "nsCP864ToUnicode.cpp"
+#include "nsUnicodeToCP850.cpp"
+#include "nsUnicodeToCP852.cpp"
+#include "nsUnicodeToCP855.cpp"
+#include "nsUnicodeToCP857.cpp"
+#include "nsUnicodeToCP862.cpp"
+#include "nsUnicodeToCP864.cpp"
+
new file mode 100644
--- /dev/null
+++ b/intl/uconv/ucvibm/UnifiedUCVIBMOS2.cpp
@@ -0,0 +1,11 @@
+/* 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 "nsCP869ToUnicode.cpp"
+#include "nsUnicodeToCP869.cpp"
+#include "nsCP1125ToUnicode.cpp"
+#include "nsUnicodeToCP1125.cpp"
+#include "nsCP1131ToUnicode.cpp"
+#include "nsUnicodeToCP1131.cpp"
+
--- a/intl/uconv/ucvibm/moz.build
+++ b/intl/uconv/ucvibm/moz.build
@@ -6,38 +6,22 @@
 
 MODULE = 'ucvibm'
 
 EXPORTS += [
     'nsUCvIBMCID.h',
 ]
 
 CPP_SOURCES += [
-    'nsCP850ToUnicode.cpp',
-    'nsCP852ToUnicode.cpp',
-    'nsCP855ToUnicode.cpp',
-    'nsCP857ToUnicode.cpp',
-    'nsCP862ToUnicode.cpp',
-    'nsCP864ToUnicode.cpp',
-    'nsUnicodeToCP850.cpp',
-    'nsUnicodeToCP852.cpp',
-    'nsUnicodeToCP855.cpp',
-    'nsUnicodeToCP857.cpp',
-    'nsUnicodeToCP862.cpp',
-    'nsUnicodeToCP864.cpp',
+    'UnifiedUCVIBM.cpp',
 ]
 
 if CONFIG['OS_ARCH'] == 'OS2':
     CPP_SOURCES += [
-        'nsCP869ToUnicode.cpp',
-        'nsUnicodeToCP869.cpp',
-        'nsCP1125ToUnicode.cpp',
-        'nsUnicodeToCP1125.cpp',
-        'nsCP1131ToUnicode.cpp',
-        'nsUnicodeToCP1131.cpp',
+        'UnifiedUCVIBMOS2.cpp',
     ]
 
 LIBRARY_NAME = 'ucvibm_s'
 
 LIBXUL_LIBRARY = True
 
 LOCAL_INCLUDES += [
     '../util',
--- a/intl/uconv/ucvibm/nsCP1125ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP1125ToUnicode.cpp
@@ -3,22 +3,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1125ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1125.ut"
-};
-
 //----------------------------------------------------------------------
 // Class nsCP1125ToUnicode [implementation]
 
 nsresult
 nsCP1125ToUnicodeConstructor(nsISupports* aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1125.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvibm/nsCP1131ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP1131ToUnicode.cpp
@@ -3,22 +3,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1131ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1131.ut"
-};
-
 //----------------------------------------------------------------------
 // Class nsCP1131ToUnicode [implementation]
 
 nsresult
 nsCP1131ToUnicodeConstructor(nsISupports* aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1131.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvibm/nsCP850ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP850ToUnicode.cpp
@@ -18,22 +18,22 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsCP850ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp850.ut"
-};
-
 //----------------------------------------------------------------------
 // Class nsCP850ToUnicode [implementation]
 
 nsresult
 nsCP850ToUnicodeConstructor(nsISupports* aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp850.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvibm/nsCP852ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP852ToUnicode.cpp
@@ -18,20 +18,20 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsCP852ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp852.ut"
-};
-
 nsresult
 nsCP852ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp852.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsCP855ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP855ToUnicode.cpp
@@ -18,20 +18,20 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsCP855ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp855.ut"
-};
-
 nsresult
 nsCP855ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp855.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsCP857ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP857ToUnicode.cpp
@@ -18,20 +18,20 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsCP857ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp857.ut"
-};
-
 nsresult
 nsCP857ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp857.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsCP862ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP862ToUnicode.cpp
@@ -18,20 +18,20 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsCP862ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp862.ut"
-};
-
 nsresult
 nsCP862ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp862.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsCP864ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP864ToUnicode.cpp
@@ -18,20 +18,20 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsCP864ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp864.ut"
-};
-
 nsresult
 nsCP864ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp864.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsCP869ToUnicode.cpp
+++ b/intl/uconv/ucvibm/nsCP869ToUnicode.cpp
@@ -3,20 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP869ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp869.ut"
-};
-
 nsresult
 nsCP869ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp869.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP1125.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP1125.cpp
@@ -3,21 +3,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1125.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1125.uf"
-};
-
 nsresult
 nsUnicodeToCP1125Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1125.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset, 
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP1131.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP1131.cpp
@@ -3,21 +3,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1131.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1131.uf"
-};
-
 nsresult
 nsUnicodeToCP1131Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1131.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset, 
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP850.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP850.cpp
@@ -18,21 +18,21 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP850.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp850.uf"
-};
-
 nsresult
 nsUnicodeToCP850Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp850.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset, 
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP852.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP852.cpp
@@ -18,21 +18,21 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP852.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp852.uf"
-};
-
 nsresult
 nsUnicodeToCP852Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp852.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP855.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP855.cpp
@@ -18,21 +18,21 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP855.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp855.uf"
-};
-
 nsresult
 nsUnicodeToCP855Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp855.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP857.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP857.cpp
@@ -18,21 +18,21 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP857.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp857.uf"
-};
-
 nsresult
 nsUnicodeToCP857Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp857.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP862.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP862.cpp
@@ -18,21 +18,21 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP862.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp862.uf"
-};
-
 nsresult
 nsUnicodeToCP862Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp862.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP864.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP864.cpp
@@ -18,21 +18,21 @@
  */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP864.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp864.uf"
-};
-
 nsresult
 nsUnicodeToCP864Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp864.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvibm/nsUnicodeToCP869.cpp
+++ b/intl/uconv/ucvibm/nsUnicodeToCP869.cpp
@@ -3,21 +3,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP869.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp869.uf"
-};
-
 nsresult
 nsUnicodeToCP869Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp869.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
new file mode 100644
--- /dev/null
+++ b/intl/uconv/ucvja/UnifiedUCVJA.cpp
@@ -0,0 +1,11 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsJapaneseToUnicode.cpp"
+#include "nsUnicodeToEUCJP.cpp"
+#include "nsUnicodeToISO2022JP.cpp"
+#include "nsUnicodeToJISx0201.cpp"
+#include "nsUnicodeToSJIS.cpp"
+
--- a/intl/uconv/ucvja/moz.build
+++ b/intl/uconv/ucvja/moz.build
@@ -7,21 +7,17 @@
 MODULE = 'ucvja'
 
 EXPORTS += [
     'nsUCVJA2CID.h',
     'nsUCVJACID.h',
 ]
 
 CPP_SOURCES += [
-    'nsJapaneseToUnicode.cpp',
-    'nsUnicodeToEUCJP.cpp',
-    'nsUnicodeToISO2022JP.cpp',
-    'nsUnicodeToJISx0201.cpp',
-    'nsUnicodeToSJIS.cpp',
+    'UnifiedUCVJA.cpp',
 ]
 
 LIBRARY_NAME = 'ucvja_s'
 
 LIBXUL_LIBRARY = True
 
 LOCAL_INCLUDES += [
     '../util',
--- a/intl/uconv/ucvja/nsUnicodeToEUCJP.cpp
+++ b/intl/uconv/ucvja/nsUnicodeToEUCJP.cpp
@@ -12,39 +12,39 @@
 
 // Shift Table
 static const int16_t g0201ShiftOutTable[] =  {
         2,
         ShiftOutCell(u1ByteChar,         1, 0x00, 0x00, 0x00, 0x7F),
         ShiftOutCell(u1BytePrefix8EChar, 2, 0x00, 0xA1, 0x00, 0xDF)
 };
 
-#define SIZE_OF_TABLES 3
-static const uScanClassID gScanClassIDs[SIZE_OF_TABLES] = {
+#define SIZE_OF_EUCJP_TABLES 3
+static const uScanClassID gScanClassIDs[SIZE_OF_EUCJP_TABLES] = {
   u2BytesGRCharset,
   u2BytesGRCharset,
   uMultibytesCharset
 };
 
-static const int16_t *gShiftTables[SIZE_OF_TABLES] =  {
+static const int16_t *gShiftTables[SIZE_OF_EUCJP_TABLES] =  {
     0,
     0,
     g0201ShiftOutTable
 };
 
-static const uint16_t *gMappingTables[SIZE_OF_TABLES] = {
+static const uint16_t *gMappingTables[SIZE_OF_EUCJP_TABLES] = {
     g_uf0208Mapping,
     g_uf0208extMapping,
     g_uf0201Mapping
 };
 
 nsresult
 nsUnicodeToEUCJPConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult)
 {
-    return CreateMultiTableEncoder(SIZE_OF_TABLES,
+    return CreateMultiTableEncoder(SIZE_OF_EUCJP_TABLES,
                                    (uScanClassID*) gScanClassIDs,
                                    (uShiftOutTable**) gShiftTables, 
                                    (uMappingTable**) gMappingTables,
                                    3 /* max length = src * 3 */,
                                    aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvja/nsUnicodeToISO2022JP.cpp
+++ b/intl/uconv/ucvja/nsUnicodeToISO2022JP.cpp
@@ -44,26 +44,26 @@ 0x30ea,0x30eb,0x30ec,0x30ed,0x30ef,0x30f
 #define IS_MARU(u)   (0xff9f == (u))
 #define NIGORI_MODIFIER 1
 #define MARU_MODIFIER   2
 
 static const uint16_t g_ufAsciiMapping [] = {
   0x0001, 0x0004, 0x0005, 0x0008, 0x0000, 0x0000, 0x007F, 0x0000
 };
 
-#define SIZE_OF_TABLES 5
-static const uint16_t * g_ufMappingTables[SIZE_OF_TABLES] = {
+#define SIZE_OF_ISO2022JP_TABLES 5
+static const uint16_t * g_ufMappingTables[SIZE_OF_ISO2022JP_TABLES] = {
   g_ufAsciiMapping,             // ASCII           ISOREG 6
   g_uf0201GLMapping,            // JIS X 0201-1976 ISOREG 14
   g_uf0208Mapping,              // JIS X 0208-1983 ISOREG 87
   g_uf0208extMapping,           // JIS X 0208 - cp932 ext
   g_uf0208Mapping,              // JIS X 0208-1978 ISOREG 42
 };
 
-static const uScanClassID g_ufScanClassIDs[SIZE_OF_TABLES] = {
+static const uScanClassID g_ufScanClassIDs[SIZE_OF_ISO2022JP_TABLES] = {
   u1ByteCharset,                // ASCII           ISOREG 6
   u1ByteCharset,                // JIS X 0201-1976 ISOREG 14
   u2BytesCharset,               // JIS X 0208-1983 ISOREG 87
   u2BytesCharset,               // JIS X 0208- cp932 ext
   u2BytesCharset,               // JIS X 0208-1978 ISOREG 42
 };
 #define JIS_X_208_INDEX 2
 
@@ -206,26 +206,26 @@ NS_IMETHODIMP nsUnicodeToISO2022JP::Conv
   const PRUnichar * src = aSrc;
   const PRUnichar * srcEnd = aSrc + *aSrcLength;
   char * dest = aDest;
   char * destEnd = aDest + *aDestLength;
   int32_t bcr, bcw;
   int32_t i;
 
   while (src < srcEnd) {
-    for (i=0; i< SIZE_OF_TABLES ; i++) {
+    for (i=0; i< SIZE_OF_ISO2022JP_TABLES ; i++) {
       bcr = 1;
       bcw = destEnd - dest;
       res = nsUnicodeEncodeHelper::ConvertByTable(src, &bcr, dest, &bcw, 
                                       g_ufScanClassIDs[i], nullptr,
                                       (uMappingTable *) g_ufMappingTables[i]);
       if (res != NS_ERROR_UENC_NOMAPPING) break;
     }
 
-    if ( i>=  SIZE_OF_TABLES) {
+    if ( i>=  SIZE_OF_ISO2022JP_TABLES) {
       if (IS_HANKAKU(*src)) {
         bcr = srcEnd - src;
         bcw = destEnd - dest;
         res = ConvertHankaku(src, &bcr, dest, &bcw);
         dest += bcw;
         src += bcr;
         if (res == NS_OK) continue;
       } else {
new file mode 100644
--- /dev/null
+++ b/intl/uconv/ucvko/UnifiedUCVKO.cpp
@@ -0,0 +1,11 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsCP949ToUnicode.cpp"
+#include "nsISO2022KRToUnicode.cpp"
+#include "nsJohabToUnicode.cpp"
+#include "nsUnicodeToCP949.cpp"
+#include "nsUnicodeToJohab.cpp"
+
--- a/intl/uconv/ucvko/moz.build
+++ b/intl/uconv/ucvko/moz.build
@@ -6,21 +6,17 @@
 
 MODULE = 'ucvko'
 
 EXPORTS += [
     'nsUCvKOCID.h',
 ]
 
 CPP_SOURCES += [
-    'nsCP949ToUnicode.cpp',
-    'nsISO2022KRToUnicode.cpp',
-    'nsJohabToUnicode.cpp',
-    'nsUnicodeToCP949.cpp',
-    'nsUnicodeToJohab.cpp',
+    'UnifiedUCVKO.cpp',
 ]
 
 LIBRARY_NAME = 'ucvko_s'
 
 LIBXUL_LIBRARY = True
 
 LOCAL_INCLUDES += [
     '../util',
new file mode 100644
--- /dev/null
+++ b/intl/uconv/ucvlatin/UnifiedUCVLatin.cpp
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsARMSCII8ToUnicode.cpp"
+#include "nsAsciiToUnicode.cpp"
+#include "nsCP1250ToUnicode.cpp"
+#include "nsCP1251ToUnicode.cpp"
+#include "nsCP1253ToUnicode.cpp"
+#include "nsCP1254ToUnicode.cpp"
+#include "nsCP1255ToUnicode.cpp"
+#include "nsCP1256ToUnicode.cpp"
+#include "nsCP1257ToUnicode.cpp"
+#include "nsCP1258ToUnicode.cpp"
+#include "nsCP866ToUnicode.cpp"
+#include "nsCP874ToUnicode.cpp"
+#include "nsISO885910ToUnicode.cpp"
+#include "nsISO885911ToUnicode.cpp"
+#include "nsISO885913ToUnicode.cpp"
+#include "nsISO885914ToUnicode.cpp"
+#include "nsISO885915ToUnicode.cpp"
+#include "nsISO885916ToUnicode.cpp"
+#include "nsISO88592ToUnicode.cpp"
+#include "nsISO88593ToUnicode.cpp"
+#include "nsISO88594ToUnicode.cpp"
+#include "nsISO88595ToUnicode.cpp"
+#include "nsISO88596EToUnicode.cpp"
+#include "nsISO88596IToUnicode.cpp"
+#include "nsISO88596ToUnicode.cpp"
+#include "nsISO88597ToUnicode.cpp"
+#include "nsISO88598EToUnicode.cpp"
+#include "nsISO88598IToUnicode.cpp"
+#include "nsISO88598ToUnicode.cpp"
+#include "nsISO88599ToUnicode.cpp"
+#include "nsISOIR111ToUnicode.cpp"
+#include "nsKOI8RToUnicode.cpp"
+#include "nsKOI8UToUnicode.cpp"
+#include "nsMUTF7ToUnicode.cpp"
+#include "nsMacArabicToUnicode.cpp"
+#include "nsMacCEToUnicode.cpp"
+#include "nsMacCroatianToUnicode.cpp"
+#include "nsMacCyrillicToUnicode.cpp"
+#include "nsMacDevanagariToUnicode.cpp"
+#include "nsMacFarsiToUnicode.cpp"
+#include "nsMacGreekToUnicode.cpp"
+#include "nsMacGujaratiToUnicode.cpp"
+#include "nsMacGurmukhiToUnicode.cpp"
+#include "nsMacHebrewToUnicode.cpp"
+#include "nsMacIcelandicToUnicode.cpp"
+#include "nsMacRomanianToUnicode.cpp"
+#include "nsMacTurkishToUnicode.cpp"
+#include "nsT61ToUnicode.cpp"
+#include "nsTCVN5712ToUnicode.cpp"
+#include "nsTIS620ToUnicode.cpp"
+#include "nsUTF16ToUnicode.cpp"
+#include "nsUTF7ToUnicode.cpp"
+#include "nsUnicodeToARMSCII8.cpp"
+#include "nsUnicodeToAdobeEuro.cpp"
+#include "nsUnicodeToAscii.cpp"
+#include "nsUnicodeToCP1250.cpp"
+#include "nsUnicodeToCP1251.cpp"
+#include "nsUnicodeToCP1253.cpp"
+#include "nsUnicodeToCP1254.cpp"
+#include "nsUnicodeToCP1255.cpp"
+#include "nsUnicodeToCP1256.cpp"
+#include "nsUnicodeToCP1257.cpp"
+#include "nsUnicodeToCP1258.cpp"
+#include "nsUnicodeToCP866.cpp"
+#include "nsUnicodeToCP874.cpp"
+#include "nsUnicodeToISO885910.cpp"
+#include "nsUnicodeToISO885911.cpp"
+#include "nsUnicodeToISO885913.cpp"
+#include "nsUnicodeToISO885914.cpp"
+#include "nsUnicodeToISO885915.cpp"
+#include "nsUnicodeToISO885916.cpp"
+#include "nsUnicodeToISO88592.cpp"
+#include "nsUnicodeToISO88593.cpp"
+#include "nsUnicodeToISO88594.cpp"
+#include "nsUnicodeToISO88595.cpp"
+#include "nsUnicodeToISO88596.cpp"
+#include "nsUnicodeToISO88596E.cpp"
+#include "nsUnicodeToISO88596I.cpp"
+#include "nsUnicodeToISO88597.cpp"
+#include "nsUnicodeToISO88598.cpp"
+#include "nsUnicodeToISO88598E.cpp"
+#include "nsUnicodeToISO88598I.cpp"
+#include "nsUnicodeToISO88599.cpp"
+#include "nsUnicodeToISOIR111.cpp"
+#include "nsUnicodeToKOI8R.cpp"
+#include "nsUnicodeToKOI8U.cpp"
+#include "nsUnicodeToMUTF7.cpp"
+#include "nsUnicodeToMacArabic.cpp"
+#include "nsUnicodeToMacCE.cpp"
+#include "nsUnicodeToMacCroatian.cpp"
+#include "nsUnicodeToMacCyrillic.cpp"
+#include "nsUnicodeToMacDevanagari.cpp"
+#include "nsUnicodeToMacFarsi.cpp"
+#include "nsUnicodeToMacGreek.cpp"
+#include "nsUnicodeToMacGujarati.cpp"
+#include "nsUnicodeToMacGurmukhi.cpp"
+#include "nsUnicodeToMacHebrew.cpp"
+#include "nsUnicodeToMacIcelandic.cpp"
+#include "nsUnicodeToMacRomanian.cpp"
+#include "nsUnicodeToMacTurkish.cpp"
+#include "nsUnicodeToSymbol.cpp"
+#include "nsUnicodeToT61.cpp"
+#include "nsUnicodeToTCVN5712.cpp"
+#include "nsUnicodeToTIS620.cpp"
+#include "nsUnicodeToTSCII.cpp"
+#include "nsUnicodeToUTF16.cpp"
+#include "nsUnicodeToUTF7.cpp"
+#include "nsUnicodeToUserDefined.cpp"
+#include "nsUnicodeToVISCII.cpp"
+#include "nsUnicodeToVPS.cpp"
+#include "nsUnicodeToZapfDingbat.cpp"
+#include "nsUserDefinedToUnicode.cpp"
+#include "nsVISCIIToUnicode.cpp"
+#include "nsVPSToUnicode.cpp"
+
--- a/intl/uconv/ucvlatin/moz.build
+++ b/intl/uconv/ucvlatin/moz.build
@@ -6,130 +6,17 @@
 
 MODULE = 'ucvlatin'
 
 EXPORTS += [
     'nsUCvLatinCID.h',
 ]
 
 CPP_SOURCES += [
-    'nsARMSCII8ToUnicode.cpp',
-    'nsAsciiToUnicode.cpp',
-    'nsCP1250ToUnicode.cpp',
-    'nsCP1251ToUnicode.cpp',
-    'nsCP1253ToUnicode.cpp',
-    'nsCP1254ToUnicode.cpp',
-    'nsCP1255ToUnicode.cpp',
-    'nsCP1256ToUnicode.cpp',
-    'nsCP1257ToUnicode.cpp',
-    'nsCP1258ToUnicode.cpp',
-    'nsCP866ToUnicode.cpp',
-    'nsCP874ToUnicode.cpp',
-    'nsISO885910ToUnicode.cpp',
-    'nsISO885911ToUnicode.cpp',
-    'nsISO885913ToUnicode.cpp',
-    'nsISO885914ToUnicode.cpp',
-    'nsISO885915ToUnicode.cpp',
-    'nsISO885916ToUnicode.cpp',
-    'nsISO88592ToUnicode.cpp',
-    'nsISO88593ToUnicode.cpp',
-    'nsISO88594ToUnicode.cpp',
-    'nsISO88595ToUnicode.cpp',
-    'nsISO88596EToUnicode.cpp',
-    'nsISO88596IToUnicode.cpp',
-    'nsISO88596ToUnicode.cpp',
-    'nsISO88597ToUnicode.cpp',
-    'nsISO88598EToUnicode.cpp',
-    'nsISO88598IToUnicode.cpp',
-    'nsISO88598ToUnicode.cpp',
-    'nsISO88599ToUnicode.cpp',
-    'nsISOIR111ToUnicode.cpp',
-    'nsKOI8RToUnicode.cpp',
-    'nsKOI8UToUnicode.cpp',
-    'nsMUTF7ToUnicode.cpp',
-    'nsMacArabicToUnicode.cpp',
-    'nsMacCEToUnicode.cpp',
-    'nsMacCroatianToUnicode.cpp',
-    'nsMacCyrillicToUnicode.cpp',
-    'nsMacDevanagariToUnicode.cpp',
-    'nsMacFarsiToUnicode.cpp',
-    'nsMacGreekToUnicode.cpp',
-    'nsMacGujaratiToUnicode.cpp',
-    'nsMacGurmukhiToUnicode.cpp',
-    'nsMacHebrewToUnicode.cpp',
-    'nsMacIcelandicToUnicode.cpp',
-    'nsMacRomanianToUnicode.cpp',
-    'nsMacTurkishToUnicode.cpp',
-    'nsT61ToUnicode.cpp',
-    'nsTCVN5712ToUnicode.cpp',
-    'nsTIS620ToUnicode.cpp',
-    'nsUTF16ToUnicode.cpp',
-    'nsUTF7ToUnicode.cpp',
-    'nsUnicodeToARMSCII8.cpp',
-    'nsUnicodeToAdobeEuro.cpp',
-    'nsUnicodeToAscii.cpp',
-    'nsUnicodeToCP1250.cpp',
-    'nsUnicodeToCP1251.cpp',
-    'nsUnicodeToCP1253.cpp',
-    'nsUnicodeToCP1254.cpp',
-    'nsUnicodeToCP1255.cpp',
-    'nsUnicodeToCP1256.cpp',
-    'nsUnicodeToCP1257.cpp',
-    'nsUnicodeToCP1258.cpp',
-    'nsUnicodeToCP866.cpp',
-    'nsUnicodeToCP874.cpp',
-    'nsUnicodeToISO885910.cpp',
-    'nsUnicodeToISO885911.cpp',
-    'nsUnicodeToISO885913.cpp',
-    'nsUnicodeToISO885914.cpp',
-    'nsUnicodeToISO885915.cpp',
-    'nsUnicodeToISO885916.cpp',
-    'nsUnicodeToISO88592.cpp',
-    'nsUnicodeToISO88593.cpp',
-    'nsUnicodeToISO88594.cpp',
-    'nsUnicodeToISO88595.cpp',
-    'nsUnicodeToISO88596.cpp',
-    'nsUnicodeToISO88596E.cpp',
-    'nsUnicodeToISO88596I.cpp',
-    'nsUnicodeToISO88597.cpp',
-    'nsUnicodeToISO88598.cpp',
-    'nsUnicodeToISO88598E.cpp',
-    'nsUnicodeToISO88598I.cpp',
-    'nsUnicodeToISO88599.cpp',
-    'nsUnicodeToISOIR111.cpp',
-    'nsUnicodeToKOI8R.cpp',
-    'nsUnicodeToKOI8U.cpp',
-    'nsUnicodeToMUTF7.cpp',
-    'nsUnicodeToMacArabic.cpp',
-    'nsUnicodeToMacCE.cpp',
-    'nsUnicodeToMacCroatian.cpp',
-    'nsUnicodeToMacCyrillic.cpp',
-    'nsUnicodeToMacDevanagari.cpp',
-    'nsUnicodeToMacFarsi.cpp',
-    'nsUnicodeToMacGreek.cpp',
-    'nsUnicodeToMacGujarati.cpp',
-    'nsUnicodeToMacGurmukhi.cpp',
-    'nsUnicodeToMacHebrew.cpp',
-    'nsUnicodeToMacIcelandic.cpp',
-    'nsUnicodeToMacRomanian.cpp',
-    'nsUnicodeToMacTurkish.cpp',
-    'nsUnicodeToSymbol.cpp',
-    'nsUnicodeToT61.cpp',
-    'nsUnicodeToTCVN5712.cpp',
-    'nsUnicodeToTIS620.cpp',
-    'nsUnicodeToTSCII.cpp',
-    'nsUnicodeToUTF16.cpp',
-    'nsUnicodeToUTF7.cpp',
-    'nsUnicodeToUserDefined.cpp',
-    'nsUnicodeToVISCII.cpp',
-    'nsUnicodeToVPS.cpp',
-    'nsUnicodeToZapfDingbat.cpp',
-    'nsUserDefinedToUnicode.cpp',
-    'nsVISCIIToUnicode.cpp',
-    'nsVPSToUnicode.cpp',
+    'UnifiedUCVLatin.cpp',
 ]
 
 LIBRARY_NAME = 'ucvlatin_s'
 
 LIBXUL_LIBRARY = True
 
 LOCAL_INCLUDES += [
     '../src',
--- a/intl/uconv/ucvlatin/nsARMSCII8ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsARMSCII8ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsARMSCII8ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "armscii.ut"
-};
-
 nsresult
 nsARMSCII8ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "armscii.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsAsciiToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsAsciiToUnicode.cpp
@@ -7,19 +7,19 @@
 #include "nsAsciiToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
 // use iso-8859-1 decoder to interpret us-ascii. Some websites are mistakenly 
 // labeled as us-ascii for iso-8859-1. Be generous here should be fine. 
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1252.ut"
-};
-
 nsresult
 nsAsciiToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1252.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsCP1250ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP1250ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1250ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1250.ut"
-};
-
 nsresult
 nsCP1250ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1250.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsCP1251ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP1251ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1251ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1251.ut"
-};
-
 nsresult
 nsCP1251ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1251.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsCP1253ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP1253ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1253ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1253.ut"
-};
-
 nsresult
 nsCP1253ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1253.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsCP1254ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP1254ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1254ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1254.ut"
-};
-
 nsresult
 nsCP1254ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1254.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsCP1255ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP1255ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1255ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1255.ut"
-};
-
 nsresult
 nsCP1255ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1255.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsCP1256ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP1256ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1256ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1256.ut"
-};
-
 nsresult
 nsCP1256ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1256.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsCP1257ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP1257ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1257ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1257.ut"
-};
-
 nsresult
 nsCP1257ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1257.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsCP1258ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP1258ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP1258ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp1258.ut"
-};
-
 nsresult
 nsCP1258ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp1258.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsCP866ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP866ToUnicode.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP866ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp866.ut"
-};
-
 nsresult
 nsCP866ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp866.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
 
--- a/intl/uconv/ucvlatin/nsCP874ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsCP874ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsCP874ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "cp874.ut"
-};
-
 nsresult
 nsCP874ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "cp874.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsISO885910ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO885910ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO885910ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-10.ut"
-};
-
 nsresult
 nsISO885910ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-10.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsISO885913ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO885913ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO885913ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-13.ut"
-};
-
 nsresult
 nsISO885913ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-13.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsISO885914ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO885914ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO885914ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-14.ut"
-};
-
 nsresult
 nsISO885914ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-14.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsISO885915ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO885915ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO885915ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-15.ut"
-};
-
 nsresult
 nsISO885915ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-15.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsISO885916ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO885916ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO885916ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-16.ut"
-};
-
 nsresult
 nsISO885916ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-16.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsISO88592ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO88592ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO88592ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-2.ut"
-};
-
 nsresult
 nsISO88592ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-2.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsISO88593ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO88593ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO88593ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-3.ut"
-};
-
 nsresult
 nsISO88593ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-3.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsISO88594ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO88594ToUnicode.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO88594ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-4.ut"
-};
-
 nsresult
 nsISO88594ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-4.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
 
--- a/intl/uconv/ucvlatin/nsISO88595ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO88595ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO88595ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-5.ut"
-};
-
 nsresult
 nsISO88595ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-5.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsISO88596ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO88596ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO88596ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-6.ut"
-};
-
 nsresult
 nsISO88596ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-6.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsISO88597ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO88597ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO88597ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-7.ut"
-};
-
 nsresult
 nsISO88597ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-7.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsISO88598ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISO88598ToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISO88598ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "8859-8.ut"
-};
-
 nsresult
 nsISO88598ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "8859-8.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsISOIR111ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsISOIR111ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsISOIR111ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "iso-ir-111.ut"
-};
-
 nsresult
 nsISOIR111ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "iso-ir-111.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsKOI8RToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsKOI8RToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsKOI8RToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "koi8r.ut"
-};
-
 nsresult
 nsKOI8RToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "koi8r.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsKOI8UToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsKOI8UToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsKOI8UToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "koi8u.ut"
-};
-
 nsresult
 nsKOI8UToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "koi8u.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacArabicToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacArabicToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacArabicToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "macarabic.ut"
-};
-
 nsresult
 nsMacArabicToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+   static const uint16_t g_utMappingTable[] = {
+#include "macarabic.ut"
+   };
+
    return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                                aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacCEToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacCEToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacCEToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_MacCEMappingTable[] = {
-#include "macce.ut"
-};
-
 nsresult
 nsMacCEToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_MacCEMappingTable[] = {
+#include "macce.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_MacCEMappingTable,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsMacCroatianToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacCroatianToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacCroatianToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "maccroat.ut"
-};
-
 nsresult
 nsMacCroatianToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "maccroat.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsMacCyrillicToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacCyrillicToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacCyrillicToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "maccyril.ut"
-};
-
 nsresult
 nsMacCyrillicToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "maccyril.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsMacDevanagariToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacDevanagariToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacDevanagariToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "macdevanaga.ut"
-};
-
 nsresult
 nsMacDevanagariToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                     void **aResult) 
 {
+   static const uint16_t g_utMappingTable[] = {
+#include "macdevanaga.ut"
+   };
+
    return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                                aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacFarsiToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacFarsiToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacFarsiToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "macfarsi.ut"
-};
-
 nsresult
 nsMacFarsiToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+   static const uint16_t g_utMappingTable[] = {
+#include "macfarsi.ut"
+   };
+
    return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                                aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacGreekToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacGreekToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacGreekToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_MacGreekMappingTable[] = {
-#include "macgreek.ut"
-};
-
 nsresult
 nsMacGreekToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_MacGreekMappingTable[] = {
+#include "macgreek.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_MacGreekMappingTable,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsMacGujaratiToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacGujaratiToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacGujaratiToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "macgujarati.ut"
-};
-
 nsresult
 nsMacGujaratiToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+   static const uint16_t g_utMappingTable[] = {
+#include "macgujarati.ut"
+   };
+
    return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                                aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacGurmukhiToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacGurmukhiToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacGurmukhiToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "macgurmukhi.ut"
-};
-
 nsresult
 nsMacGurmukhiToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+   static const uint16_t g_utMappingTable[] = {
+#include "macgurmukhi.ut"
+   };
+
    return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                                aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacHebrewToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacHebrewToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacHebrewToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "machebrew.ut"
-};
-
 nsresult
 nsMacHebrewToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+   static const uint16_t g_utMappingTable[] = {
+#include "machebrew.ut"
+   };
+
    return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                                aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacIcelandicToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacIcelandicToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacIcelandicToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "macicela.ut"
-};
-
 nsresult
 nsMacIcelandicToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                    void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "macicela.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacRomanianToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacRomanianToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacRomanianToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "macro.ut"
-};
-
 nsresult
 nsMacRomanianToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "macro.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsMacTurkishToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsMacTurkishToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsMacTurkishToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_MacTurkishMappingTable[] = {
-#include "macturki.ut"
-};
-
 nsresult
 nsMacTurkishToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                  void **aResult) 
 {
+  static const uint16_t g_MacTurkishMappingTable[] = {
+#include "macturki.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_MacTurkishMappingTable,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsT61ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsT61ToUnicode.cpp
@@ -4,30 +4,29 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsT61ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_T61MappingTable[] = {
-#include "t61.ut"
-};
-
-
-static const int16_t g_T61ShiftInTable[] =  {
-    3,  
-    ShiftInCell(u1ByteChar,   1, 0x00, 0xBF),
-    ShiftInCell(u1ByteChar,   1, 0xD0, 0xFF),
-    ShiftInCell(u2BytesChar,  2, 0xC0, 0xCF)
-};
-
 nsresult
 nsT61ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                           void **aResult) 
 {
+  static const uint16_t g_T61MappingTable[] = {
+#include "t61.ut"
+  };
+
+  static const int16_t g_T61ShiftInTable[] =  {
+      3,  
+      ShiftInCell(u1ByteChar,   1, 0x00, 0xBF),
+      ShiftInCell(u1ByteChar,   1, 0xD0, 0xFF),
+      ShiftInCell(u2BytesChar,  2, 0xC0, 0xCF)
+  };
+
   return CreateTableDecoder(uMultibytesCharset,
                             (uShiftInTable*) &g_T61ShiftInTable, 
                             (uMappingTable*) &g_T61MappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsTCVN5712ToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsTCVN5712ToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsTCVN5712ToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "tcvn5712.ut"
-};
-
 nsresult
 nsTCVN5712ToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "tcvn5712.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToARMSCII8.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToARMSCII8.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToARMSCII8.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "armscii.uf"
-};
-
 nsresult
 nsUnicodeToARMSCII8Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "armscii.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToAdobeEuro.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToAdobeEuro.cpp
@@ -4,23 +4,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToAdobeEuro.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-/* "adobeeuro.uf" was generated like this:
- * % echo '0xA4    0x20AC  #    EURO CURRENCY SIGN' | ./umaptable -uf >adobeeuro.uf
- */
-#include "adobeeuro.uf"
-};
-
 nsresult
 nsUnicodeToAdobeEuroConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+  /* "adobeeuro.uf" was generated like this:
+   * % echo '0xA4    0x20AC  #    EURO CURRENCY SIGN' | ./umaptable -uf >adobeeuro.uf
+   */
+#include "adobeeuro.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToAscii.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToAscii.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToAscii.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-  0x0001, 0x0004, 0x0005, 0x0008, 0x0000, 0x0000, 0x007F, 0x0000
-};
-
 nsresult
 nsUnicodeToAsciiConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+    0x0001, 0x0004, 0x0005, 0x0008, 0x0000, 0x0000, 0x007F, 0x0000
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP1250.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP1250.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1250.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1250.uf"
-};
-
 nsresult
 nsUnicodeToCP1250Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1250.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP1251.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP1251.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1251.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1251.uf"
-};
-
 nsresult
 nsUnicodeToCP1251Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1251.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP1253.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP1253.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1253.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1253.uf"
-};
-
 nsresult
 nsUnicodeToCP1253Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1253.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP1254.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP1254.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1254.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1254.uf"
-};
-
 nsresult
 nsUnicodeToCP1254Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1254.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP1255.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP1255.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1255.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1255.uf"
-};
-
 nsresult
 nsUnicodeToCP1255Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1255.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP1256.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP1256.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1256.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1256.uf"
-};
-
 nsresult
 nsUnicodeToCP1256Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1256.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP1257.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP1257.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1257.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1257.uf"
-};
-
 nsresult
 nsUnicodeToCP1257Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1257.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP1258.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP1258.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP1258.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp1258.uf"
-};
-
 nsresult
 nsUnicodeToCP1258Constructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp1258.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP866.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP866.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP866.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp866.uf"
-};
-
 nsresult
 nsUnicodeToCP866Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp866.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToCP874.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToCP874.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToCP874.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "cp874.uf"
-};
-
 nsresult
 nsUnicodeToCP874Constructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "cp874.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToISO885910.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO885910.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO885910.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-10.uf"
-};
-
 nsresult
 nsUnicodeToISO885910Constructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-10.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO885911.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO885911.cpp
@@ -5,21 +5,21 @@
 
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO885911.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-11.uf"
-};
-
 nsresult
 nsUnicodeToISO885911Constructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-11.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO885913.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO885913.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO885913.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-13.uf"
-};
-
 nsresult
 nsUnicodeToISO885913Constructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-13.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToISO885914.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO885914.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO885914.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-14.uf"
-};
-
 nsresult
 nsUnicodeToISO885914Constructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-14.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO885915.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO885915.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO885915.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-15.uf"
-};
-
 nsresult
 nsUnicodeToISO885915Constructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-15.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO885916.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO885916.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO885916.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-16.uf"
-};
-
 nsresult
 nsUnicodeToISO885916Constructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-16.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO88592.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO88592.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88592.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-2.uf"
-};
-
 nsresult
 nsUnicodeToISO88592Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-2.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToISO88593.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO88593.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88593.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-3.uf"
-};
-
 nsresult
 nsUnicodeToISO88593Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-3.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToISO88594.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO88594.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88594.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-4.uf"
-};
-
 nsresult
 nsUnicodeToISO88594Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-4.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO88595.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO88595.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88595.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-5.uf"
-};
-
 nsresult
 nsUnicodeToISO88595Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-5.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO88596.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO88596.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88596.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-6.uf"
-};
-
 nsresult
 nsUnicodeToISO88596Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-6.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToISO88597.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO88597.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88597.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-7.uf"
-};
-
 nsresult
 nsUnicodeToISO88597Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-7.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO88598.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO88598.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88598.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-8.uf"
-};
-
 nsresult
 nsUnicodeToISO88598Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-8.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToISO88599.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISO88599.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISO88599.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "8859-9.uf"
-};
-
 nsresult
 nsUnicodeToISO88599Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "8859-9.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToISOIR111.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToISOIR111.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToISOIR111.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "iso-ir-111.uf"
-};
-
 nsresult
 nsUnicodeToISOIR111Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "iso-ir-111.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToKOI8R.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToKOI8R.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToKOI8R.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "koi8r.uf"
-};
-
 nsresult
 nsUnicodeToKOI8RConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "koi8r.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToKOI8U.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToKOI8U.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToKOI8U.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "koi8u.uf"
-};
-
 nsresult
 nsUnicodeToKOI8UConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "koi8u.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToMacArabic.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacArabic.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacArabic.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "macarabic.uf"
-};
-
 nsresult
 nsUnicodeToMacArabicConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "macarabic.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToMacCE.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacCE.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacCE.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_MacCEMappingTable[] = {
-#include "macce.uf"
-};
-
 nsresult
 nsUnicodeToMacCEConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult) 
 {
+  static const uint16_t g_MacCEMappingTable[] = {
+#include "macce.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_MacCEMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToMacCroatian.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacCroatian.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacCroatian.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "maccroat.uf"
-};
-
 nsresult
 nsUnicodeToMacCroatianConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "maccroat.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToMacCyrillic.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacCyrillic.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacCyrillic.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "maccyril.uf"
-};
-
 nsresult
 nsUnicodeToMacCyrillicConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "maccyril.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToMacDevanagari.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacDevanagari.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacDevanagari.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "macdevanaga.uf"
-};
-
 nsresult
 nsUnicodeToMacDevanagariConstructor(nsISupports *aOuter, REFNSIID aIID,
                                     void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "macdevanaga.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToMacFarsi.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacFarsi.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacFarsi.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "macfarsi.uf"
-};
-
 nsresult
 nsUnicodeToMacFarsiConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "macfarsi.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToMacGreek.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacGreek.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacGreek.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_MacGreekMappingTable[] = {
-#include "macgreek.uf"
-};
-
 nsresult
 nsUnicodeToMacGreekConstructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_MacGreekMappingTable[] = {
+#include "macgreek.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_MacGreekMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToMacGujarati.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacGujarati.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacGujarati.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "macgujarati.uf"
-};
-
 nsresult
 nsUnicodeToMacGujaratiConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "macgujarati.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToMacGurmukhi.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacGurmukhi.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacGurmukhi.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "macgurmukhi.uf"
-};
-
 nsresult
 nsUnicodeToMacGurmukhiConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "macgurmukhi.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToMacHebrew.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacHebrew.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacHebrew.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "machebrew.uf"
-};
-
 nsresult
 nsUnicodeToMacHebrewConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "machebrew.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToMacIcelandic.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacIcelandic.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacIcelandic.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "macicela.uf"
-};
-
 nsresult
 nsUnicodeToMacIcelandicConstructor(nsISupports *aOuter, REFNSIID aIID,
                                    void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "macicela.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToMacRomanian.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacRomanian.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacRomanian.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "macro.uf"
-};
-
 nsresult
 nsUnicodeToMacRomanianConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "macro.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToMacTurkish.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToMacTurkish.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToMacTurkish.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_MacTurkishMappingTable[] = {
-#include "macturki.uf"
-};
-
 nsresult
 nsUnicodeToMacTurkishConstructor(nsISupports *aOuter, REFNSIID aIID,
                                  void **aResult) 
 {
+  static const uint16_t g_MacTurkishMappingTable[] = {
+#include "macturki.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_MacTurkishMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToSymbol.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToSymbol.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToSymbol.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "adobesymbol.uf"
-};
-
 nsresult
 nsUnicodeToSymbolConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "adobesymbol.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToT61.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToT61.cpp
@@ -4,27 +4,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToT61.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_T61MappingTable[] = {
-#include "t61.uf"
-};
-
-static const int16_t g_T61ShiftOutTable[] =  {
-    3,  
-    ShiftOutCell(u1ByteChar,   1, 0x00, 0x00, 0x00, 0xBF),
-    ShiftOutCell(u1ByteChar,   1, 0x00, 0xD0, 0x00, 0xFF),
-    ShiftOutCell(u2BytesChar,  2, 0xC0, 0x41, 0xCF, 0x7A)
-};
 nsresult
 nsUnicodeToT61Constructor(nsISupports *aOuter, REFNSIID aIID,
                           void **aResult) 
 {
+  static const uint16_t g_T61MappingTable[] = {
+#include "t61.uf"
+  };
+
+  static const int16_t g_T61ShiftOutTable[] =  {
+      3,  
+      ShiftOutCell(u1ByteChar,   1, 0x00, 0x00, 0x00, 0xBF),
+      ShiftOutCell(u1ByteChar,   1, 0x00, 0xD0, 0x00, 0xFF),
+      ShiftOutCell(u2BytesChar,  2, 0xC0, 0x41, 0xCF, 0x7A)
+  };
+
   return CreateTableEncoder(uMultibytesCharset,
                             (uShiftOutTable*) &g_T61ShiftOutTable, 
                             (uMappingTable*) &g_T61MappingTable, 2,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToTCVN5712.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToTCVN5712.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToTCVN5712.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "tcvn5712.uf"
-};
-
 nsresult
 nsUnicodeToTCVN5712Constructor(nsISupports *aOuter, REFNSIID aIID,
                                void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "tcvn5712.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToTIS620.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToTIS620.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToTIS620.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "tis620.uf"
-};
-
 nsresult
 nsUnicodeToTIS620Constructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "tis620.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToUserDefined.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToUserDefined.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToUserDefined.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "userdefined.uf"
-};
-
 nsresult
 nsUnicodeToUserDefinedConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "userdefined.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsUnicodeToVISCII.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToVISCII.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToVISCII.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "viscii.uf"
-};
-
 nsresult
 nsUnicodeToVISCIIConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "viscii.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToVPS.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToVPS.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToVPS.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "vps.uf"
-};
-
 nsresult
 nsUnicodeToVPSConstructor(nsISupports *aOuter, REFNSIID aIID,
                           void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "vps.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUnicodeToZapfDingbat.cpp
+++ b/intl/uconv/ucvlatin/nsUnicodeToZapfDingbat.cpp
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUnicodeToZapfDingbat.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_ufMappingTable[] = {
-#include "adobezingbat.uf"
-};
-
 nsresult
 nsUnicodeToZapfDingbatConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_ufMappingTable[] = {
+#include "adobezingbat.uf"
+  };
+
   return CreateTableEncoder(u1ByteCharset,
                             (uMappingTable*) &g_ufMappingTable, 1,
                             aOuter, aIID, aResult);
 }
 
--- a/intl/uconv/ucvlatin/nsUserDefinedToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsUserDefinedToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsUCConstructors.h"
 #include "nsUserDefinedToUnicode.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "userdefined.ut"
-};
-
 nsresult
 nsUserDefinedToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                   void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "userdefined.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsVISCIIToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsVISCIIToUnicode.cpp
@@ -4,19 +4,19 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsVISCIIToUnicode.h"
 #include "nsUCConstructors.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "viscii.ut"
-};
-
 nsresult
 nsVISCIIToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                              void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "viscii.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvlatin/nsVPSToUnicode.cpp
+++ b/intl/uconv/ucvlatin/nsVPSToUnicode.cpp
@@ -4,20 +4,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsVPSToUnicode.h"
 #include "nsUCConstructors.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uint16_t g_utMappingTable[] = {
-#include "vps.ut"
-};
-
 nsresult
 nsVPSToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                           void **aResult) 
 {
+  static const uint16_t g_utMappingTable[] = {
+#include "vps.ut"
+  };
+
   return CreateOneByteDecoder((uMappingTable*) &g_utMappingTable,
                               aOuter, aIID, aResult);
 }
 
new file mode 100644
--- /dev/null
+++ b/intl/uconv/ucvtw/UnifiedUCVTW.cpp
@@ -0,0 +1,11 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsBIG5HKSCSToUnicode.cpp"
+#include "nsBIG5ToUnicode.cpp"
+#include "nsUnicodeToBIG5.cpp"
+#include "nsUnicodeToBIG5HKSCS.cpp"
+#include "nsUnicodeToHKSCS.cpp"
+
--- a/intl/uconv/ucvtw/moz.build
+++ b/intl/uconv/ucvtw/moz.build
@@ -6,21 +6,17 @@
 
 MODULE = 'ucvtw'
 
 EXPORTS += [
     'nsUCvTWCID.h',
 ]
 
 CPP_SOURCES += [
-    'nsBIG5HKSCSToUnicode.cpp',
-    'nsBIG5ToUnicode.cpp',
-    'nsUnicodeToBIG5.cpp',
-    'nsUnicodeToBIG5HKSCS.cpp',
-    'nsUnicodeToHKSCS.cpp',
+    'UnifiedUCVTW.cpp',
 ]
 
 LIBRARY_NAME = 'ucvtw_s'
 
 LIBXUL_LIBRARY = True
 
 LOCAL_INCLUDES += [
     '../util',
--- a/intl/uconv/ucvtw/nsUnicodeToBIG5HKSCS.cpp
+++ b/intl/uconv/ucvtw/nsUnicodeToBIG5HKSCS.cpp
@@ -5,33 +5,32 @@
 
 #include "nsUnicodeToBIG5HKSCS.h"
 #include "nsUCvTWDll.h"
 #include "nsUCConstructors.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-
-static const uint16_t *g_Big5HKSCSMappingTable[] = {
-  g_ASCIIMappingTable,
-  g_ufBig5Mapping,
-  g_ufBig5HKSCSMapping
-};
-
-static const uScanClassID g_Big5HKSCSScanClassIDs[] =  {
-  u1ByteCharset,
-  u2BytesCharset,
-  u2BytesCharset
-};
-
 nsresult
 nsUnicodeToBIG5HKSCSConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult)
 {
+    static const uint16_t *g_Big5HKSCSMappingTable[] = {
+      g_ASCIIMappingTable,
+      g_ufBig5Mapping,
+      g_ufBig5HKSCSMapping
+    };
+
+    static const uScanClassID g_Big5HKSCSScanClassIDs[] =  {
+      u1ByteCharset,
+      u2BytesCharset,
+      u2BytesCharset
+    };
+
     return CreateMultiTableEncoder(3,
                                    (uScanClassID*) &g_Big5HKSCSScanClassIDs,
                                    (uMappingTable**) &g_Big5HKSCSMappingTable,
                                    2 /* max length = src * 2 */,
                                    aOuter, aIID, aResult);
 }
 
 
--- a/intl/uconv/ucvtw/nsUnicodeToHKSCS.cpp
+++ b/intl/uconv/ucvtw/nsUnicodeToHKSCS.cpp
@@ -5,32 +5,30 @@
 
 #include "nsUnicodeToHKSCS.h"
 #include "nsUCvTWDll.h"
 #include "nsUCConstructors.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-
-
-static const uint16_t *g_Big5HKSCSMappingTable[] = {
-  g_ufBig5HKSCSMapping
-};
-
-static const uScanClassID g_Big5HKSCSScanClassIDs[] =  {
-  u2BytesCharset
-};
-
 //----------------------------------------------------------------------
 // Class nsUnicodeToHKSCS [implementation]
 
 nsresult
 nsUnicodeToHKSCSConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult)
 {
+  static const uint16_t *g_Big5HKSCSMappingTable[] = {
+    g_ufBig5HKSCSMapping
+  };
+
+  static const uScanClassID g_Big5HKSCSScanClassIDs[] =  {
+    u2BytesCharset
+  };
+
   return CreateMultiTableEncoder(1,
                                  (uScanClassID*) &g_Big5HKSCSScanClassIDs,
                                  (uMappingTable**) &g_Big5HKSCSMappingTable,
                                  2 /* max length = src * 2 */,
                                  aOuter, aIID, aResult);
 }
 
new file mode 100644
--- /dev/null
+++ b/intl/uconv/ucvtw2/UnifiedUCVTW2.cpp
@@ -0,0 +1,8 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsEUCTWToUnicode.cpp"
+#include "nsUnicodeToEUCTW.cpp"
+
--- a/intl/uconv/ucvtw2/moz.build
+++ b/intl/uconv/ucvtw2/moz.build
@@ -6,18 +6,17 @@
 
 MODULE = 'ucvtw2'
 
 EXPORTS += [
     'nsUCvTW2CID.h',
 ]
 
 CPP_SOURCES += [
-    'nsEUCTWToUnicode.cpp',
-    'nsUnicodeToEUCTW.cpp',
+    'UnifiedUCVTW2.cpp',
 ]
 
 LIBRARY_NAME = 'ucvtw2_s'
 
 LIBXUL_LIBRARY = True
 
 LOCAL_INCLUDES += [
     '../util',
--- a/intl/uconv/ucvtw2/nsEUCTWToUnicode.cpp
+++ b/intl/uconv/ucvtw2/nsEUCTWToUnicode.cpp
@@ -4,55 +4,55 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsEUCTWToUnicode.h"
 #include "nsUCvTW2Dll.h"
 #include "nsUCConstructors.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
-static const uScanClassID g_EUCTWScanClassIDs [] = {
-  u1ByteCharset,
-  u2BytesGRCharset,
-  u2BytesGRPrefix8EA2Charset,
-  u2BytesGRPrefix8EA3Charset,
-  u2BytesGRPrefix8EA4Charset,
-  u2BytesGRPrefix8EA5Charset,
-  u2BytesGRPrefix8EA6Charset,
-  u2BytesGRPrefix8EA7Charset
-};
-
-static const uint16_t *g_EUCTWMappingTableSet [] ={
-  g_ASCIIMappingTable,
-  g_utCNS1MappingTable,
-  g_utCNS2MappingTable,
-  g_utCNS3MappingTable,
-  g_utCNS4MappingTable,
-  g_utCNS5MappingTable,
-  g_utCNS6MappingTable,
-  g_utCNS7MappingTable
-};
-
-static const uRange g_EUCTWRanges[] = {
-  { 0x00, 0x7E },
-  { 0xA1, 0xFE },
-  { 0x8E, 0x8E },
-  { 0x8E, 0x8E },
-  { 0x8E, 0x8E },
-  { 0x8E, 0x8E },
-  { 0x8E, 0x8E },
-  { 0x8E, 0x8E }
-};
-
 
 //----------------------------------------------------------------------
 // Class nsEUCTWToUnicode [implementation]
 
 nsresult
 nsEUCTWToUnicodeConstructor(nsISupports *aOuter, REFNSIID aIID,
                                 void **aResult)
 {
+  static const uScanClassID g_EUCTWScanClassIDs [] = {
+    u1ByteCharset,
+    u2BytesGRCharset,
+    u2BytesGRPrefix8EA2Charset,
+    u2BytesGRPrefix8EA3Charset,
+    u2BytesGRPrefix8EA4Charset,
+    u2BytesGRPrefix8EA5Charset,
+    u2BytesGRPrefix8EA6Charset,
+    u2BytesGRPrefix8EA7Charset
+  };
+
+  static const uint16_t *g_EUCTWMappingTableSet [] ={
+    g_ASCIIMappingTable,
+    g_utCNS1MappingTable,
+    g_utCNS2MappingTable,
+    g_utCNS3MappingTable,
+    g_utCNS4MappingTable,
+    g_utCNS5MappingTable,
+    g_utCNS6MappingTable,
+    g_utCNS7MappingTable
+  };
+
+  static const uRange g_EUCTWRanges[] = {
+    { 0x00, 0x7E },
+    { 0xA1, 0xFE },
+    { 0x8E, 0x8E },
+    { 0x8E, 0x8E },
+    { 0x8E, 0x8E },
+    { 0x8E, 0x8E },
+    { 0x8E, 0x8E },
+    { 0x8E, 0x8E }
+  };
+
   return CreateMultiTableDecoder(8, 
                                  (const uRange*) &g_EUCTWRanges,
                                  (uScanClassID*) &g_EUCTWScanClassIDs,
                                  (uMappingTable**) &g_EUCTWMappingTableSet,
                                  1, aOuter, aIID, aResult);
 }
--- a/intl/uconv/ucvtw2/nsUnicodeToEUCTW.cpp
+++ b/intl/uconv/ucvtw2/nsUnicodeToEUCTW.cpp
@@ -5,44 +5,44 @@
 
 #include "nsUnicodeToEUCTW.h"
 #include "nsUCvTW2Dll.h"
 #include "nsUCConstructors.h"
 
 //----------------------------------------------------------------------
 // Global functions and data [declaration]
 
-static const uScanClassID g_EUCTWScanClassSet [] = {
-  u1ByteCharset,
-  u2BytesGRCharset,
-  u2BytesGRPrefix8EA2Charset,
-  u2BytesGRPrefix8EA3Charset,
-  u2BytesGRPrefix8EA4Charset,
-  u2BytesGRPrefix8EA5Charset,
-  u2BytesGRPrefix8EA6Charset,
-  u2BytesGRPrefix8EA7Charset
-};
-
-static const uint16_t *g_EUCTWMappingTableSet [] ={
-  g_ASCIIMappingTable,
-  g_ufCNS1MappingTable,
-  g_ufCNS2MappingTable,
-  g_ufCNS3MappingTable,
-  g_ufCNS4MappingTable,
-  g_ufCNS5MappingTable,
-  g_ufCNS6MappingTable,
-  g_ufCNS7MappingTable
-};
-
 //----------------------------------------------------------------------
 // Class nsUnicodeToEUCTW [implementation]
 
 nsresult
 nsUnicodeToEUCTWConstructor(nsISupports *aOuter, REFNSIID aIID,
                             void **aResult)
 {
+  static const uScanClassID g_EUCTWScanClassSet [] = {
+    u1ByteCharset,
+    u2BytesGRCharset,
+    u2BytesGRPrefix8EA2Charset,
+    u2BytesGRPrefix8EA3Charset,
+    u2BytesGRPrefix8EA4Charset,
+    u2BytesGRPrefix8EA5Charset,
+    u2BytesGRPrefix8EA6Charset,
+    u2BytesGRPrefix8EA7Charset
+  };
+
+  static const uint16_t *g_EUCTWMappingTableSet [] ={
+    g_ASCIIMappingTable,
+    g_ufCNS1MappingTable,
+    g_ufCNS2MappingTable,
+    g_ufCNS3MappingTable,
+    g_ufCNS4MappingTable,
+    g_ufCNS5MappingTable,
+    g_ufCNS6MappingTable,
+    g_ufCNS7MappingTable
+  };
+
   return CreateMultiTableEncoder(8,
                                  (uScanClassID*) &g_EUCTWScanClassSet,
                                  (uMappingTable**) &g_EUCTWMappingTableSet,
                                  4 /* max length = src * 4 */,
                                  aOuter, aIID, aResult);
 }
 
new file mode 100644
--- /dev/null
+++ b/intl/uconv/util/UnifiedUCVCUtils.c
@@ -0,0 +1,9 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ugen.c"
+#include "umap.c"
+#include "uscan.c"
+
new file mode 100644
--- /dev/null
+++ b/intl/uconv/util/UnifiedUCVUtils.cpp
@@ -0,0 +1,10 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsUCConstructors.cpp"
+#include "nsUCSupport.cpp"
+#include "nsUnicodeDecodeHelper.cpp"
+#include "nsUnicodeEncodeHelper.cpp"
+
--- a/intl/uconv/util/moz.build
+++ b/intl/uconv/util/moz.build
@@ -2,28 +2,23 @@
 # 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/.
 
 MODULE = 'uconv'
 
 CPP_SOURCES += [
-    'nsUCConstructors.cpp',
-    'nsUCSupport.cpp',
-    'nsUnicodeDecodeHelper.cpp',
-    'nsUnicodeEncodeHelper.cpp',
+    'UnifiedUCVUtils.cpp',
 ]
 
 LIBRARY_NAME = 'ucvutil_s'
 
 LIBXUL_LIBRARY = True
 
 CSRCS += [
-    'ugen.c',
-    'umap.c',
-    'uscan.c',
+    'UnifiedUCVCUtils.c',
 ]
 
 MSVC_ENABLE_PGO = True
 
 EXPORT_LIBRARY = True
 
--- a/js/public/StructuredClone.h
+++ b/js/public/StructuredClone.h
@@ -43,17 +43,19 @@ typedef JSObject *(*ReadStructuredCloneO
 typedef bool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w,
                                          JS::Handle<JSObject*> obj, void *closure);
 
 // This is called when JS_WriteStructuredClone is given an invalid transferable.
 // To follow HTML5, the application must throw a DATA_CLONE_ERR DOMException
 // with error set to one of the JS_SCERR_* values.
 typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32_t errorid);
 
-// The maximum supported structured-clone serialization format version.
+// The maximum supported structured-clone serialization format version. Note
+// that this does not need to be bumped for Transferable-only changes, since
+// they are never saved to persistent storage.
 #define JS_STRUCTURED_CLONE_VERSION 2
 
 struct JSStructuredCloneCallbacks {
     ReadStructuredCloneOp read;
     WriteStructuredCloneOp write;
     StructuredCloneErrorOp reportError;
 };
 
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -264,17 +264,18 @@ private:
         OP_GROUP2_EvIb                  = 0xC1,
         OP_RET_Iz                       = 0xC2,
         OP_RET                          = 0xC3,
         OP_GROUP11_EvIb                 = 0xC6,
         OP_GROUP11_EvIz                 = 0xC7,
         OP_INT3                         = 0xCC,
         OP_GROUP2_Ev1                   = 0xD1,
         OP_GROUP2_EvCL                  = 0xD3,
-	OP_FPU6				= 0xDD,
+        OP_FPU6                         = 0xDD,
+        OP_FLD32                        = 0xD9,
         OP_CALL_rel32                   = 0xE8,
         OP_JMP_rel32                    = 0xE9,
         PRE_SSE_F2                      = 0xF2,
         PRE_SSE_F3                      = 0xF3,
         OP_HLT                          = 0xF4,
         OP_GROUP3_EbIb                  = 0xF6,
         OP_GROUP3_Ev                    = 0xF7,
         OP_GROUP3_EvIz                  = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
@@ -295,16 +296,17 @@ private:
         OP2_MULSD_VsdWsd    = 0x59,
         OP2_CVTSS2SD_VsdEd  = 0x5A,
         OP2_CVTSD2SS_VsdEd  = 0x5A,
         OP2_SUBSD_VsdWsd    = 0x5C,
         OP2_MINSD_VsdWsd    = 0x5D,
         OP2_DIVSD_VsdWsd    = 0x5E,
         OP2_MAXSD_VsdWsd    = 0x5F,
         OP2_SQRTSD_VsdWsd   = 0x51,
+        OP2_SQRTSS_VssWss   = 0x51,
         OP2_ANDPD_VpdWpd    = 0x54,
         OP2_ORPD_VpdWpd     = 0x56,
         OP2_XORPD_VpdWpd    = 0x57,
         OP2_MOVD_VdEd       = 0x6E,
         OP2_MOVDQA_VsdWsd   = 0x6F,
         OP2_PSRLDQ_Vd       = 0x73,
         OP2_PCMPEQW         = 0x75,
         OP2_MOVD_EdVd       = 0x7E,
@@ -718,16 +720,21 @@ public:
     }
 #endif
 
     void fld_m(int offset, RegisterID base)
     {
         spew("fld        %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_FPU6, FPU6_OP_FLD, base, offset);
     }
+    void fld32_m(int offset, RegisterID base)
+    {
+        spew("fld        %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base));
+        m_formatter.oneByteOp(OP_FLD32, FPU6_OP_FLD, base, offset);
+    }
     void fisttp_m(int offset, RegisterID base)
     {
         spew("fisttp     %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base));
         m_formatter.oneByteOp(OP_FPU6, FPU6_OP_FISTTP, base, offset);
     }
     void fstp_m(int offset, RegisterID base)
     {
         spew("fstp       %s0x%x(%s)", PRETTY_PRINT_OFFSET(offset), nameIReg(base));
@@ -2340,16 +2347,23 @@ public:
 #if WTF_CPU_X86_64
     void cvtsq2sd_rr(RegisterID src, XMMRegisterID dst)
     {
         spew("cvtsq2sd   %s, %s",
              nameIReg(src), nameFPReg(dst));
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
     }
+    void cvtsq2ss_rr(RegisterID src, XMMRegisterID dst)
+    {
+        spew("cvtsq2ss   %s, %s",
+             nameIReg(src), nameFPReg(dst));
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp64(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
+    }
 #endif
 
     void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst)
     {
         spew("cvtsi2sd   %s0x%x(%s), %s",
              PRETTY_PRINT_OFFSET(offset), nameIReg(base), nameFPReg(dst));
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset);
@@ -2403,24 +2417,29 @@ public:
              nameFPReg(src), nameIReg(4, dst));
         m_formatter.prefix(PRE_SSE_F3);
         m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
     }
 
 #if WTF_CPU_X86_64
     void cvttsd2sq_rr(XMMRegisterID src, RegisterID dst)
     {
-        // We call this instruction cvttsd2sq to differentiate the 64-bit
-        // version from the 32-bit version, but in assembler it's just
-        // called cvttsd2si and it's disambiguated by the register name.
         spew("cvttsd2si  %s, %s",
              nameFPReg(src), nameIReg(dst));
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp64(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
     }
+
+    void cvttss2sq_rr(XMMRegisterID src, RegisterID dst)
+    {
+        spew("cvttss2si  %s, %s",
+             nameFPReg(src), nameIReg(dst));
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp64(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
+    }
 #endif
 
     void unpcklps_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         spew("unpcklps   %s, %s",
              nameFPReg(src), nameFPReg(dst));
         m_formatter.twoByteOp(OP2_UNPCKLPS_VsdWsd, (RegisterID)dst, (RegisterID)src);
     }
@@ -2882,24 +2901,39 @@ public:
     void andpd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         spew("andpd      %s, %s",
              nameFPReg(src), nameFPReg(dst));
         m_formatter.prefix(PRE_SSE_66);
         m_formatter.twoByteOp(OP2_ANDPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
     }
 
+    void andps_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        spew("andps      %s, %s",
+             nameFPReg(src), nameFPReg(dst));
+        m_formatter.twoByteOp(OP2_ANDPD_VpdWpd, (RegisterID)dst, (RegisterID)src);
+    }
+
     void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
         spew("sqrtsd     %s, %s",
              nameFPReg(src), nameFPReg(dst));
         m_formatter.prefix(PRE_SSE_F2);
         m_formatter.twoByteOp(OP2_SQRTSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
     }
 
+    void sqrtss_rr(XMMRegisterID src, XMMRegisterID dst)
+    {
+        spew("sqrtss     %s, %s",
+             nameFPReg(src), nameFPReg(dst));
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.twoByteOp(OP2_SQRTSS_VssWss, (RegisterID)dst, (RegisterID)src);
+    }
+
     void roundsd_rr(XMMRegisterID src, XMMRegisterID dst, RoundingMode mode)
     {
         spew("roundsd    %s, %s, %d",
              nameFPReg(src), nameFPReg(dst), (int)mode);
         m_formatter.prefix(PRE_SSE_66);
         m_formatter.threeByteOp(OP3_ROUNDSD_VsdWsd, ESCAPE_ROUNDSD, (RegisterID)dst, (RegisterID)src);
         m_formatter.immediate8(mode);
     }
deleted file mode 100644
--- a/js/src/build/cl.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import ctypes
-import os
-import sys
-
-from mozprocess.processhandler import ProcessHandlerMixin
-from mozbuild.makeutil import Makefile
-
-CL_INCLUDES_PREFIX = os.environ.get("CL_INCLUDES_PREFIX", "Note: including file:")
-
-GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
-GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
-
-
-# cl.exe likes to print inconsistent paths in the showIncludes output
-# (some lowercased, some not, with different directions of slashes),
-# and we need the original file case for make/pymake to be happy.
-# As this is slow and needs to be called a lot of times, use a cache
-# to speed things up.
-_normcase_cache = {}
-
-def normcase(path):
-    # Get*PathName want paths with backslashes
-    path = path.replace('/', os.sep)
-    dir = os.path.dirname(path)
-    # name is fortunately always going to have the right case,
-    # so we can use a cache for the directory part only.
-    name = os.path.basename(path)
-    if dir in _normcase_cache:
-        result = _normcase_cache[dir]
-    else:
-        path = ctypes.create_unicode_buffer(dir)
-        length = GetShortPathName(path, None, 0)
-        shortpath = ctypes.create_unicode_buffer(length)
-        GetShortPathName(path, shortpath, length)
-        length = GetLongPathName(shortpath, None, 0)
-        if length > len(path):
-            path = ctypes.create_unicode_buffer(length)
-        GetLongPathName(shortpath, path, length)
-        result = _normcase_cache[dir] = path.value
-    return os.path.join(result, name)
-
-
-def InvokeClWithDependencyGeneration(cmdline):
-    target = ""
-    # Figure out what the target is
-    for arg in cmdline:
-        if arg.startswith("-Fo"):
-            target = arg[3:]
-            break
-
-    if target == None:
-        print >>sys.stderr, "No target set" and sys.exit(1)
-
-    # Assume the source file is the last argument
-    source = cmdline[-1]
-    assert not source.startswith('-')
-
-    # The deps target lives here
-    depstarget = os.path.basename(target) + ".pp"
-
-    cmdline += ['-showIncludes']
-
-    mk = Makefile()
-    rule = mk.create_rule([target])
-    rule.add_dependencies([normcase(source)])
-
-    def on_line(line):
-        # cl -showIncludes prefixes every header with "Note: including file:"
-        # and an indentation corresponding to the depth (which we don't need)
-        if line.startswith(CL_INCLUDES_PREFIX):
-            dep = line[len(CL_INCLUDES_PREFIX):].strip()
-            # We can't handle pathes with spaces properly in mddepend.pl, but
-            # we can assume that anything in a path with spaces is a system
-            # header and throw it away.
-            dep = normcase(dep)
-            if ' ' not in dep:
-                rule.add_dependencies([dep])
-        else:
-            # Make sure we preserve the relevant output from cl. mozprocess
-            # swallows the newline delimiter, so we need to re-add it.
-            sys.stdout.write(line)
-            sys.stdout.write('\n')
-
-    # We need to ignore children because MSVC can fire up a background process
-    # during compilation. This process is cleaned up on its own. If we kill it,
-    # we can run into weird compilation issues.
-    p = ProcessHandlerMixin(cmdline, processOutputLine=[on_line],
-        ignore_children=True)
-    p.run()
-    p.processOutput()
-    ret = p.wait()
-
-    if ret != 0 or target == "":
-        sys.exit(ret)
-
-    depsdir = os.path.normpath(os.path.join(os.curdir, ".deps"))
-    depstarget = os.path.join(depsdir, depstarget)
-    if not os.path.isdir(depsdir):
-        try:
-            os.makedirs(depsdir)
-        except OSError:
-            pass # This suppresses the error we get when the dir exists, at the
-                 # cost of masking failure to create the directory.  We'll just
-                 # die on the next line though, so it's not that much of a loss.
-
-    with open(depstarget, "w") as f:
-        mk.dump(f)
-
-if __name__ == "__main__":
-    InvokeClWithDependencyGeneration(sys.argv[1:])
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -13,28 +13,33 @@
 #include "jsobj.h"
 #ifndef JS_MORE_DETERMINISTIC
 #include "jsprf.h"
 #endif
 #include "jswrapper.h"
 
 #include "jit/AsmJS.h"
 #include "jit/AsmJSLink.h"
+#include "js/StructuredClone.h"
 #include "vm/ForkJoin.h"
 #include "vm/GlobalObject.h"
 #include "vm/Interpreter.h"
 #include "vm/ProxyObject.h"
 
 #include "jscntxtinlines.h"
 
 using namespace js;
 using namespace JS;
 
 using mozilla::ArrayLength;
 
+// If fuzzingSafe is set, remove functionality that could cause problems with
+// fuzzers. Set this via the environment variable MOZ_FUZZING_SAFE.
+static bool fuzzingSafe = false;
+
 static bool
 GetBuildConfiguration(JSContext *cx, unsigned argc, jsval *vp)
 {
     RootedObject info(cx, JS_NewObject(cx, nullptr, nullptr, nullptr));
     if (!info)
         return false;
     RootedValue value(cx);
 
@@ -1086,16 +1091,238 @@ static bool
 SetIonAssertGraphCoherency(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     jit::js_IonOptions.assertGraphConsistency = ToBoolean(args.get(0));
     args.rval().setUndefined();
     return true;
 }
 
+class CloneBufferObject : public JSObject {
+    static const JSPropertySpec props_[2];
+    static const size_t DATA_SLOT   = 0;
+    static const size_t LENGTH_SLOT = 1;
+    static const size_t NUM_SLOTS   = 2;
+
+  public:
+    static const Class class_;
+
+    static CloneBufferObject *Create(JSContext *cx) {
+        RootedObject obj(cx, JS_NewObject(cx, Jsvalify(&class_), nullptr, nullptr));
+        if (!obj)
+            return nullptr;
+        obj->setReservedSlot(DATA_SLOT, PrivateValue(nullptr));
+        obj->setReservedSlot(LENGTH_SLOT, Int32Value(0));
+
+        if (!JS_DefineProperties(cx, obj, props_))
+            return nullptr;
+
+        return &obj->as<CloneBufferObject>();
+    }
+
+    static CloneBufferObject *Create(JSContext *cx, JSAutoStructuredCloneBuffer *buffer) {
+        Rooted<CloneBufferObject*> obj(cx, Create(cx));
+        if (!obj)
+            return nullptr;
+        uint64_t *datap;
+        size_t nbytes;
+        buffer->steal(&datap, &nbytes);
+        obj->setData(datap);
+        obj->setNBytes(nbytes);
+        return obj;
+    }
+
+    uint64_t *data() const {
+        return static_cast<uint64_t*>(getReservedSlot(0).toPrivate());
+    }
+
+    void setData(uint64_t *aData) {
+        JS_ASSERT(!data());
+        setReservedSlot(DATA_SLOT, PrivateValue(aData));
+    }
+
+    size_t nbytes() const {
+        return getReservedSlot(LENGTH_SLOT).toInt32();
+    }
+
+    void setNBytes(size_t nbytes) {
+        JS_ASSERT(nbytes <= UINT32_MAX);
+        setReservedSlot(LENGTH_SLOT, Int32Value(nbytes));
+    }
+
+    // Discard an owned clone buffer.
+    void discard() {
+        if (data())
+            JS_ClearStructuredClone(data(), nbytes());
+        setReservedSlot(DATA_SLOT, PrivateValue(nullptr));
+    }
+
+    static bool
+    setCloneBuffer_impl(JSContext* cx, CallArgs args) {
+        if (args.length() != 1 || !args[0].isString()) {
+            JS_ReportError(cx,
+                           "the first argument argument must be maxBytes, "
+                           "maxMallocBytes, gcStackpoolLifespan, gcBytes or "
+                           "gcNumber");
+            JS_ReportError(cx, "clonebuffer setter requires a single string argument");
+            return false;
+        }
+
+        if (fuzzingSafe) {
+            // A manually-created clonebuffer could easily trigger a crash
+            args.rval().setUndefined();
+            return true;
+        }
+
+        Rooted<CloneBufferObject*> obj(cx, &args.thisv().toObject().as<CloneBufferObject>());
+        obj->discard();
+
+        char *str = JS_EncodeString(cx, args[0].toString());
+        if (!str)
+            return false;
+        obj->setData(reinterpret_cast<uint64_t*>(str));
+        obj->setNBytes(JS_GetStringLength(args[0].toString()));
+
+        args.rval().setUndefined();
+        return true;
+    }
+
+    static bool
+    is(HandleValue v) {
+        return v.isObject() && v.toObject().is<CloneBufferObject>();
+    }
+
+    static bool
+    setCloneBuffer(JSContext* cx, unsigned int argc, JS::Value* vp) {
+        CallArgs args = CallArgsFromVp(argc, vp);
+        return CallNonGenericMethod<is, setCloneBuffer_impl>(cx, args);
+    }
+
+    static bool
+    getCloneBuffer_impl(JSContext* cx, CallArgs args) {
+        Rooted<CloneBufferObject*> obj(cx, &args.thisv().toObject().as<CloneBufferObject>());
+        JS_ASSERT(args.length() == 0);
+
+        if (!obj->data()) {
+            args.rval().setUndefined();
+            return true;
+        }
+
+        bool hasTransferable;
+        if (!JS_StructuredCloneHasTransferables(obj->data(), obj->nbytes(), &hasTransferable))
+            return false;
+
+        if (hasTransferable) {
+            JS_ReportError(cx, "cannot retrieve structured clone buffer with transferables");
+            return false;
+        }
+
+        JSString *str = JS_NewStringCopyN(cx, reinterpret_cast<char*>(obj->data()), obj->nbytes());
+        if (!str)
+            return false;
+        args.rval().setString(str);
+        return true;
+    }
+
+    static bool
+    getCloneBuffer(JSContext* cx, unsigned int argc, JS::Value* vp) {
+        CallArgs args = CallArgsFromVp(argc, vp);
+        return CallNonGenericMethod<is, getCloneBuffer_impl>(cx, args);
+    }
+
+    static void Finalize(FreeOp *fop, JSObject *obj) {
+        obj->as<CloneBufferObject>().discard();
+    }
+};
+
+const Class CloneBufferObject::class_ = {
+    "CloneBuffer", JSCLASS_HAS_RESERVED_SLOTS(CloneBufferObject::NUM_SLOTS),
+    JS_PropertyStub,       /* addProperty */
+    JS_DeletePropertyStub, /* delProperty */
+    JS_PropertyStub,       /* getProperty */
+    JS_StrictPropertyStub, /* setProperty */
+    JS_EnumerateStub,
+    JS_ResolveStub,
+    JS_ConvertStub,
+    Finalize,
+    nullptr,                  /* checkAccess */
+    nullptr,                  /* call */
+    nullptr,                  /* hasInstance */
+    nullptr,                  /* construct */
+    nullptr,                  /* trace */
+    JS_NULL_CLASS_EXT,
+    JS_NULL_OBJECT_OPS
+};
+
+const JSPropertySpec CloneBufferObject::props_[] = {
+    JS_PSGS("clonebuffer", getCloneBuffer, setCloneBuffer, 0),
+    JS_PS_END
+};
+
+static bool
+Serialize(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    Value v = args.length() > 0 ? args[0] : UndefinedValue();
+    Value transferables = args.length() > 1 ? args[1] : UndefinedValue();
+
+    JSAutoStructuredCloneBuffer clonebuf;
+    if (!clonebuf.write(cx, v, transferables))
+        return false;
+
+    RootedObject obj(cx, CloneBufferObject::Create(cx, &clonebuf));
+    if (!obj)
+        return false;
+
+    args.rval().setObject(*obj);
+    return true;
+}
+
+static bool
+Deserialize(JSContext *cx, unsigned argc, jsval *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    if (args.length() != 1 || !args[0].isObject()) {
+        JS_ReportError(cx, "deserialize requires a single clonebuffer argument");
+        return false;
+    }
+
+    if (!args[0].toObject().is<CloneBufferObject>()) {
+        JS_ReportError(cx, "deserialize requires a clonebuffer");
+        return false;
+    }
+
+    Rooted<CloneBufferObject*> obj(cx, &args[0].toObject().as<CloneBufferObject>());
+
+    // Clone buffer was already consumed?
+    if (!obj->data()) {
+        JS_ReportError(cx, "deserialize given invalid clone buffer "
+                       "(transferables already consumed?)");
+        return false;
+    }
+
+    bool hasTransferable;
+    if (!JS_StructuredCloneHasTransferables(obj->data(), obj->nbytes(), &hasTransferable))
+        return false;
+
+    RootedValue deserialized(cx);
+    if (!JS_ReadStructuredClone(cx, obj->data(), obj->nbytes(),
+                                JS_STRUCTURED_CLONE_VERSION, deserialized.address(), NULL, NULL)) {
+        return false;
+    }
+    args.rval().set(deserialized);
+
+    if (hasTransferable)
+        obj->discard();
+
+    return true;
+}
+
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'compartment')",
 "  Run the garbage collector. When obj is given, GC only its compartment.\n"
 "  If 'compartment' is given, GC any compartments that were scheduled for\n"
 "  GC via schedulegc."),
 
     JS_FN_HELP("minorgc", ::MinorGC, 0, 0,
@@ -1291,16 +1518,28 @@ static const JSFunctionSpecWithHelp Test
 "  Set a compiler option indexed in JSCompileOption enum to a number.\n"),
 
     JS_FN_HELP("setIonAssertGraphCoherency", SetIonAssertGraphCoherency, 1, 0,
 "setIonAssertGraphCoherency(bool)",
 "  Set whether Ion should perform graph consistency (DEBUG-only) assertions. These assertions\n"
 "  are valuable and should be generally enabled, however they can be very expensive for large\n"
 "  (asm.js) programs."),
 
+    JS_FN_HELP("serialize", Serialize, 1, 0,
+"serialize(data, [transferables])",
+"  Serialize 'data' using JS_WriteStructuredClone. Returns a structured\n"
+"  clone buffer object."),
+
+    JS_FN_HELP("deserialize", Deserialize, 1, 0,
+"deserialize(clonebuffer)",
+"  Deserialize data generated by serialize."),
+
     JS_FS_HELP_END
 };
 
 bool
-js::DefineTestingFunctions(JSContext *cx, HandleObject obj)
+js::DefineTestingFunctions(JSContext *cx, HandleObject obj, bool fuzzingSafe_)
 {
+    fuzzingSafe = fuzzingSafe_;
+    if (getenv("MOZ_FUZZING_SAFE") && getenv("MOZ_FUZZING_SAFE")[0] != '0')
+        fuzzingSafe = true;
     return JS_DefineFunctionsWithHelp(cx, obj, TestingFunctions);
 }
--- a/js/src/builtin/TestingFunctions.h
+++ b/js/src/builtin/TestingFunctions.h
@@ -7,17 +7,17 @@
 #ifndef builtin_TestingFunctions_h
 #define builtin_TestingFunctions_h
 
 #include "NamespaceImports.h"
 
 namespace js {
 
 bool
-DefineTestingFunctions(JSContext *cx, HandleObject obj);
+DefineTestingFunctions(JSContext *cx, HandleObject obj, bool fuzzingSafe);
 
 bool
 testingFunc_inParallelSection(JSContext *cx, unsigned argc, Value *vp);
 
 bool
 testingFunc_bailout(JSContext *cx, unsigned argc, Value *vp);
 
 bool
--- a/js/src/config/config.mk
+++ b/js/src/config/config.mk
@@ -211,18 +211,18 @@ endif
 endif
 
 OS_CONFIG	:= $(OS_ARCH)$(OS_RELEASE)
 
 MOZ_UNICHARUTIL_LIBS = $(LIBXUL_DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
 MOZ_WIDGET_SUPPORT_LIBS    = $(DIST)/lib/$(LIB_PREFIX)widgetsupport_s.$(LIB_SUFFIX)
 
 ifdef _MSC_VER
-CC_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
-CXX_WRAPPER ?= $(PYTHON) -O $(topsrcdir)/build/cl.py
+CC_WRAPPER = $(call py_action,cl)
+CXX_WRAPPER = $(call py_action,cl)
 endif # _MSC_VER
 
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
 MKDIR ?= mkdir
 SLEEP ?= sleep
 TOUCH ?= touch
 
@@ -891,20 +891,8 @@ PLY_INCLUDE = -I$(topsrcdir)/other-licen
 
 export CL_INCLUDES_PREFIX
 
 ifdef MOZ_GTK2_CFLAGS
 MOZ_GTK2_CFLAGS := -I$(topsrcdir)/widget/gtk/compat $(MOZ_GTK2_CFLAGS)
 endif
 
 DEFINES += -DNO_NSPR_10_SUPPORT
-
-# Run a named Python build action. The first argument is the name of the build
-# action. The second argument are the arguments to pass to the action (space
-# delimited arguments). e.g.
-#
-#   libs::
-#       $(call py_action,purge_manifests,_build_manifests/purge/foo.manifest)
-ifdef .PYMAKE
-py_action = %mozbuild.action.$(1) main $(2)
-else
-py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
-endif
--- a/js/src/config/makefiles/functions.mk
+++ b/js/src/config/makefiles/functions.mk
@@ -15,8 +15,20 @@ ifdef INCLUDED_FUNCTIONS_MK
 $(error Do not include functions.mk twice!)
 endif
 INCLUDED_FUNCTIONS_MK = 1
 
 core_abspath = $(error core_abspath is unsupported, use $$(abspath) instead)
 core_realpath = $(error core_realpath is unsupported)
 
 core_winabspath = $(error core_winabspath is unsupported)
+
+# Run a named Python build action. The first argument is the name of the build
+# action. The second argument are the arguments to pass to the action (space
+# delimited arguments). e.g.
+#
+#   libs::
+#       $(call py_action,purge_manifests,_build_manifests/purge/foo.manifest)
+ifdef .PYMAKE
+py_action = %mozbuild.action.$(1) main $(2)
+else
+py_action = $(PYTHON) -m mozbuild.action.$(1) $(2)
+endif
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -679,17 +679,17 @@ struct ChunkBitmap
     ChunkBitmap() { }
 
     MOZ_ALWAYS_INLINE void getMarkWordAndMask(const Cell *cell, uint32_t color,
                                               uintptr_t **wordp, uintptr_t *maskp)
     {
         GetGCThingMarkWordAndMask(cell, color, wordp, maskp);
     }
 
-    MOZ_ALWAYS_INLINE bool isMarked(const Cell *cell, uint32_t color) {
+    MOZ_ALWAYS_INLINE MOZ_TSAN_BLACKLIST bool isMarked(const Cell *cell, uint32_t color) {
         uintptr_t *word, mask;
         getMarkWordAndMask(cell, color, &word, &mask);
         return *word & mask;
     }
 
     MOZ_ALWAYS_INLINE bool markIfUnmarked(const Cell *cell, uint32_t color) {
         uintptr_t *word, mask;
         getMarkWordAndMask(cell, BLACK, &word, &mask);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug890722.js
@@ -0,0 +1,29 @@
+
+// Test setting return value;
+
+function bail() { bailout(); }
+function bail2() { bailout(); return 2; }
+
+// Test 1: Test setting/getting return value in ionmonkey
+function test() {
+    return evalcx("1;");
+}
+assertEq(test(), 1)
+
+// Test 3: Test ion -> baseline
+function test2() {
+    return evaluate("1; bail2();");
+}
+assertEq(test2(), 2)
+
+// Test 3: Test ion -> baseline
+function test3() {
+    return evaluate("1; bail2(); 3");
+}
+assertEq(test3(), 3)
+
+// Test4: Test baseline -> ion entering (very fragile, since iterations need to be precise, before it gets tested)
+function test4() {
+    return evaluate("1; for(var i=0; i<1097; i++) { 3; };");
+}
+assertEq(test4(), 3)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug928625.js
@@ -0,0 +1,3 @@
+var summary = true;
+evaluate("var summary = 'Array slice when arrays length is assigned';");
+evaluate('var summary;');
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/testFloat32-correctness.js
@@ -0,0 +1,229 @@
+setJitCompilerOption("ion.usecount.trigger", 50);
+
+var f32 = new Float32Array(10);
+
+function test(setup, f) {
+    if (f === undefined) {
+        f = setup;
+        setup = function(){};
+    }
+    setup();
+    for(var n = 200; n; --n) {
+        f();
+    }
+}
+
+// Basic arithmetic
+function setupBasicArith() {
+    f32[0] = -Infinity;
+    f32[1] = -1;
+    f32[2] = -0;
+    f32[3] = 0;
+    f32[4] = 1.337;
+    f32[5] = 42;
+    f32[6] = Infinity;
+    f32[7] = NaN;
+}
+function basicArith() {
+    for (var i = 0; i < 7; ++i) {
+        var opf = Math.fround(f32[i] + f32[i+1]);
+        var opd = (1 / (1 / f32[i])) + f32[i+1];
+        assertFloat32(opf, true);
+        assertFloat32(opd, false);
+        assertEq(opf, Math.fround(opd));
+
+        opf = Math.fround(f32[i] - f32[i+1]);
+        opd = (1 / (1 / f32[i])) - f32[i+1];
+        assertFloat32(opf, true);
+        assertFloat32(opd, false);
+        assertEq(opf, Math.fround(opd));
+
+        opf = Math.fround(f32[i] * f32[i+1]);
+        opd = (1 / (1 / f32[i])) * f32[i+1];
+        assertFloat32(opf, true);
+        assertFloat32(opd, false);
+        assertEq(opf, Math.fround(opd));
+
+        opf = Math.fround(f32[i] / f32[i+1]);
+        opd = (1 / (1 / f32[i])) / f32[i+1];
+        assertFloat32(opf, true);
+        assertFloat32(opd, false);
+        assertEq(opf, Math.fround(opd));
+    }
+}
+test(setupBasicArith, basicArith);
+
+// MAbs
+function setupAbs() {
+    f32[0] = -0;
+    f32[1] = 0;
+    f32[2] = -3.14159;
+    f32[3] = 3.14159;
+    f32[4] = -Infinity;
+    f32[5] = Infinity;
+    f32[6] = NaN;
+}
+function abs() {
+    for(var i = 0; i < 7; ++i) {
+        assertEq( Math.fround(Math.abs(f32[i])), Math.abs(f32[i]) );
+    }
+}
+test(setupAbs, abs);
+
+// MSqrt
+function setupSqrt() {
+    f32[0] = 0;
+    f32[1] = 1;
+    f32[2] = 4;
+    f32[3] = -1;
+    f32[4] = Infinity;
+    f32[5] = NaN;
+    f32[6] = 13.37;
+}
+function sqrt() {
+    for(var i = 0; i < 7; ++i) {
+        var sqrtf = Math.fround(Math.sqrt(f32[i]));
+        var sqrtd = 1 + Math.sqrt(f32[i]) - 1; // force no float32 by chaining arith ops
+        assertEq( sqrtf, Math.fround(sqrtd) );
+    }
+}
+test(setupSqrt, sqrt);
+
+// MTruncateToInt32
+// The only way to get a MTruncateToInt32 with a Float32 input is to use Math.imul
+function setupTruncateToInt32() {
+    f32[0] = -1;
+    f32[1] = 4;
+    f32[2] = 5.13;
+}
+function truncateToInt32() {
+    assertEq( Math.imul(f32[0], f32[1]), Math.imul(-1, 4) );
+    assertEq( Math.imul(f32[1], f32[2]), Math.imul(4, 5) );
+}
+test(setupTruncateToInt32, truncateToInt32);
+
+// MCompare
+function comp() {
+    for(var i = 0; i < 9; ++i) {
+        assertEq( f32[i] < f32[i+1], true );
+    }
+}
+function setupComp() {
+    f32[0] = -Infinity;
+    f32[1] = -1;
+    f32[2] = -0.01;
+    f32[3] = 0;
+    f32[4] = 0.01;
+    f32[5] = 1;
+    f32[6] = 10;
+    f32[7] = 13.37;
+    f32[8] = 42;
+    f32[9] = Infinity;
+}
+test(setupComp, comp);
+
+// MNot
+function setupNot() {
+    f32[0] = -0;
+    f32[1] = 0;
+    f32[2] = 1;
+    f32[3] = NaN;
+    f32[4] = Infinity;
+    f32[5] = 42;
+    f32[5] = -23;
+}
+function not() {
+    assertEq( !f32[0], true );
+    assertEq( !f32[1], true );
+    assertEq( !f32[2], false );
+    assertEq( !f32[3], true );
+    assertEq( !f32[4], false );
+    assertEq( !f32[5], false );
+    assertEq( !f32[6], false );
+}
+test(setupNot, not);
+
+// MToInt32
+var str = "can haz cheezburger? okthxbye;";
+function setupToInt32() {
+    f32[0] = 0;
+    f32[1] = 1;
+    f32[2] = 2;
+    f32[3] = 4;
+    f32[4] = 5;
+}
+function testToInt32() {
+    assertEq(str[f32[0]], 'c');
+    assertEq(str[f32[1]], 'a');
+    assertEq(str[f32[2]], 'n');
+    assertEq(str[f32[3]], 'h');
+    assertEq(str[f32[4]], 'a');
+}
+test(setupToInt32, testToInt32);
+
+function setupBailoutToInt32() {
+    f32[0] = .5;
+}
+function testBailoutToInt32() {
+    assertEq(typeof str[f32[0]], 'undefined');
+}
+test(setupBailoutToInt32, testBailoutToInt32);
+
+// MMath
+function assertNear(a, b) {
+    return ( a != a && b != b ) ||
+           Math.abs(a-b) < 1e-7;
+}
+function setupTrigo() {
+    f32[0] = 0;
+    f32[1] = Math.PI / 2;
+    f32[2] = Math.PI;
+    f32[3] = 3 * Math.PI / 2;
+}
+function trigo() {
+    // Cos
+    assertNear(Math.fround(Math.cos(f32[0])), Math.cos(0));
+    assertNear(Math.fround(Math.cos(f32[1])), Math.cos(Math.PI / 2));
+    assertNear(Math.fround(Math.cos(f32[2])), Math.cos(Math.PI));
+    assertNear(Math.fround(Math.cos(f32[3])), Math.cos(3 * Math.PI / 2));
+
+    // Sin
+    assertNear(Math.fround(Math.sin(f32[0])), Math.sin(0));
+    assertNear(Math.fround(Math.sin(f32[1])), Math.sin(Math.PI / 2));
+    assertNear(Math.fround(Math.sin(f32[2])), Math.sin(Math.PI));
+    assertNear(Math.fround(Math.sin(f32[3])), Math.sin(3 * Math.PI / 2));
+
+    // Tan
+    assertNear(Math.fround(Math.tan(f32[0])), Math.tan(0));
+    assertNear(Math.fround(Math.tan(f32[1])), Math.tan(Math.PI / 2));
+    assertNear(Math.fround(Math.tan(f32[2])), Math.tan(Math.PI));
+    assertNear(Math.fround(Math.tan(f32[3])), Math.tan(3 * Math.PI / 2));
+
+    // ACos
+    assertNear(Math.fround(Math.acos(f32[0])), Math.acos(0));
+    assertNear(Math.fround(Math.acos(f32[1])), Math.acos(Math.PI / 2));
+    assertNear(Math.fround(Math.acos(f32[2])), Math.acos(Math.PI));
+    assertNear(Math.fround(Math.acos(f32[3])), Math.acos(3 * Math.PI / 2));
+
+    // ASin
+    assertNear(Math.fround(Math.asin(f32[0])), Math.asin(0));
+    assertNear(Math.fround(Math.asin(f32[1])), Math.asin(Math.PI / 2));
+    assertNear(Math.fround(Math.asin(f32[2])), Math.asin(Math.PI));
+    assertNear(Math.fround(Math.asin(f32[3])), Math.asin(3 * Math.PI / 2));
+
+    // ATan
+    assertNear(Math.fround(Math.atan(f32[0])), Math.atan(0));
+    assertNear(Math.fround(Math.atan(f32[1])), Math.atan(Math.PI / 2));
+    assertNear(Math.fround(Math.atan(f32[2])), Math.atan(Math.PI));
+    assertNear(Math.fround(Math.atan(f32[3])), Math.atan(3 * Math.PI / 2));
+}
+test(setupTrigo, trigo);
+
+function otherMath() {
+    for (var i = 0; i < 10; ++i) {
+        assertNear(Math.fround(Math.exp(f32[i])), Math.exp(f32[i]));
+        assertNear(Math.fround(Math.log(f32[i])), Math.log(f32[i]));
+    }
+};
+test(setupComp, otherMath);
+
--- a/js/src/jit-test/tests/ion/testFloat32.js
+++ b/js/src/jit-test/tests/ion/testFloat32.js
@@ -50,17 +50,17 @@
 // would be guarded against modifications (typeguard on Math and then on fround). In this case, Math.fround is
 // not inlined and the compiler will consider the return value to be a double, not a float32, making the
 // assertions fail. Note that as assertFloat32 is declared unsafe for fuzzing, this can't happen in fuzzed code.
 //
 // To be able to test it, we still need ion compilation though. A nice solution is to manually lower the ion usecount.
 setJitCompilerOption("ion.usecount.trigger", 50);
 
 function test(f) {
-    f32[0] = 1;
+    f32[0] = .5;
     for(var n = 110; n; n--)
         f();
 }
 
 var f32 = new Float32Array(2);
 var f64 = new Float64Array(2);
 
 function acceptAdd() {
@@ -131,16 +131,44 @@ test(refuseAddSeveral);
 function refuseAddFunctionCall() {
     function plusOne(x) { return Math.cos(x+1)*13.37; }
     var res = plusOne(f32[0]); // func call is not a consumer
     f32[0] = res;
     assertFloat32(res, false);
 }
 test(refuseAddFunctionCall);
 
+function acceptSqrt() {
+    var res = Math.sqrt(f32[0]);
+    assertFloat32(res, true);
+    f32[0] = res;
+}
+test(acceptSqrt);
+
+function refuseSqrt() {
+    var res = Math.sqrt(f32[0]);
+    assertFloat32(res, false);
+    f32[0] = res + 1;
+}
+test(refuseSqrt);
+
+function acceptAbs() {
+    var res = Math.abs(f32[0]);
+    assertFloat32(res, true);
+    f32[0] = res;
+}
+test(acceptAbs);
+
+function refuseAbs() {
+    var res = Math.abs(f32[0]);
+    assertFloat32(res, false);
+    f64[0] = res + 1;
+}
+test(refuseAbs);
+
 function acceptTrigo() {
     var res = Math.cos(f32[0]);
     f32[0] = res;
     assertFloat32(res, true);
 
     var res = Math.sin(f32[0]);
     f32[0] = res;
     assertFloat32(res, true);
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -532,26 +532,31 @@ InitFromBailout(JSContext *cx, HandleScr
     // that will be fixed later.
     if (cx->runtime()->spsProfiler.enabled() && ionScript->hasSPSInstrumentation()) {
         IonSpew(IonSpew_BaselineBailouts, "      Setting SPS flag on frame!");
         flags |= BaselineFrame::HAS_PUSHED_SPS_FRAME;
     }
 
     // Initialize BaselineFrame's scopeChain and argsObj
     JSObject *scopeChain = nullptr;
+    Value returnValue;
     ArgumentsObject *argsObj = nullptr;
     BailoutKind bailoutKind = iter.bailoutKind();
     if (bailoutKind == Bailout_ArgumentCheck) {
         // Temporary hack -- skip the (unused) scopeChain, because it could be
         // bogus (we can fail before the scope chain slot is set). Strip the
         // hasScopeChain flag and this will be fixed up later in |FinishBailoutToBaseline|,
         // which calls |EnsureHasScopeObjects|.
         IonSpew(IonSpew_BaselineBailouts, "      Bailout_ArgumentCheck! (no valid scopeChain)");
         iter.skip();
 
+        // skip |return value|
+        iter.skip();
+        returnValue = UndefinedValue();
+
         // Scripts with |argumentsHasVarBinding| have an extra slot.
         if (script->argumentsHasVarBinding()) {
             IonSpew(IonSpew_BaselineBailouts,
                     "      Bailout_ArgumentCheck for script with argumentsHasVarBinding!"
                     "Using empty arguments object");
             iter.skip();
         }
     } else {
@@ -577,26 +582,31 @@ InitFromBailout(JSContext *cx, HandleScr
                 // prologue in this case because the prologue expects the scope
                 // chain in R1 for eval and global scripts.
                 JS_ASSERT(!script->isForEval());
                 JS_ASSERT(script->compileAndGo);
                 scopeChain = &(script->global());
             }
         }
 
-        // If script maybe has an arguments object, the second slot will hold it.
+        // Second slot holds the return value.
+        returnValue = iter.read();
+
+        // If script maybe has an arguments object, the third slot will hold it.
         if (script->argumentsHasVarBinding()) {
             v = iter.read();
             JS_ASSERT(v.isObject() || v.isUndefined());
             if (v.isObject())
                 argsObj = &v.toObject().as<ArgumentsObject>();
         }
     }
     IonSpew(IonSpew_BaselineBailouts, "      ScopeChain=%p", scopeChain);
     blFrame->setScopeChain(scopeChain);
+    IonSpew(IonSpew_BaselineBailouts, "      ReturnValue=%016llx", *((uint64_t *) &returnValue));
+    blFrame->setReturnValue(returnValue);
 
     // Do not need to initialize scratchValue or returnValue fields in BaselineFrame.
 
     blFrame->setFlags(flags);
 
     // initArgsObjUnchecked modifies the frame's flags, so call it after setFlags.
     if (argsObj)
         blFrame->initArgsObjUnchecked(*argsObj);
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -28,17 +28,17 @@ BaselineCompiler::BaselineCompiler(JSCon
   : BaselineCompilerSpecific(cx, script),
     modifiesArguments_(false)
 {
 }
 
 bool
 BaselineCompiler::init()
 {
-    if (!analysis_.init(cx))
+    if (!analysis_.init(cx->runtime()->gsnCache))
         return false;
 
     if (!labels_.init(script->length))
         return false;
 
     for (size_t i = 0; i < script->length; i++)
         new (&labels_[i]) Label();
 
@@ -69,17 +69,17 @@ MethodStatus
 BaselineCompiler::compile()
 {
     IonSpew(IonSpew_BaselineScripts, "Baseline compiling script %s:%d (%p)",
             script->filename(), script->lineno, script.get());
 
     IonSpew(IonSpew_Codegen, "# Emitting baseline code for script %s:%d",
             script->filename(), script->lineno);
 
-    if (cx->typeInferenceEnabled() && !script->ensureHasBytecodeTypeMap(cx))
+    if (cx->typeInferenceEnabled() && !script->ensureHasTypes(cx))
         return Method_Error;
 
     // Only need to analyze scripts which are marked |argumensHasVarBinding|, to
     // compute |needsArgsObj| flag.
     if (script->argumentsHasVarBinding()) {
         if (!script->ensureRanAnalysis(cx))
             return Method_Error;
     }
@@ -150,21 +150,25 @@ BaselineCompiler::compile()
     }
 
     if (pcEntries.oom())
         return Method_Error;
 
     prologueOffset_.fixup(&masm);
     spsPushToggleOffset_.fixup(&masm);
 
+    // Note: There is an extra entry in the bytecode type map for the search hint, see below.
+    size_t bytecodeTypeMapEntries = cx->typeInferenceEnabled() ? script->nTypeSets + 1 : 0;
+
     BaselineScript *baselineScript = BaselineScript::New(cx, prologueOffset_.offset(),
                                                          spsPushToggleOffset_.offset(),
                                                          icEntries_.length(),
                                                          pcMappingIndexEntries.length(),
-                                                         pcEntries.length());
+                                                         pcEntries.length(),
+                                                         bytecodeTypeMapEntries);
     if (!baselineScript)
         return Method_Error;
 
     baselineScript->setMethod(code);
 
     script->setBaselineScript(baselineScript);
 
     IonSpew(IonSpew_BaselineScripts, "Created BaselineScript %p (raw %p) for %s:%d",
@@ -205,16 +209,36 @@ BaselineCompiler::compile()
     // All barriers are emitted off-by-default, toggle them on if needed.
     if (cx->zone()->needsBarrier())
         baselineScript->toggleBarriers(true);
 
     // All SPS instrumentation is emitted toggled off.  Toggle them on if needed.
     if (cx->runtime()->spsProfiler.enabled())
         baselineScript->toggleSPS(true);
 
+    if (cx->typeInferenceEnabled()) {
+        uint32_t *bytecodeMap = baselineScript->bytecodeTypeMap();
+
+        uint32_t added = 0;
+        for (jsbytecode *pc = script->code; pc < script->code + script->length; pc += GetBytecodeLength(pc)) {
+            JSOp op = JSOp(*pc);
+            if (js_CodeSpec[op].format & JOF_TYPESET) {
+                bytecodeMap[added++] = pc - script->code;
+                if (added == script->nTypeSets)
+                    break;
+            }
+        }
+
+        JS_ASSERT(added == script->nTypeSets);
+
+        // The last entry in the last index found, and is used to avoid binary
+        // searches for the sought entry when queries are in linear order.
+        bytecodeMap[script->nTypeSets] = 0;
+    }
+
     return Method_Compiled;
 }
 
 bool
 BaselineCompiler::emitPrologue()
 {
     masm.push(BaselineFrameReg);
     masm.mov(BaselineStackReg, BaselineFrameReg);
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -890,16 +890,22 @@ PrepareOsrTempData(JSContext *cx, ICUseC
         // Store the function in exec field, and StackFrame::FUNCTION for flags.
         *((JSFunction **) (stackFrame + StackFrame::offsetOfExec())) = frame->fun();
         *((uint32_t *) (stackFrame + StackFrame::offsetOfFlags())) = StackFrame::FUNCTION;
     } else {
         *((JSScript **) (stackFrame + StackFrame::offsetOfExec())) = frame->script();
         *((uint32_t *) (stackFrame + StackFrame::offsetOfFlags())) = 0;
     }
 
+    // Set return value.
+    if (frame->hasReturnValue()) {
+        *((uint32_t *) (stackFrame + StackFrame::offsetOfFlags())) |= StackFrame::HAS_RVAL;
+        *((Value *) (stackFrame + StackFrame::offsetOfReturnValue())) = *(frame->returnValue());
+    }
+
     // Do locals and stack values.  Note that in the fake StackFrame, these go from
     // low to high addresses, while on the C stack, they go from high to low addresses.
     // So we can't use memcpy on this, but must copy the values in reverse order.
     Value *stackFrameLocalsStart = (Value *) (stackFrame + sizeof(StackFrame));
     for (size_t i = 0; i < numLocalsAndStackVals; i++)
         stackFrameLocalsStart[i] = *(frame->valueSlot(i));
 
     IonSpew(IonSpew_BaselineOSR, "Allocated IonOsrTempData at %p", (void *) info);
--- a/js/src/jit/BaselineInspector.h
+++ b/js/src/jit/BaselineInspector.h
@@ -41,22 +41,22 @@ class SetElemICInspector : public ICInsp
     bool sawOOBTypedArrayWrite() const;
     bool sawDenseWrite() const;
     bool sawTypedArrayWrite() const;
 };
 
 class BaselineInspector
 {
   private:
-    RootedScript script;
+    JSScript *script;
     ICEntry *prevLookedUpEntry;
 
   public:
-    BaselineInspector(JSContext *cx, JSScript *rawScript)
-      : script(cx, rawScript), prevLookedUpEntry(nullptr)
+    BaselineInspector(JSScript *script)
+      : script(script), prevLookedUpEntry(nullptr)
     {
         JS_ASSERT(script);
     }
 
     bool hasBaselineScript() const {
         return script->hasBaselineScript();
     }
 
--- a/js/src/jit/BaselineJIT.cpp
+++ b/js/src/jit/BaselineJIT.cpp
@@ -206,18 +206,18 @@ jit::EnterBaselineAtBranch(JSContext *cx
     IonExecStatus status = EnterBaseline(cx, data);
     if (status != IonExec_Ok)
         return status;
 
     fp->setReturnValue(data.result);
     return IonExec_Ok;
 }
 
-static MethodStatus
-BaselineCompile(JSContext *cx, HandleScript script)
+MethodStatus
+jit::BaselineCompile(JSContext *cx, HandleScript script)
 {
     JS_ASSERT(!script->hasBaselineScript());
     JS_ASSERT(script->canBaselineCompile());
 
     LifoAlloc alloc(BASELINE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
 
     TempAllocator *temp = alloc.new_<TempAllocator>(&alloc);
     if (!temp)
@@ -356,31 +356,35 @@ jit::CanEnterBaselineMethod(JSContext *c
 };
 
 // Be safe, align IC entry list to 8 in all cases.
 static const unsigned DataAlignment = sizeof(uintptr_t);
 
 BaselineScript *
 BaselineScript::New(JSContext *cx, uint32_t prologueOffset,
                     uint32_t spsPushToggleOffset, size_t icEntries,
-                    size_t pcMappingIndexEntries, size_t pcMappingSize)
+                    size_t pcMappingIndexEntries, size_t pcMappingSize,
+                    size_t bytecodeTypeMapEntries)
 {
     size_t paddedBaselineScriptSize = AlignBytes(sizeof(BaselineScript), DataAlignment);
 
     size_t icEntriesSize = icEntries * sizeof(ICEntry);
     size_t pcMappingIndexEntriesSize = pcMappingIndexEntries * sizeof(PCMappingIndexEntry);
+    size_t bytecodeTypeMapSize = bytecodeTypeMapEntries * sizeof(uint32_t);
 
     size_t paddedICEntriesSize = AlignBytes(icEntriesSize, DataAlignment);
     size_t paddedPCMappingIndexEntriesSize = AlignBytes(pcMappingIndexEntriesSize, DataAlignment);
     size_t paddedPCMappingSize = AlignBytes(pcMappingSize, DataAlignment);
+    size_t paddedBytecodeTypesMapSize = AlignBytes(bytecodeTypeMapSize, DataAlignment);
 
     size_t allocBytes = paddedBaselineScriptSize +
         paddedICEntriesSize +
         paddedPCMappingIndexEntriesSize +
-        paddedPCMappingSize;
+        paddedPCMappingSize +
+        paddedBytecodeTypesMapSize;
 
     uint8_t *buffer = (uint8_t *)cx->malloc_(allocBytes);
     if (!buffer)
         return nullptr;
 
     BaselineScript *script = reinterpret_cast<BaselineScript *>(buffer);
     new (script) BaselineScript(prologueOffset, spsPushToggleOffset);
 
@@ -393,16 +397,18 @@ BaselineScript::New(JSContext *cx, uint3
     script->pcMappingIndexOffset_ = offsetCursor;
     script->pcMappingIndexEntries_ = pcMappingIndexEntries;
     offsetCursor += paddedPCMappingIndexEntriesSize;
 
     script->pcMappingOffset_ = offsetCursor;
     script->pcMappingSize_ = pcMappingSize;
     offsetCursor += paddedPCMappingSize;
 
+    script->bytecodeTypeMapOffset_ = bytecodeTypeMapEntries ? offsetCursor : 0;
+
     return script;
 }
 
 void
 BaselineScript::trace(JSTracer *trc)
 {
     MarkIonCode(trc, &method_, "baseline-method");
 
--- a/js/src/jit/BaselineJIT.h
+++ b/js/src/jit/BaselineJIT.h
@@ -141,23 +141,28 @@ struct BaselineScript
     uint32_t icEntries_;
 
     uint32_t pcMappingIndexOffset_;
     uint32_t pcMappingIndexEntries_;
 
     uint32_t pcMappingOffset_;
     uint32_t pcMappingSize_;
 
+    // List mapping indexes of bytecode type sets to the offset of the opcode
+    // they correspond to, for use by TypeScript::BytecodeTypes.
+    uint32_t bytecodeTypeMapOffset_;
+
   public:
     // Do not call directly, use BaselineScript::New. This is public for cx->new_.
     BaselineScript(uint32_t prologueOffset, uint32_t spsPushToggleOffset);
 
     static BaselineScript *New(JSContext *cx, uint32_t prologueOffset,
                                uint32_t spsPushToggleOffset, size_t icEntries,
-                               size_t pcMappingIndexEntries, size_t pcMappingSize);
+                               size_t pcMappingIndexEntries, size_t pcMappingSize,
+                               size_t bytecodeTypeMapEntries);
     static void Trace(JSTracer *trc, BaselineScript *script);
     static void Destroy(FreeOp *fop, BaselineScript *script);
 
     void purgeOptimizedStubs(Zone *zone);
 
     static inline size_t offsetOfMethod() {
         return offsetof(BaselineScript, method_);
     }
@@ -264,16 +269,21 @@ struct BaselineScript
     void noteAccessedGetter(uint32_t pcOffset);
     void noteArrayWriteHole(uint32_t pcOffset);
 
     static size_t offsetOfFlags() {
         return offsetof(BaselineScript, flags_);
     }
 
     static void writeBarrierPre(Zone *zone, BaselineScript *script);
+
+    uint32_t *bytecodeTypeMap() {
+        JS_ASSERT(bytecodeTypeMapOffset_);
+        return reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(this) + bytecodeTypeMapOffset_);
+    }
 };
 
 inline bool
 IsBaselineEnabled(JSContext *cx)
 {
     return cx->options().baseline();
 }
 
@@ -343,14 +353,17 @@ BailoutIonToBaseline(JSContext *cx, JitA
                      bool invalidate, BaselineBailoutInfo **bailoutInfo,
                      const ExceptionBailoutInfo *exceptionInfo = nullptr);
 
 // Mark baseline scripts on the stack as active, so that they are not discarded
 // during GC.
 void
 MarkActiveBaselineScripts(Zone *zone);
 
+MethodStatus
+BaselineCompile(JSContext *cx, HandleScript script);
+
 } // namespace jit
 } // namespace js
 
 #endif // JS_ION
 
 #endif /* jit_BaselineJIT_h */
--- a/js/src/jit/BytecodeAnalysis.cpp
+++ b/js/src/jit/BytecodeAnalysis.cpp
@@ -34,17 +34,17 @@ struct CatchFinallyRange
     }
 
     bool contains(uint32_t offset) const {
         return start <= offset && offset < end;
     }
 };
 
 bool
-BytecodeAnalysis::init(JSContext *cx)
+BytecodeAnalysis::init(GSNCache &gsn)
 {
     if (!infos_.growByUninitialized(script_->length))
         return false;
 
     jsbytecode *end = script_->code + script_->length;
 
     // Clear all BytecodeInfo.
     mozilla::PodZero(infos_.begin(), infos_.length());
@@ -115,17 +115,17 @@ BytecodeAnalysis::init(JSContext *cx)
                         infos_[catchOffset].init(stackDepth);
                         infos_[catchOffset].jumpTarget = true;
                     }
                 }
             }
 
             // Get the pc of the last instruction in the try block. It's a JSOP_GOTO to
             // jump over the catch/finally blocks.
-            jssrcnote *sn = js_GetSrcNote(cx, script_, pc);
+            jssrcnote *sn = GetSrcNote(gsn, script_, pc);
             JS_ASSERT(SN_TYPE(sn) == SRC_TRY);
 
             jsbytecode *endOfTry = pc + js_GetSrcNoteOffset(sn, 0);
             JS_ASSERT(JSOp(*endOfTry) == JSOP_GOTO);
 
             jsbytecode *afterTry = endOfTry + GET_JUMP_OFFSET(endOfTry);
             JS_ASSERT(afterTry > endOfTry);
 
--- a/js/src/jit/BytecodeAnalysis.h
+++ b/js/src/jit/BytecodeAnalysis.h
@@ -42,17 +42,17 @@ class BytecodeAnalysis
 
     bool usesScopeChain_;
     bool hasTryFinally_;
     bool hasSetArg_;
 
   public:
     explicit BytecodeAnalysis(JSScript *script);
 
-    bool init(JSContext *cx);
+    bool init(GSNCache &gsn);
 
     BytecodeInfo &info(jsbytecode *pc) {
         JS_ASSERT(infos_[pc - script_->code].initialized);
         return infos_[pc - script_->code];
     }
 
     BytecodeInfo *maybeInfo(jsbytecode *pc) {
         if (infos_[pc - script_->code].initialized)
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1055,16 +1055,47 @@ CodeGenerator::visitOsrArgumentsObject(L
 
     const ptrdiff_t frameOffset = StackFrame::offsetOfArgumentsObject();
 
     masm.loadPtr(Address(ToRegister(frame), frameOffset), ToRegister(object));
     return true;
 }
 
 bool
+CodeGenerator::visitOsrValue(LOsrValue *value)
+{
+    const LAllocation *frame   = value->getOperand(0);
+    const ValueOperand out     = ToOutValue(value);
+
+    const ptrdiff_t frameOffset = value->mir()->frameOffset();
+
+    masm.loadValue(Address(ToRegister(frame), frameOffset), out);
+    return true;
+}
+
+bool
+CodeGenerator::visitOsrReturnValue(LOsrReturnValue *lir)
+{
+    const LAllocation *frame   = lir->getOperand(0);
+    const ValueOperand out     = ToOutValue(lir);
+
+    Address flags = Address(ToRegister(frame), StackFrame::offsetOfFlags());
+    Address retval = Address(ToRegister(frame), StackFrame::offsetOfReturnValue());
+
+    masm.moveValue(UndefinedValue(), out);
+
+    Label done;
+    masm.branchTest32(Assembler::Zero, flags, Imm32(StackFrame::HAS_RVAL), &done);
+    masm.loadValue(retval, out);
+    masm.bind(&done);
+
+    return true;
+}
+
+bool
 CodeGenerator::visitStackArgT(LStackArgT *lir)
 {
     const LAllocation *arg = lir->getArgument();
     MIRType argType = lir->mir()->getArgument()->type();
     uint32_t argslot = lir->argslot();
 
     int32_t stack_offset = StackOffsetOfPassedArg(argslot);
     Address dest(StackPointer, stack_offset);
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -64,16 +64,18 @@ class CodeGenerator : public CodeGenerat
     bool visitParameter(LParameter *lir);
     bool visitCallee(LCallee *lir);
     bool visitStart(LStart *lir);
     bool visitReturn(LReturn *ret);
     bool visitDefVar(LDefVar *lir);
     bool visitDefFun(LDefFun *lir);
     bool visitOsrEntry(LOsrEntry *lir);
     bool visitOsrScopeChain(LOsrScopeChain *lir);
+    bool visitOsrValue(LOsrValue *lir);
+    bool visitOsrReturnValue(LOsrReturnValue *lir);
     bool visitOsrArgumentsObject(LOsrArgumentsObject *lir);
     bool visitStackArgT(LStackArgT *lir);
     bool visitStackArgV(LStackArgV *lir);
     bool visitMoveGroup(LMoveGroup *group);
     bool visitValueToInt32(LValueToInt32 *lir);
     bool visitValueToDouble(LValueToDouble *lir);
     bool visitValueToFloat32(LValueToFloat32 *lir);
     bool visitFloat32ToDouble(LFloat32ToDouble *lir);
--- a/js/src/jit/CompileInfo.h
+++ b/js/src/jit/CompileInfo.h
@@ -12,24 +12,33 @@
 #include "jit/Registers.h"
 
 namespace js {
 namespace jit {
 
 inline unsigned
 StartArgSlot(JSScript *script, JSFunction *fun)
 {
-    // First slot is for scope chain.
-    // Second one may be for arguments object.
-    return 1 + (script->argumentsHasVarBinding() ? 1 : 0);
+    // Reserved slots:
+    // Slot 0: Scope chain.
+    // Slot 1: Return value.
+
+    // When needed:
+    // Slot 2: Argumentsobject.
+
+    return 2 + (script->argumentsHasVarBinding() ? 1 : 0);
 }
 
 inline unsigned
 CountArgSlots(JSScript *script, JSFunction *fun)
 {
+    // Slot x + 0: This value.
+    // Slot x + 1: Argument 1.
+    // ...
+    // Slot x + n: Argument n.
     return StartArgSlot(script, fun) + (fun ? fun->nargs + 1 : 0);
 }
 
 // Contains information about the compilation source for IR being generated.
 class CompileInfo
 {
   public:
     CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
@@ -127,37 +136,49 @@ class CompileInfo
         return GetSrcNote(gsn, script(), pc);
     }
 
     // Total number of slots: args, locals, and stack.
     unsigned nslots() const {
         return nslots_;
     }
 
+    // Number of slots needed for Scope chain, return value,
+    // maybe argumentsobject and this value.
+    unsigned nimplicit() const {
+        return nimplicit_;
+    }
+    // Number of arguments (without counting this value).
     unsigned nargs() const {
         return nargs_;
     }
+    // Number of slots needed for local variables.
     unsigned nlocals() const {
         return nlocals_;
     }
     unsigned ninvoke() const {
         return nslots_ - nstack_;
     }
 
     uint32_t scopeChainSlot() const {
         JS_ASSERT(script());
         return 0;
     }
+    uint32_t returnValueSlot() const {
+        JS_ASSERT(script());
+        return 1;
+    }
     uint32_t argsObjSlot() const {
         JS_ASSERT(hasArguments());
-        return 1;
+        return 2;
     }
     uint32_t thisSlot() const {
         JS_ASSERT(fun());
-        return hasArguments() ? 2 : 1;
+        JS_ASSERT(nimplicit_ > 0);
+        return nimplicit_ - 1;
     }
     uint32_t firstArgSlot() const {
         return nimplicit_;
     }
     uint32_t argSlotUnchecked(uint32_t i) const {
         // During initialization, some routines need to get at arg
         // slots regardless of how regular argument access is done.
         JS_ASSERT(i < nargs_);
@@ -179,26 +200,27 @@ class CompileInfo
     uint32_t firstStackSlot() const {
         return firstLocalSlot() + nlocals();
     }
     uint32_t stackSlot(uint32_t i) const {
         return firstStackSlot() + i;
     }
 
     uint32_t startArgSlot() const {
-        JS_ASSERT(scopeChainSlot() == 0);
+        JS_ASSERT(script());
         return StartArgSlot(script(), fun());
     }
     uint32_t endArgSlot() const {
-        JS_ASSERT(scopeChainSlot() == 0);
+        JS_ASSERT(script());
         return CountArgSlots(script(), fun());
     }
 
     uint32_t totalSlots() const {
-        return 2 + (hasArguments() ? 1 : 0) + nargs() + nlocals();
+        JS_ASSERT(script() && fun());
+        return nimplicit() + nargs() + nlocals();
     }
 
     bool isSlotAliased(uint32_t index) const {
         if (fun() && index == thisSlot())
             return false;
 
         uint32_t arg = index - firstArgSlot();
         if (arg < nargs()) {
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -666,17 +666,17 @@ IonCode::finalize(FreeOp *fop)
     // Make sure this can't race with an interrupting thread, which may try
     // to read the contents of the pool we are releasing references in.
     JS_ASSERT(fop->runtime()->currentThreadOwnsOperationCallbackLock());
 
 #ifdef DEBUG
     // Buffer can be freed at any time hereafter. Catch use-after-free bugs.
     // Don't do this if the Ion code is protected, as the signal handler will
     // deadlock trying to reaqcuire the operation callback lock.
-    if (!fop->runtime()->ionRuntime()->ionCodeProtected())
+    if (fop->runtime()->ionRuntime() && !fop->runtime()->ionRuntime()->ionCodeProtected())
         JS_POISON(code_, JS_FREE_PATTERN, bufferSize_);
 #endif
 
     // Horrible hack: if we are using perf integration, we don't
     // want to reuse code addresses, so we just leak the memory instead.
     if (PerfEnabled())
         return;
 
@@ -1589,17 +1589,17 @@ IonCompile(JSContext *cx, JSScript *scri
     if (!graph)
         return AbortReason_Alloc;
 
     CompileInfo *info = alloc->new_<CompileInfo>(script, script->function(), osrPc, constructing,
                                                  executionMode);
     if (!info)
         return AbortReason_Alloc;
 
-    BaselineInspector inspector(cx, script);
+    BaselineInspector inspector(script);
 
     AutoFlushCache afc("IonCompile", cx->runtime()->ionRuntime());
 
     AutoTempAllocatorRooter root(cx, temp);
     types::CompilerConstraintList *constraints = types::NewCompilerConstraintList();
     if (!constraints)
         return AbortReason_Alloc;
 
@@ -1757,17 +1757,17 @@ CanIonCompileScript(JSContext *cx, Handl
 static MethodStatus
 Compile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc,
         bool constructing, ExecutionMode executionMode)
 {
     JS_ASSERT(jit::IsIonEnabled(cx));
     JS_ASSERT(jit::IsBaselineEnabled(cx));
     JS_ASSERT_IF(osrPc != nullptr, (JSOp)*osrPc == JSOP_LOOPENTRY);
 
-    if (executionMode == SequentialExecution && !script->hasBaselineScript())
+    if (!script->hasBaselineScript())
         return Method_Skipped;
 
     if (cx->compartment()->debugMode()) {
         IonSpew(IonSpew_Abort, "debugging");
         return Method_CantCompile;
     }
 
     if (!CheckScript(cx, script, bool(osrPc))) {
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.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 "jit/IonAnalysis.h"
 
 #include "jsanalyze.h"
 
 #include "jit/BaselineInspector.h"
+#include "jit/BaselineJIT.h"
 #include "jit/Ion.h"
 #include "jit/IonBuilder.h"
 #include "jit/LIR.h"
 #include "jit/Lowering.h"
 #include "jit/MIRGraph.h"
 
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
@@ -2060,49 +2061,55 @@ bool
 jit::AnalyzeNewScriptProperties(JSContext *cx, JSFunction *fun,
                                 types::TypeObject *type, HandleObject baseobj,
                                 Vector<types::TypeNewScript::Initializer> *initializerList)
 {
     // When invoking 'new' on the specified script, try to find some properties
     // which will definitely be added to the created object before it has a
     // chance to escape and be accessed elsewhere.
 
-    if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx)) {
-        return false;
-    }
-
-    if (!fun->nonLazyScript()->compileAndGo)
-        return true;
-
-    if (!fun->nonLazyScript()->ensureHasTypes(cx))
+    if (fun->isInterpretedLazy() && !fun->getOrCreateScript(cx))
         return false;
 
-    types::TypeScript::SetThis(cx, fun->nonLazyScript(), types::Type::ObjectType(type));
+    RootedScript script(cx, fun->nonLazyScript());
+
+    if (!script->compileAndGo || !script->canBaselineCompile())
+        return true;
 
     Vector<PropertyName *> accessedProperties(cx);
 
     LifoAlloc alloc(types::TypeZone::TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
 
     TempAllocator temp(&alloc);
     IonContext ictx(cx, &temp);
 
     types::AutoEnterAnalysis enter(cx);
 
-    if (!fun->nonLazyScript()->ensureRanAnalysis(cx))
-        return false;
+    if (!cx->compartment()->ensureIonCompartmentExists(cx))
+        return Method_Error;
+
+    if (!script->hasBaselineScript()) {
+        MethodStatus status = BaselineCompile(cx, script);
+        if (status == Method_Error)
+            return false;
+        if (status != Method_Compiled)
+            return true;
+    }
+
+    types::TypeScript::SetThis(cx, script, types::Type::ObjectType(type));
 
     MIRGraph graph(&temp);
-    CompileInfo info(fun->nonLazyScript(), fun,
+    CompileInfo info(script, fun,
                      /* osrPc = */ nullptr, /* constructing = */ false,
                      DefinitePropertiesAnalysis);
 
     AutoTempAllocatorRooter root(cx, &temp);
 
     types::CompilerConstraintList *constraints = types::NewCompilerConstraintList();
-    BaselineInspector inspector(cx, fun->nonLazyScript());
+    BaselineInspector inspector(script);
     IonBuilder builder(cx, &temp, &graph, constraints,
                        &inspector, &info, /* baselineFrame = */ nullptr);
 
     if (!builder.build()) {
         if (builder.abortReason() == AbortReason_Alloc)
             return false;
         return true;
     }
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -61,16 +61,18 @@ IonBuilder::IonBuilder(JSContext *cx, Te
     failedBoundsCheck_(info->script()->failedBoundsCheck),
     failedShapeGuard_(info->script()->failedShapeGuard),
     nonStringIteration_(false),
     lazyArguments_(nullptr),
     inlineCallInfo_(nullptr)
 {
     script_.init(info->script());
     pc = info->startPC();
+
+    JS_ASSERT(script()->hasBaselineScript());
 }
 
 void
 IonBuilder::clearForBackEnd()
 {
     cx = nullptr;
     baselineFrame_ = nullptr;
 
@@ -274,17 +276,17 @@ IonBuilder::canInlineTarget(JSFunction *
     if (target->getParent() != &script()->global()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to scope mismatch");
         return false;
     }
 
     // Allow constructing lazy scripts when performing the definite properties
     // analysis, as baseline has not been used to warm the caller up yet.
     if (target->isInterpretedLazy() && info().executionMode() == DefinitePropertiesAnalysis) {
-        if (!target->getOrCreateScript(cx))
+        if (!target->getOrCreateScript(context()))
             return false;
     }
 
     if (!target->hasScript()) {
         IonSpew(IonSpew_Inlining, "Cannot inline due to lack of Non-Lazy script");
         return false;
     }
 
@@ -296,18 +298,18 @@ IonBuilder::canInlineTarget(JSFunction *
     JSScript *inlineScript = target->nonLazyScript();
     ExecutionMode executionMode = info().executionMode();
     if (!CanIonCompile(inlineScript, executionMode)) {
         IonSpew(IonSpew_Inlining, "%s:%d Cannot inline due to disable Ion compilation",
                                   inlineScript->filename(), inlineScript->lineno);
         return false;
     }
 
-    // Don't inline functions which don't have baseline scripts compiled for them.
-    if (executionMode == SequentialExecution && !inlineScript->hasBaselineScript()) {
+    // Don't inline functions which don't have baseline scripts.
+    if (!inlineScript->hasBaselineScript()) {
         IonSpew(IonSpew_Inlining, "%s:%d Cannot inline target with no baseline jitcode",
                                   inlineScript->filename(), inlineScript->lineno);
         return false;
     }
 
     // Allow inlining of recursive calls, but only one level deep.
     IonBuilder *builder = callerBuilder_;
     while (builder) {
@@ -508,26 +510,23 @@ IonBuilder::pushLoop(CFGState::State ini
     state.loop.initialStopAt = stopAt;
     state.loop.loopHead = loopHead;
     return cfgStack_.append(state);
 }
 
 bool
 IonBuilder::init()
 {
-    if (!script()->ensureHasBytecodeTypeMap(cx))
-        return false;
-
     if (!types::TypeScript::FreezeTypeSets(constraints(), script(),
                                            &thisTypes, &argTypes, &typeArray))
     {
         return false;
     }
 
-    if (!analysis().init(cx))
+    if (!analysis().init(gsn))
         return false;
 
     return true;
 }
 
 bool
 IonBuilder::build()
 {
@@ -550,21 +549,24 @@ IonBuilder::build()
         current->add(undef);
         current->initSlot(info().localSlot(i), undef);
     }
 
     // Initialize something for the scope chain. We can bail out before the
     // start instruction, but the snapshot is encoded *at* the start
     // instruction, which means generating any code that could load into
     // registers is illegal.
-    {
-        MInstruction *scope = MConstant::New(UndefinedValue());
-        current->add(scope);
-        current->initSlot(info().scopeChainSlot(), scope);
-    }
+    MInstruction *scope = MConstant::New(UndefinedValue());
+    current->add(scope);
+    current->initSlot(info().scopeChainSlot(), scope);
+
+    // Initialize the return value.
+    MInstruction *returnValue = MConstant::New(UndefinedValue());
+    current->add(returnValue);
+    current->initSlot(info().returnValueSlot(), returnValue);
 
     // Initialize the arguments object slot to undefined if necessary.
     if (info().hasArguments()) {
         MInstruction *argsObj = MConstant::New(UndefinedValue());
         current->add(argsObj);
         current->initSlot(info().argsObjSlot(), argsObj);
     }
 
@@ -706,21 +708,24 @@ IonBuilder::buildInline(IonBuilder *call
                                                 MFunctionBoundary::Inline_Enter,
                                                 inliningDepth_));
 
     predecessor->end(MGoto::New(current));
     if (!current->addPredecessorWithoutPhis(predecessor))
         return false;
 
     // Initialize scope chain slot to Undefined.  It's set later by |initScopeChain|.
-    {
-        MInstruction *scope = MConstant::New(UndefinedValue());
-        current->add(scope);
-        current->initSlot(info().scopeChainSlot(), scope);
-    }
+    MInstruction *scope = MConstant::New(UndefinedValue());
+    current->add(scope);
+    current->initSlot(info().scopeChainSlot(), scope);
+
+    // Initialize |return value| slot.
+    MInstruction *returnValue = MConstant::New(UndefinedValue());
+    current->add(returnValue);
+    current->initSlot(info().returnValueSlot(), returnValue);
 
     // Initialize |arguments| slot.
     if (info().hasArguments()) {
         MInstruction *argsObj = MConstant::New(UndefinedValue());
         current->add(argsObj);
         current->initSlot(info().argsObjSlot(), argsObj);
     }
 
@@ -1192,16 +1197,18 @@ IonBuilder::traverseBytecode()
               case JSOP_POP:
               case JSOP_POPN:
               case JSOP_DUP:
               case JSOP_DUP2:
               case JSOP_PICK:
               case JSOP_SWAP:
               case JSOP_SETARG:
               case JSOP_SETLOCAL:
+              case JSOP_SETRVAL:
+              case JSOP_POPV:
               case JSOP_VOID:
                 // Don't require SSA uses for values popped by these ops.
                 break;
 
               case JSOP_POS:
               case JSOP_TOID:
                 // These ops may leave their input on the stack without setting
                 // the Folded flag. If this value will be popped immediately,
@@ -1241,16 +1248,17 @@ IonBuilder::snoopControlFlow(JSOp op)
       case JSOP_NOP:
         return maybeLoop(op, info().getNote(gsn, pc));
 
       case JSOP_POP:
         return maybeLoop(op, info().getNote(gsn, pc));