Merge inbound to m-c. FIREFOX_AURORA_30_BASE
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 17 Mar 2014 13:16:53 -0400
changeset 184933 83c9853e136451474dfa6d1aaa60a7fca7d2d83a
parent 184918 803a735d9cf24eb698ff6fc3ff53bf25f76409ba (current diff)
parent 184932 233a33ca8ef81fca3d2b08f5f1a085ab6385fd39 (diff)
child 184934 85031ae07876659c28cf38d7fec89050aa515f49
child 185967 4811c0f6bf3faa76981665514b88400c716133ec
push idunknown
push userunknown
push dateunknown
milestone30.0a1
Merge inbound to m-c.
js/src/jit-test/tests/ion/bug980960.js
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -39,18 +39,22 @@ ifneq (,$(source_repo))
 endif
 
 endif
 
 # Put a useful .gdbinit in the bin directory, to be picked up automatically
 # by GDB when we debug executables there.
 # NOTE: Keep .gdbinit in the topsrcdir for people who run gdb from the topsrcdir.
 GDBINIT_FILES := $(topsrcdir)/.gdbinit
+GDBINIT_OBJDIR_FILES = $(topsrcdir)/.gdbinit
 GDBINIT_DEST = $(FINAL_TARGET)
-INSTALL_TARGETS += GDBINIT
+
+# needs to be absolute to be distinct from $(topsrcdir)/.gdbinit
+GDBINIT_OBJDIR_DEST = $(abspath $(DEPTH))
+INSTALL_TARGETS += GDBINIT GDBINIT_OBJDIR
 
 # Put a .lldbinit in the bin directory and the objdir, to be picked up
 # automatically by LLDB when we debug executables using either of those two
 # directories as the current working directory.  The .lldbinit file will
 # load $(topsrcdir)/.lldbinit, which is where the actual debugging commands are.
 LLDBINIT_OBJDIR := .lldbinit.in
 LLDBINIT_OBJDIR_PATH = $(DEPTH)
 LLDBINIT_OBJDIR_FLAGS += -Dtopsrcdir=$(abspath $(topsrcdir))
--- a/configure.in
+++ b/configure.in
@@ -7883,17 +7883,23 @@ if test "$USE_FC_FREETYPE"; then
         fi
     ])
 fi
 
 dnl ========================================================
 dnl Check for pixman and cairo
 dnl ========================================================
 
-MOZ_TREE_CAIRO=1
+if test "$MOZ_WIDGET_TOOLKIT" = "gtk3" ; then
+  # cairo-gtk3 can be build with system-cairo only
+  MOZ_TREE_CAIRO=
+else
+  MOZ_TREE_CAIRO=1
+fi
+
 MOZ_ARG_ENABLE_BOOL(system-cairo,
 [  --enable-system-cairo   Use system cairo (located with pkgconfig)],
 MOZ_TREE_CAIRO=,
 MOZ_TREE_CAIRO=1 )
 
 MOZ_TREE_PIXMAN=1
 MOZ_ARG_ENABLE_BOOL(system-pixman,
 [ --enable-system-pixman Use system pixman (located with pkgconfig)],
@@ -7973,16 +7979,19 @@ if test "$MOZ_TREE_CAIRO"; then
 
         MOZ_CHECK_HEADER(d3d9.h, MOZ_ENABLE_D3D9_LAYER=1)
 
         dnl D3D10 Layers depend on D2D Surfaces.
         if test -n "$WIN32_D2D_SURFACE_FEATURE"; then
           MOZ_CHECK_HEADER(d3d10.h, MOZ_ENABLE_D3D10_LAYER=1)
         fi
         ;;
+      gtk3)
+        AC_MSG_ERROR([cairo-gtk3 toolkit is incompatible with in-tree cairo. Please add --enable-system-cairo to your build config.])
+        ;;
     esac
     if test "$USE_FC_FREETYPE"; then
         FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
     fi
     AC_SUBST(MOZ_ENABLE_CAIRO_FT)
     AC_SUBST(MOZ_ENABLE_DWRITE_FONT)
     AC_SUBST(MOZ_ENABLE_D2D_SURFACE)
     AC_SUBST(MOZ_ENABLE_D3D9_LAYER)
--- a/content/canvas/src/WebGLBuffer.cpp
+++ b/content/canvas/src/WebGLBuffer.cpp
@@ -1,17 +1,19 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "WebGLBuffer.h"
-#include "WebGLContext.h"
+
 #include "GLContext.h"
 #include "mozilla/dom/WebGLRenderingContextBinding.h"
+#include "WebGLContext.h"
+#include "WebGLElementArrayCache.h"
 
 using namespace mozilla;
 
 WebGLBuffer::WebGLBuffer(WebGLContext *context)
     : WebGLContextBoundObject(context)
     , mHasEverBeenBound(false)
     , mByteLength(0)
     , mTarget(LOCAL_GL_NONE)
@@ -50,16 +52,32 @@ WebGLBuffer::ElementArrayCacheBufferData
 }
 
 void
 WebGLBuffer::ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes) {
     if (mTarget == LOCAL_GL_ELEMENT_ARRAY_BUFFER)
         mCache->BufferSubData(pos, ptr, update_size_in_bytes);
 }
 
+size_t
+WebGLBuffer::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+{
+    size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
+    return aMallocSizeOf(this) + sizeOfCache;
+}
+
+bool
+WebGLBuffer::Validate(GLenum type, uint32_t max_allowed,
+                      size_t first, size_t count,
+                      uint32_t* out_upperBound)
+{
+    return mCache->Validate(type, max_allowed, first, count, out_upperBound);
+}
+
+
 JSObject*
 WebGLBuffer::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
     return dom::WebGLBufferBinding::Wrap(cx, scope, this);
 }
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(WebGLBuffer)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLBuffer, AddRef)
--- a/content/canvas/src/WebGLBuffer.h
+++ b/content/canvas/src/WebGLBuffer.h
@@ -1,24 +1,22 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 WEBGLBUFFER_H_
 #define WEBGLBUFFER_H_
 
-#include "WebGLObjectModel.h"
-#include "WebGLElementArrayCache.h"
 #include "GLDefs.h"
-
-#include "nsWrapperCache.h"
-
 #include "mozilla/LinkedList.h"
 #include "mozilla/MemoryReporting.h"
+#include "nsWrapperCache.h"
+#include "WebGLObjectModel.h"
+#include "WebGLTypes.h"
 
 namespace mozilla {
 
 class WebGLElementArrayCache;
 
 class WebGLBuffer MOZ_FINAL
     : public nsWrapperCache
     , public WebGLRefCountedObject<WebGLBuffer>
@@ -27,38 +25,34 @@ class WebGLBuffer MOZ_FINAL
 {
 public:
     WebGLBuffer(WebGLContext *context);
 
     ~WebGLBuffer();
 
     void Delete();
 
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
-        size_t sizeOfCache = mCache ? mCache->SizeOfIncludingThis(aMallocSizeOf) : 0;
-        return aMallocSizeOf(this) + sizeOfCache;
-    }
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     GLuint GLName() const { return mGLName; }
     WebGLsizeiptr ByteLength() const { return mByteLength; }
     GLenum Target() const { return mTarget; }
 
     void SetByteLength(WebGLsizeiptr byteLength) { mByteLength = byteLength; }
 
     void SetTarget(GLenum target);
 
     bool ElementArrayCacheBufferData(const void* ptr, size_t buffer_size_in_bytes);
 
     void ElementArrayCacheBufferSubData(size_t pos, const void* ptr, size_t update_size_in_bytes);
 
-    bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count) {
-        return mCache->Validate(type, max_allowed, first, count);
-    }
+    bool Validate(GLenum type, uint32_t max_allowed, size_t first, size_t count,
+                  uint32_t* out_upperBound);
 
     WebGLContext *GetParentObject() const {
         return Context();
     }
 
     virtual JSObject* WrapObject(JSContext *cx,
                                  JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
 
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -782,17 +782,18 @@ private:
         mBufferFetchingIsVerified = false;
         mBufferFetchingHasPerVertex = false;
         mMaxFetchedVertices = 0;
         mMaxFetchedInstances = 0;
     }
 
     bool DrawArrays_check(GLint first, GLsizei count, GLsizei primcount, const char* info);
     bool DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset,
-                            GLsizei primcount, const char* info);
+                            GLsizei primcount, const char* info,
+                            GLuint* out_upperBound = nullptr);
     bool DrawInstanced_check(const char* info);
     void Draw_cleanup();
 
     void VertexAttrib1fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
     void VertexAttrib2fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
     void VertexAttrib3fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
     void VertexAttrib4fv_base(GLuint idx, uint32_t arrayLength, const GLfloat* ptr);
 
--- a/content/canvas/src/WebGLContextVertices.cpp
+++ b/content/canvas/src/WebGLContextVertices.cpp
@@ -1,24 +1,26 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 "WebGLContext.h"
+
+#include "GLContext.h"
+#include "mozilla/CheckedInt.h"
 #include "WebGLBuffer.h"
-#include "WebGLVertexAttribData.h"
-#include "WebGLVertexArray.h"
-#include "WebGLTexture.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLProgram.h"
 #include "WebGLRenderbuffer.h"
-#include "WebGLFramebuffer.h"
+#include "WebGLShader.h"
+#include "WebGLTexture.h"
 #include "WebGLUniformInfo.h"
-#include "WebGLShader.h"
-#include "WebGLProgram.h"
-#include "GLContext.h"
+#include "WebGLVertexArray.h"
+#include "WebGLVertexAttribData.h"
 
 using namespace mozilla;
 using namespace dom;
 
 // For a Tegra workaround.
 static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
 
 void
@@ -549,17 +551,19 @@ WebGLContext::DrawArraysInstanced(GLenum
 
     SetupContextLossTimer();
     gl->fDrawArraysInstanced(mode, first, count, primcount);
 
     Draw_cleanup();
 }
 
 bool
-WebGLContext::DrawElements_check(GLsizei count, GLenum type, WebGLintptr byteOffset, GLsizei primcount, const char* info)
+WebGLContext::DrawElements_check(GLsizei count, GLenum type,
+                                 WebGLintptr byteOffset, GLsizei primcount,
+                                 const char* info, GLuint* out_upperBound)
 {
     if (count < 0 || byteOffset < 0) {
         ErrorInvalidValue("%s: negative count or offset", info);
         return false;
     }
 
     if (primcount < 0) {
         ErrorInvalidValue("%s: negative primcount", info);
@@ -615,38 +619,40 @@ WebGLContext::DrawElements_check(GLsizei
         return false;
     }
 
     if (!mBoundVertexArray->mBoundElementArrayBuffer) {
         ErrorInvalidOperation("%s: must have element array buffer binding", info);
         return false;
     }
 
-    if (!mBoundVertexArray->mBoundElementArrayBuffer->ByteLength()) {
+    WebGLBuffer& elemArrayBuffer = *mBoundVertexArray->mBoundElementArrayBuffer;
+
+    if (!elemArrayBuffer.ByteLength()) {
         ErrorInvalidOperation("%s: bound element array buffer doesn't have any data", info);
         return false;
     }
 
     CheckedInt<GLsizei> checked_neededByteCount = checked_byteCount.toChecked<GLsizei>() + byteOffset;
 
     if (!checked_neededByteCount.isValid()) {
         ErrorInvalidOperation("%s: overflow in byteOffset+byteCount", info);
         return false;
     }
 
-    if (uint32_t(checked_neededByteCount.value()) > mBoundVertexArray->mBoundElementArrayBuffer->ByteLength()) {
+    if (uint32_t(checked_neededByteCount.value()) > elemArrayBuffer.ByteLength()) {
         ErrorInvalidOperation("%s: bound element array buffer is too small for given count and offset", info);
         return false;
     }
 
     if (!ValidateBufferFetching(info))
         return false;
 
     if (!mMaxFetchedVertices ||
-        !mBoundVertexArray->mBoundElementArrayBuffer->Validate(type, mMaxFetchedVertices - 1, first, count))
+        !elemArrayBuffer.Validate(type, mMaxFetchedVertices - 1, first, count, out_upperBound))
     {
         ErrorInvalidOperation(
                               "%s: bound vertex attribute buffers do not have sufficient "
                               "size for given indices from the bound element array", info);
         return false;
     }
 
     if (uint32_t(primcount) > mMaxFetchedInstances) {
@@ -668,36 +674,46 @@ WebGLContext::DrawElements_check(GLsizei
     }
     BindFakeBlackTextures();
 
     return true;
 }
 
 void
 WebGLContext::DrawElements(GLenum mode, GLsizei count, GLenum type,
-                               WebGLintptr byteOffset)
+                           WebGLintptr byteOffset)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateDrawModeEnum(mode, "drawElements: mode"))
         return;
 
-    if (!DrawElements_check(count, type, byteOffset, 1, "drawElements"))
+    GLuint upperBound = UINT_MAX;
+    if (!DrawElements_check(count, type, byteOffset, 1, "drawElements",
+                            &upperBound))
+    {
         return;
+    }
 
     SetupContextLossTimer();
-    gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
+
+    if (gl->IsSupported(gl::GLFeature::draw_range_elements)) {
+        gl->fDrawRangeElements(mode, 0, upperBound,
+                               count, type, reinterpret_cast<GLvoid*>(byteOffset));
+    } else {
+        gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
+    }
 
     Draw_cleanup();
 }
 
 void
 WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
-                                        WebGLintptr byteOffset, GLsizei primcount)
+                                    WebGLintptr byteOffset, GLsizei primcount)
 {
     if (IsContextLost())
         return;
 
     if (!ValidateDrawModeEnum(mode, "drawElementsInstanced: mode"))
         return;
 
     if (!DrawElements_check(count, type, byteOffset, primcount, "drawElementsInstanced"))
--- a/content/canvas/src/WebGLElementArrayCache.cpp
+++ b/content/canvas/src/WebGLElementArrayCache.cpp
@@ -11,16 +11,34 @@
 
 #include <cstdlib>
 #include <cstring>
 #include <limits>
 #include <algorithm>
 
 namespace mozilla {
 
+static void
+SetUpperBound(uint32_t* out_upperBound, uint32_t newBound)
+{
+  if (!out_upperBound)
+      return;
+
+  *out_upperBound = newBound;
+}
+
+static void
+UpdateUpperBound(uint32_t* out_upperBound, uint32_t newBound)
+{
+  if (!out_upperBound)
+      return;
+
+  *out_upperBound = std::max(*out_upperBound, newBound);
+}
+
 /*
  * WebGLElementArrayCacheTree contains most of the implementation of WebGLElementArrayCache,
  * which performs WebGL element array buffer validation for drawElements.
  *
  * Attention: Here lie nontrivial data structures, bug-prone algorithms, and non-canonical tweaks!
  * Whence the explanatory comments, and compiled unit test.
  *
  * *** What problem are we solving here? ***
@@ -222,44 +240,52 @@ public:
   static size_t FirstElementUnderSameLeaf(size_t element) {
     return element & ~sElementsPerLeafMask;
   }
 
   static size_t NextMultipleOfElementsPerLeaf(size_t numElements) {
     return ((numElements - 1) | sElementsPerLeafMask) + 1;
   }
 
-  bool Validate(T maxAllowed, size_t firstLeaf, size_t lastLeaf) {
+  bool Validate(T maxAllowed, size_t firstLeaf, size_t lastLeaf,
+                uint32_t* out_upperBound)
+  {
     MOZ_ASSERT(!mInvalidated);
 
     size_t firstTreeIndex = TreeIndexForLeaf(firstLeaf);
     size_t lastTreeIndex  = TreeIndexForLeaf(lastLeaf);
 
     while (true) {
       // given that we tweak these values in nontrivial ways, it doesn't hurt to do
       // this sanity check
       MOZ_ASSERT(firstTreeIndex <= lastTreeIndex);
 
       // final case where there is only 1 node to validate at the current tree level
       if (lastTreeIndex == firstTreeIndex) {
-        return mTreeData[firstTreeIndex] <= maxAllowed;
+        const T& curData = mTreeData[firstTreeIndex];
+        UpdateUpperBound(out_upperBound, curData);
+        return curData <= maxAllowed;
       }
 
       // if the first node at current tree level is a right node, handle it individually
       // and replace it with its right neighbor, which is a left node
       if (IsRightNode(firstTreeIndex)) {
-        if (mTreeData[firstTreeIndex] > maxAllowed)
+        const T& curData = mTreeData[firstTreeIndex];
+        UpdateUpperBound(out_upperBound, curData);
+        if (curData > maxAllowed)
           return false;
         firstTreeIndex = RightNeighborNode(firstTreeIndex);
       }
 
       // if the last node at current tree level is a left node, handle it individually
       // and replace it with its left neighbor, which is a right node
       if (IsLeftNode(lastTreeIndex)) {
-        if (mTreeData[lastTreeIndex] > maxAllowed)
+        const T& curData = mTreeData[lastTreeIndex];
+        UpdateUpperBound(out_upperBound, curData);
+        if (curData > maxAllowed)
           return false;
         lastTreeIndex = LeftNeighborNode(lastTreeIndex);
       }
 
       // at this point it can happen that firstTreeIndex and lastTreeIndex "crossed" each
       // other. That happens if firstTreeIndex was a right node and lastTreeIndex was its
       // right neighor: in that case, both above tweaks happened and as a result, they ended
       // up being swapped: lastTreeIndex is now the _left_ neighbor of firstTreeIndex.
@@ -485,20 +511,28 @@ void WebGLElementArrayCache::InvalidateT
     mUint8Tree->Invalidate(firstByte, lastByte);
   if (mUint16Tree)
     mUint16Tree->Invalidate(firstByte, lastByte);
   if (mUint32Tree)
     mUint32Tree->Invalidate(firstByte, lastByte);
 }
 
 template<typename T>
-bool WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement, size_t countElements) {
+bool
+WebGLElementArrayCache::Validate(uint32_t maxAllowed, size_t firstElement,
+                                 size_t countElements, uint32_t* out_upperBound)
+{
+  SetUpperBound(out_upperBound, 0);
+
   // if maxAllowed is >= the max T value, then there is no way that a T index could be invalid
-  if (maxAllowed >= std::numeric_limits<T>::max())
+  uint32_t maxTSize = std::numeric_limits<T>::max();
+  if (maxAllowed >= maxTSize) {
+    SetUpperBound(out_upperBound, maxTSize);
     return true;
+  }
 
   T maxAllowedT(maxAllowed);
 
   // integer overflow must have been handled earlier, so we assert that maxAllowedT
   // is exactly the max allowed value.
   MOZ_ASSERT(uint32_t(maxAllowedT) == maxAllowed);
 
   if (!mByteSize || !countElements)
@@ -510,61 +544,76 @@ bool WebGLElementArrayCache::Validate(ui
   }
 
   size_t lastElement = firstElement + countElements - 1;
 
   tree->Update();
 
   // fast exit path when the global maximum for the whole element array buffer
   // falls in the allowed range
-  if (tree->GlobalMaximum() <= maxAllowedT)
+  T globalMax = tree->GlobalMaximum();
+  if (globalMax <= maxAllowedT)
   {
+    SetUpperBound(out_upperBound, globalMax);
     return true;
   }
 
   const T* elements = Elements<T>();
 
   // before calling tree->Validate, we have to validate ourselves the boundaries of the elements span,
   // to round them to the nearest multiple of sElementsPerLeaf.
   size_t firstElementAdjustmentEnd = std::min(lastElement,
                                             tree->LastElementUnderSameLeaf(firstElement));
   while (firstElement <= firstElementAdjustmentEnd) {
-    if (elements[firstElement] > maxAllowedT)
+    const T& curData = elements[firstElement];
+    UpdateUpperBound(out_upperBound, curData);
+    if (curData > maxAllowedT)
       return false;
     firstElement++;
   }
   size_t lastElementAdjustmentEnd = std::max(firstElement,
                                            tree->FirstElementUnderSameLeaf(lastElement));
   while (lastElement >= lastElementAdjustmentEnd) {
-    if (elements[lastElement] > maxAllowedT)
+    const T& curData = elements[lastElement];
+    UpdateUpperBound(out_upperBound, curData);
+    if (curData > maxAllowedT)
       return false;
     lastElement--;
   }
 
   // at this point, for many tiny validations, we're already done.
   if (firstElement > lastElement)
     return true;
 
   // general case
   return tree->Validate(maxAllowedT,
                         tree->LeafForElement(firstElement),
-                        tree->LeafForElement(lastElement));
+                        tree->LeafForElement(lastElement),
+                        out_upperBound);
 }
 
-bool WebGLElementArrayCache::Validate(GLenum type, uint32_t maxAllowed, size_t firstElement, size_t countElements) {
+bool
+WebGLElementArrayCache::Validate(GLenum type, uint32_t maxAllowed,
+                                 size_t firstElement, size_t countElements,
+                                 uint32_t* out_upperBound)
+{
   if (type == LOCAL_GL_UNSIGNED_BYTE)
-    return Validate<uint8_t>(maxAllowed, firstElement, countElements);
+    return Validate<uint8_t>(maxAllowed, firstElement, countElements, out_upperBound);
   if (type == LOCAL_GL_UNSIGNED_SHORT)
-    return Validate<uint16_t>(maxAllowed, firstElement, countElements);
+    return Validate<uint16_t>(maxAllowed, firstElement, countElements, out_upperBound);
   if (type == LOCAL_GL_UNSIGNED_INT)
-    return Validate<uint32_t>(maxAllowed, firstElement, countElements);
+    return Validate<uint32_t>(maxAllowed, firstElement, countElements, out_upperBound);
+
+  MOZ_ASSERT(false, "Invalid type.");
   return false;
 }
 
-size_t WebGLElementArrayCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
+size_t
+WebGLElementArrayCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+{
   size_t uint8TreeSize  = mUint8Tree  ? mUint8Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
   size_t uint16TreeSize = mUint16Tree ? mUint16Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
   size_t uint32TreeSize = mUint32Tree ? mUint32Tree->SizeOfIncludingThis(aMallocSizeOf) : 0;
   return aMallocSizeOf(this) +
           mByteSize +
           uint8TreeSize +
           uint16TreeSize +
           uint32TreeSize;
--- a/content/canvas/src/WebGLElementArrayCache.h
+++ b/content/canvas/src/WebGLElementArrayCache.h
@@ -28,17 +28,18 @@ struct WebGLElementArrayCacheTree;
  * Refer to its code for design comments.
  */
 class WebGLElementArrayCache {
 
 public:
   bool BufferData(const void* ptr, size_t byteSize);
   void BufferSubData(size_t pos, const void* ptr, size_t updateByteSize);
 
-  bool Validate(GLenum type, uint32_t maxAllowed, size_t first, size_t count);
+  bool Validate(GLenum type, uint32_t maxAllowed, size_t first, size_t count,
+                uint32_t* out_upperBound = nullptr);
 
   template<typename T>
   T Element(size_t i) const { return Elements<T>()[i]; }
 
   WebGLElementArrayCache()
     : mUntypedData(nullptr)
     , mByteSize(0)
     , mUint8Tree(nullptr)
@@ -48,17 +49,18 @@ public:
 
   ~WebGLElementArrayCache();
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
 
   template<typename T>
-  bool Validate(uint32_t maxAllowed, size_t first, size_t count);
+  bool Validate(uint32_t maxAllowed, size_t first, size_t count,
+                uint32_t* out_upperBound);
 
   size_t ByteSize() const {
     return mByteSize;
   }
 
   template<typename T>
   const T* Elements() const { return static_cast<const T*>(mUntypedData); }
   template<typename T>
--- a/content/media/TextTrackRegion.h
+++ b/content/media/TextTrackRegion.h
@@ -8,31 +8,38 @@
 #define mozilla_dom_TextTrackRegion_h
 
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsString.h"
 #include "nsWrapperCache.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/TextTrack.h"
+#include "mozilla/Preferences.h"
 
 namespace mozilla {
 namespace dom {
 
 class GlobalObject;
 class TextTrack;
 
 class TextTrackRegion MOZ_FINAL : public nsISupports,
                                   public nsWrapperCache
 {
 public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TextTrackRegion)
 
+  static bool RegionsEnabled(JSContext* cx, JSObject* obj)
+  {
+    return Preferences::GetBool("media.webvtt.enabled") &&
+           Preferences::GetBool("media.webvtt.regions.enabled");
+  }
+
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
 
   nsISupports* GetParentObject() const
   {
     return mParent;
   }
 
--- a/content/media/test/test_texttrackcue.html
+++ b/content/media/test/test_texttrackcue.html
@@ -12,17 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 <p id="display"></p>
 <div id="content">
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 SimpleTest.waitForExplicitFinish();
-SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
+SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true],
+                                   ["media.webvtt.regions.enabled", true]]},
   function() {
     var video = document.createElement("video");
     video.src = "seek.webm";
     video.preload = "auto";
     var trackElement = document.createElement("track");
     trackElement.src = "basic.vtt";
     trackElement.kind = "subtitles";
     document.getElementById("content").appendChild(video);
--- a/content/media/test/test_texttrackregion.html
+++ b/content/media/test/test_texttrackregion.html
@@ -12,17 +12,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 <p id="display"></p>
 <div id="content">
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 SimpleTest.waitForExplicitFinish();
-SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
+SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true],
+                                   ["media.webvtt.regions.enabled", true]]},
   function() {
     var video = document.createElement("video");
     video.src = "seek.webm";
     video.preload = "auto";
     var trackElement = document.createElement("track");
     trackElement.src = "region.vtt";
     trackElement.kind = "subtitles";
     document.getElementById("content").appendChild(video);
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -1113,17 +1113,17 @@ var interfaceNamesInGlobalScope =
     {name: "USSDReceivedEvent", b2g: true, pref: "dom.mobileconnection.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ValidityState",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "VideoStreamTrack",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "VTTCue",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    "VTTRegion",
+    {name: "VTTRegion", pref: "media.webvtt.regions.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WaveShaperNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLActiveInfo",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLBuffer",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "WebGLFramebuffer",
--- a/dom/webidl/VTTCue.webidl
+++ b/dom/webidl/VTTCue.webidl
@@ -27,16 +27,17 @@ enum DirectionSetting {
  Pref="media.webvtt.enabled"]
 interface VTTCue : EventTarget {
   readonly attribute TextTrack? track;
 
   attribute DOMString id;
   attribute double startTime;
   attribute double endTime;
   attribute boolean pauseOnExit;
+  [Pref="media.webvtt.regions.enabled"]
   attribute VTTRegion? region;
   attribute DirectionSetting vertical;
   attribute boolean snapToLines;
   attribute (long or AutoKeyword) line;
   [SetterThrows]
   attribute AlignSetting lineAlign;
   [SetterThrows]
   attribute long position;
--- a/dom/webidl/VTTRegion.webidl
+++ b/dom/webidl/VTTRegion.webidl
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  *  http://dev.w3.org/html5/webvtt/#extension-of-the-texttrack-interface-for-region-support
  */
 
-[Constructor, Pref="media.webvtt.enabled"]
+[Constructor, Func="TextTrackRegion::RegionsEnabled"]
 interface VTTRegion {
            [SetterThrows]
            attribute double width;
 
            attribute long lines;
 
            [SetterThrows]
            attribute double regionAnchorX;
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -133,16 +133,17 @@ static const char *sExtensionNames[] = {
     "GL_EXT_sRGB",
     "GL_EXT_texture_sRGB",
     "GL_ARB_framebuffer_sRGB",
     "GL_EXT_framebuffer_sRGB",
     "GL_KHR_debug",
     "GL_ARB_half_float_pixel",
     "GL_EXT_frag_depth",
     "GL_OES_compressed_ETC1_RGB8_texture",
+    "GL_EXT_draw_range_elements",
     nullptr
 };
 
 static bool
 ParseGLVersion(GLContext* gl, unsigned int* version)
 {
     GLenum error = gl->fGetError();
     if (error != LOCAL_GL_NO_ERROR) {
@@ -1068,16 +1069,30 @@ GLContext::InitWithPrefix(const char *pr
                 mSymbols.fPopDebugGroup        = nullptr;
                 mSymbols.fObjectLabel          = nullptr;
                 mSymbols.fGetObjectLabel       = nullptr;
                 mSymbols.fObjectPtrLabel       = nullptr;
                 mSymbols.fGetObjectPtrLabel    = nullptr;
             }
         }
 
+        if (IsSupported(GLFeature::draw_range_elements)) {
+            SymLoadStruct imageSymbols[] = {
+                { (PRFuncPtr*) &mSymbols.fDrawRangeElements, { "DrawRangeElementsEXT", "DrawRangeElements", nullptr } },
+                { nullptr, { nullptr } },
+            };
+
+            if (!LoadSymbols(&imageSymbols[0], trygl, prefix)) {
+                NS_ERROR("GL supports draw_range_elements without supplying its functions.");
+
+                MarkUnsupported(GLFeature::draw_range_elements);
+                mSymbols.fDrawRangeElements = nullptr;
+            }
+        }
+
         // Load developer symbols, don't fail if we can't find them.
         SymLoadStruct auxSymbols[] = {
                 { (PRFuncPtr*) &mSymbols.fGetTexImage, { "GetTexImage", nullptr } },
                 { (PRFuncPtr*) &mSymbols.fGetTexLevelParameteriv, { "GetTexLevelParameteriv", nullptr } },
                 { nullptr, { nullptr } },
         };
         bool warnOnFailures = DebugMode();
         LoadSymbols(&auxSymbols[0], trygl, prefix, warnOnFailures);
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -82,16 +82,17 @@ namespace mozilla {
 namespace gl {
 
 MOZ_BEGIN_ENUM_CLASS(GLFeature)
     bind_buffer_offset,
     blend_minmax,
     depth_texture,
     draw_buffers,
     draw_instanced,
+    draw_range_elements,
     element_index_uint,
     ES2_compatibility,
     ES3_compatibility,
     frag_color_float,
     frag_depth,
     framebuffer_blit,
     framebuffer_multisample,
     framebuffer_object,
@@ -414,16 +415,17 @@ public:
         EXT_sRGB,
         EXT_texture_sRGB,
         ARB_framebuffer_sRGB,
         EXT_framebuffer_sRGB,
         KHR_debug,
         ARB_half_float_pixel,
         EXT_frag_depth,
         OES_compressed_ETC1_RGB8_texture,
+        EXT_draw_range_elements,
         Extensions_Max,
         Extensions_End
     };
 
     bool IsExtensionSupported(GLExtensions aKnownExtension) const {
         return mAvailableExtensions[aKnownExtension];
     }
 
@@ -2223,16 +2225,27 @@ public:
         BeforeGLDrawCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fDrawElementsInstanced);
         mSymbols.fDrawElementsInstanced(mode, count, type, indices, primcount);
         AFTER_GL_CALL;
         AfterGLDrawCall();
     }
 
+// -----------------------------------------------------------------------------
+// Feature draw_range_elements
+public:
+    void fDrawRangeElements(GLenum mode, GLuint start, GLuint end,
+                            GLsizei count, GLenum type, const GLvoid* indices)
+    {
+        BEFORE_GL_CALL;
+        ASSERT_SYMBOL_PRESENT(fDrawRangeElements);
+        mSymbols.fDrawRangeElements(mode, start, end, count, type, indices);
+        AFTER_GL_CALL;
+    }
 
 // -----------------------------------------------------------------------------
 // Package XXX_framebuffer_blit
 public:
     // Draw/Read
     void fBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
         BeforeGLDrawCall();
         BeforeGLReadCall();
@@ -2693,17 +2706,17 @@ protected:
 #ifdef DEBUG
     // GLDebugMode will check that we don't send call
     // to a GLContext that isn't current on the current
     // thread.
     // Store the current context when binding to thread local
     // storage to support DebugMode on an arbitrary thread.
     static unsigned sCurrentGLContextTLS;
 #endif
-    
+
     ScopedDeletePtr<GLBlitHelper> mBlitHelper;
     ScopedDeletePtr<GLBlitTextureImageHelper> mBlitTextureImageHelper;
     ScopedDeletePtr<GLReadTexImageHelper> mReadTexImageHelper;
 
 public:
     GLBlitHelper* BlitHelper();
     GLBlitTextureImageHelper* BlitTextureImageHelper();
     GLReadTexImageHelper* ReadTexImageHelper();
--- a/gfx/gl/GLContextFeatures.cpp
+++ b/gfx/gl/GLContextFeatures.cpp
@@ -80,16 +80,25 @@ static const FeatureInfo sFeatureInfoArr
             GLContext::ARB_draw_instanced,
             GLContext::EXT_draw_instanced,
             GLContext::NV_draw_instanced,
             GLContext::ANGLE_instanced_arrays,
             GLContext::Extensions_End
         }
     },
     {
+        "draw_range_elements",
+        120, // OpenGL version
+        300, // OpenGL ES version
+        {
+            GLContext::EXT_draw_range_elements,
+            GLContext::Extensions_End
+        }
+    },
+    {
         "element_index_uint",
         200, // OpenGL version
         300, // OpenGL ES version
         {
             GLContext::OES_element_index_uint,
             GLContext::Extensions_End
         }
     },
--- a/gfx/gl/GLContextSymbols.h
+++ b/gfx/gl/GLContextSymbols.h
@@ -488,14 +488,18 @@ struct GLContextSymbols
     typedef void (GLAPIENTRY * PFNGLOBJECTLABEL) (GLenum identifier, GLuint name, GLsizei length, const GLchar* label);
     PFNGLOBJECTLABEL fObjectLabel;
     typedef void (GLAPIENTRY * PFNGLGETOBJECTLABEL) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label);
     PFNGLGETOBJECTLABEL fGetObjectLabel;
     typedef void (GLAPIENTRY * PFNGLOBJECTPTRLABEL) (const GLvoid* ptr, GLsizei length, const GLchar* label);
     PFNGLOBJECTPTRLABEL fObjectPtrLabel;
     typedef void (GLAPIENTRY * PFNGLGETOBJECTPTRLABEL) (const GLvoid* ptr, GLsizei bufSize, GLsizei* length, GLchar* label);
     PFNGLGETOBJECTPTRLABEL fGetObjectPtrLabel;
+
+    // draw_range_elements
+    typedef void (GLAPIENTRY * PFNGLDRAWRANGEELEMENTS) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices);
+    PFNGLDRAWRANGEELEMENTS fDrawRangeElements;
 };
 
 }
 }
 
 #endif /* GLCONTEXTSYMBOLS_H_ */
--- a/gfx/layers/CopyableCanvasLayer.cpp
+++ b/gfx/layers/CopyableCanvasLayer.cpp
@@ -281,29 +281,25 @@ CopyableCanvasLayer::PaintWithOpacity(gf
     Matrix flipped = oldTransform;
     flipped.Translate(0, mBounds.height);
     flipped.Scale(1.0, -1.0);
     aTarget->SetTransform(flipped);
   }
 
   DrawOptions options = DrawOptions(aOpacity, CompositionOp::OP_SOURCE);
 
-  // If content opaque, then save off current operator and set to source.
-  // This ensures that alpha is not applied even if the source surface
-  // has an alpha channel
-  if (GetContentFlags() & CONTENT_OPAQUE) {
-    options.mCompositionOp = CompositionOp::OP_SOURCE;
-  }
-
   if (aOperator != CompositionOp::OP_OVER) {
     options.mCompositionOp = aOperator;
   }
 
+  // XXX: This needs rewriting for acceptable performance using CoreGraphics.
+  // Therefore - this ::PaintWithOpacity is currently not used
   Rect rect = Rect(0, 0, mBounds.width, mBounds.height);
   aTarget->FillRect(rect, pat, options);
+
   if (aMaskSurface) {
     aTarget->MaskSurface(pat, aMaskSurface, Point(0, 0), options);
   }
 
   if (mNeedsYFlip) {
     aTarget->SetTransform(oldTransform);
   }
 }
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -74,20 +74,20 @@ CanvasClient2D::Update(gfx::IntSize aSiz
 
   if (!mBuffer->Lock(OPEN_WRITE_ONLY)) {
     return;
   }
 
   bool updated = false;
   {
     // Restrict drawTarget to a scope so that terminates before Unlock.
-    RefPtr<DrawTarget> drawTarget =
-      mBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget();
-    if (drawTarget) {
-      aLayer->UpdateTarget(drawTarget);
+    nsRefPtr<gfxASurface> surface =
+      mBuffer->AsTextureClientSurface()->GetAsSurface();
+    if (surface) {
+      aLayer->DeprecatedUpdateSurface(surface);
       updated = true;
     }
   }
   mBuffer->Unlock();
 
   if (bufferCreated && !AddTextureClient(mBuffer)) {
     mBuffer = nullptr;
     return;
--- a/gfx/layers/client/ClientContainerLayer.h
+++ b/gfx/layers/client/ClientContainerLayer.h
@@ -71,21 +71,22 @@ public:
     SortChildrenBy3DZOrder(children);
 
     for (uint32_t i = 0; i < children.Length(); i++) {
       Layer* child = children.ElementAt(i);
       if (child->GetEffectiveVisibleRegion().IsEmpty()) {
         continue;
       }
 
-      if (!child->GetInvalidRegion().IsEmpty()) {
+      ToClientLayer(child)->RenderLayer();
+
+      if (!ClientManager()->GetRepeatTransaction() &&
+          !child->GetInvalidRegion().IsEmpty()) {
         child->Mutated();
       }
-
-      ToClientLayer(child)->RenderLayer();
     }
   }
 
   virtual void SetVisibleRegion(const nsIntRegion& aRegion)
   {
     NS_ASSERTION(ClientManager()->InConstruction(),
                  "Can only set properties in construction phase");
     ContainerLayer::SetVisibleRegion(aRegion);
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -189,20 +189,20 @@ ClientLayerManager::EndTransactionIntern
   // properties.
   GetRoot()->ApplyPendingUpdatesToSubtree();
     
   mThebesLayerCallback = aCallback;
   mThebesLayerCallbackData = aCallbackData;
 
   GetRoot()->ComputeEffectiveTransforms(Matrix4x4());
 
-  if (!GetRoot()->GetInvalidRegion().IsEmpty()) {
+  root->RenderLayer();
+  if (!mRepeatTransaction && !GetRoot()->GetInvalidRegion().IsEmpty()) {
     GetRoot()->Mutated();
   }
-  root->RenderLayer();
   
   mThebesLayerCallback = nullptr;
   mThebesLayerCallbackData = nullptr;
 
   // Go back to the construction phase if the transaction isn't complete.
   // Layout will update the layer tree and call EndTransaction().
   mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
 
--- a/gfx/src/nsITheme.h
+++ b/gfx/src/nsITheme.h
@@ -25,18 +25,18 @@ class nsDeviceContext;
 class nsIFrame;
 class nsIContent;
 class nsIAtom;
 class nsIWidget;
 
 // IID for the nsITheme interface
 // {b0f3efe9-0bd4-4f6b-8daa-0ec7f6006822}
  #define NS_ITHEME_IID     \
-{ 0x2e49c679, 0x2130, 0x432c, \
-  { 0x92, 0xcb, 0xd4, 0x8e, 0x9a, 0xe2, 0x34, 0x75 } }
+{ 0x4440b5c7, 0xd8bd, 0x4d9c, \
+  { 0x9c, 0x3e, 0xa5, 0xe6, 0x26, 0x81, 0x10, 0xa0 } }
 // {D930E29B-6909-44e5-AB4B-AF10D6923705}
 #define NS_THEMERENDERER_CID \
 { 0x9020805b, 0x14a3, 0x4125, \
   { 0xa5, 0x63, 0x4a, 0x8c, 0x5d, 0xe0, 0xa9, 0xa3 } }
 
 /**
  * nsITheme is a service that provides platform-specific native
  * rendering for widgets.  In other words, it provides the necessary
@@ -58,18 +58,17 @@ public:
    * @param aWidgetType the -moz-appearance value to draw
    * @param aRect the rectangle defining the area occupied by the widget
    * @param aDirtyRect the rectangle that needs to be drawn
    */
   NS_IMETHOD DrawWidgetBackground(nsRenderingContext* aContext,
                                   nsIFrame* aFrame,
                                   uint8_t aWidgetType,
                                   const nsRect& aRect,
-                                  const nsRect& aDirtyRect,
-                                  nsIntRegion* aRegionToClear = nullptr) = 0;
+                                  const nsRect& aDirtyRect) = 0;
 
   /**
    * Get the computed CSS border for the widget, in pixels.
    */
   NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, 
                              nsIFrame* aFrame,
                              uint8_t aWidgetType,
                              nsIntMargin* aResult)=0;
--- a/js/src/assembler/assembler/ARMAssembler.h
+++ b/js/src/assembler/assembler/ARMAssembler.h
@@ -901,16 +901,21 @@ namespace JSC {
             m_buffer.flushWithoutBarrier(true);
         }
 
         size_t size() const
         {
             return m_buffer.uncheckedSize();
         }
 
+        size_t allocSize() const
+        {
+            return m_buffer.allocSize();
+        }
+
         void ensureSpace(int insnSpace, int constSpace)
         {
             m_buffer.ensureSpace(insnSpace, constSpace);
         }
 
         void ensureSpace(int space)
         {
             m_buffer.ensureSpace(space);
--- a/js/src/assembler/assembler/AssemblerBuffer.h
+++ b/js/src/assembler/assembler/AssemblerBuffer.h
@@ -37,16 +37,17 @@
 #include <string.h>
 #include <limits.h>
 #include "assembler/jit/ExecutableAllocator.h"
 #include "assembler/wtf/Assertions.h"
 
 #include <stdarg.h>
 #include "jsfriendapi.h"
 #include "jsopcode.h"
+#include "jsutil.h"
 
 #include "jit/IonSpewer.h"
 #include "js/RootingAPI.h"
 
 #define PRETTY_PRINT_OFFSET(os) (((os)<0)?"-":""), (((os)<0)?-(os):(os))
 
 #define FIXME_INSN_PRINTING                                 \
     do {                                                    \
@@ -58,16 +59,17 @@ namespace JSC {
 
     class AssemblerBuffer {
         static const size_t inlineCapacity = 256;
     public:
         AssemblerBuffer()
             : m_buffer(m_inlineBuffer)
             , m_capacity(inlineCapacity)
             , m_size(0)
+            , m_allocSize(0)
             , m_oom(false)
         {
         }
 
         ~AssemblerBuffer()
         {
             if (m_buffer != m_inlineBuffer)
                 js_free(m_buffer);
@@ -138,33 +140,40 @@ namespace JSC {
             return m_buffer;
         }
 
         size_t size() const
         {
             return m_size;
         }
 
+        size_t allocSize() const
+        {
+            return m_allocSize;
+        }
+
         bool oom() const
         {
             return m_oom;
         }
 
         /*
          * The user must check for a NULL return value, which means
          * no code was generated, or there was an OOM.
          */
         void* executableAllocAndCopy(ExecutableAllocator* allocator, ExecutablePool** poolp, CodeKind kind)
         {
             if (m_oom || m_size == 0) {
                 *poolp = NULL;
                 return 0;
             }
 
-            void* result = allocator->alloc(m_size, poolp, kind);
+            m_allocSize = js::AlignBytes(m_size, sizeof(void *));
+
+            void* result = allocator->alloc(m_allocSize, poolp, kind);
             if (!result) {
                 *poolp = NULL;
                 return 0;
             }
             JS_ASSERT(*poolp);
 
             ExecutableAllocator::makeWritable(result, m_size);
 
@@ -250,16 +259,17 @@ namespace JSC {
             m_buffer = newBuffer;
             m_capacity = newCapacity;
         }
 
         char m_inlineBuffer[inlineCapacity];
         char* m_buffer;
         size_t m_capacity;
         size_t m_size;
+        size_t m_allocSize;
         bool m_oom;
     };
 
     class GenericAssembler
     {
         js::Sprinter *printer;
 
       public:
--- a/js/src/assembler/assembler/LinkBuffer.h
+++ b/js/src/assembler/assembler/LinkBuffer.h
@@ -61,48 +61,29 @@ class LinkBuffer {
     typedef MacroAssembler::DataLabel32 DataLabel32;
     typedef MacroAssembler::DataLabelPtr DataLabelPtr;
 
 public:
     // 'ok' should be checked after this constructor is called;  it's false if OOM occurred.
     LinkBuffer(MacroAssembler* masm, ExecutableAllocator* executableAllocator,
                ExecutablePool** poolp, bool* ok, CodeKind codeKind)
     {
+        // LinkBuffer is only used by Yarr. MacroAssemblerCodeRef::release relies on this.
+        MOZ_ASSERT(codeKind == REGEXP_CODE);
         m_codeKind = codeKind;
         m_code = executableAllocAndCopy(*masm, executableAllocator, poolp);
         m_executablePool = *poolp;
         m_size = masm->m_assembler.size();  // must come after call to executableAllocAndCopy()!
+        m_allocSize = masm->m_assembler.allocSize();
 #ifndef NDEBUG
         m_completed = false;
 #endif
         *ok = !!m_code;
     }
 
-    LinkBuffer(CodeKind kind)
-        : m_executablePool(NULL)
-        , m_code(NULL)
-        , m_size(0)
-        , m_codeKind(kind)
-#ifndef NDEBUG
-        , m_completed(false)
-#endif
-    {
-    }
-
-    LinkBuffer(uint8_t* ncode, size_t size, CodeKind kind)
-        : m_executablePool(NULL)
-        , m_code(ncode)
-        , m_size(size)
-        , m_codeKind(kind)
-#ifndef NDEBUG
-        , m_completed(false)
-#endif
-    {
-    }
-
     ~LinkBuffer()
     {
         ASSERT(!m_executablePool || m_completed);
     }
 
     // These methods are used to link or set values at code generation time.
 
     void link(Call call, FunctionPtr function)
@@ -178,17 +159,18 @@ public:
     // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called
     // once to complete generation of the code.  'finalizeCode()' is suited to situations
     // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is
     // suited to adding to an existing allocation.
     CodeRef finalizeCode()
     {
         performFinalization();
 
-        return CodeRef(m_code, m_executablePool, m_size);
+        MOZ_ASSERT(m_allocSize >= m_size);
+        return CodeRef(m_code, m_executablePool, m_allocSize);
     }
     CodeLocationLabel finalizeCodeAddendum()
     {
         performFinalization();
 
         return CodeLocationLabel(code());
     }
 
@@ -220,16 +202,17 @@ protected:
 
         ExecutableAllocator::makeExecutable(code(), m_size);
         ExecutableAllocator::cacheFlush(code(), m_size);
     }
 
     ExecutablePool* m_executablePool;
     void* m_code;
     size_t m_size;
+    size_t m_allocSize;
     CodeKind m_codeKind;
 #ifndef NDEBUG
     bool m_completed;
 #endif
 };
 
 } // namespace JSC
 
--- a/js/src/assembler/assembler/MacroAssemblerCodeRef.h
+++ b/js/src/assembler/assembler/MacroAssemblerCodeRef.h
@@ -177,50 +177,51 @@ private:
 //
 // A reference to a section of JIT generated code.  A CodeRef consists of a
 // pointer to the code, and a ref pointer to the pool from within which it
 // was allocated.
 class MacroAssemblerCodeRef {
 public:
     MacroAssemblerCodeRef()
         : m_executablePool(NULL),
-          m_size(0)
+          m_allocSize(0)
     {
     }
 
-    MacroAssemblerCodeRef(void* code, ExecutablePool* executablePool, size_t size)
+    MacroAssemblerCodeRef(void* code, ExecutablePool* executablePool, size_t allocSize)
         : m_code(code)
         , m_executablePool(executablePool)
-        , m_size(size)
+        , m_allocSize(allocSize)
     {
     }
 
     // Release the code memory in this code ref.
     void release()
     {
         if (!m_executablePool)
             return;
 
 #if defined DEBUG && (defined WTF_CPU_X86 || defined WTF_CPU_X86_64) 
         void *addr = m_code.executableAddress();
-        memset(addr, 0xcc, m_size);
+        memset(addr, 0xcc, m_allocSize);
 #endif
-        m_executablePool->release();
+        // MacroAssemblerCodeRef is only used by Yarr.
+        m_executablePool->release(m_allocSize, REGEXP_CODE);
         m_executablePool = NULL;
     }
 
     MacroAssemblerCodePtr code() const {
         return m_code;
     }
-    size_t size() const {
-        return m_size;
+    size_t allocSize() const {
+        return m_allocSize;
     }
 
     MacroAssemblerCodePtr m_code;
     ExecutablePool* m_executablePool;
-    size_t m_size;
+    size_t m_allocSize;
 };
 
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER)
 
 #endif /* assembler_assembler_MacroAssemblerCodeRef_h */
--- a/js/src/assembler/assembler/X86Assembler.h
+++ b/js/src/assembler/assembler/X86Assembler.h
@@ -435,16 +435,17 @@ public:
             return m_offset;
         }
     private:
         signed int m_offset : 31;
         bool m_used : 1;
     };
 
     size_t size() const { return m_formatter.size(); }
+    size_t allocSize() const { return m_formatter.allocSize(); }
     unsigned char *buffer() const { return m_formatter.buffer(); }
     bool oom() const { return m_formatter.oom(); }
 
     void nop()
     {
         spew("nop");
         m_formatter.oneByteOp(OP_NOP);
     }
@@ -3862,16 +3863,17 @@ private:
         {
             m_buffer.ensureSpace(sizeof(int64_t));
             m_buffer.putInt64Unchecked(i);
         }
 
         // Administrative methods:
 
         size_t size() const { return m_buffer.size(); }
+        size_t allocSize() const { return m_buffer.allocSize(); }
         unsigned char *buffer() const { return m_buffer.buffer(); }
         bool oom() const { return m_buffer.oom(); }
         bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
         void* data() const { return m_buffer.data(); }
         void* executableAllocAndCopy(ExecutableAllocator* allocator, ExecutablePool** poolp, CodeKind kind) {
             return m_buffer.executableAllocAndCopy(allocator, poolp, kind);
         }
 
--- a/js/src/assembler/jit/ExecutableAllocator.cpp
+++ b/js/src/assembler/jit/ExecutableAllocator.cpp
@@ -33,16 +33,21 @@
 
 namespace JSC {
 
 size_t ExecutableAllocator::pageSize = 0;
 size_t ExecutableAllocator::largeAllocSize = 0;
 
 ExecutablePool::~ExecutablePool()
 {
+    MOZ_ASSERT(m_ionCodeBytes == 0);
+    MOZ_ASSERT(m_baselineCodeBytes == 0);
+    MOZ_ASSERT(m_regexpCodeBytes == 0);
+    MOZ_ASSERT(m_otherCodeBytes == 0);
+
     m_allocator->releasePoolPages(this);
 }
 
 void
 ExecutableAllocator::addSizeOfCode(JS::CodeSizes *sizes) const
 {
     if (m_pools.initialized()) {
         for (ExecPoolHashSet::Range r = m_pools.all(); !r.empty(); r.popFront()) {
--- a/js/src/assembler/jit/ExecutableAllocator.h
+++ b/js/src/assembler/jit/ExecutableAllocator.h
@@ -80,17 +80,17 @@ extern  "C" void sync_instruction_memory
 namespace JS {
     struct CodeSizes;
 }
 
 namespace JSC {
 
   class ExecutableAllocator;
 
-  enum CodeKind { ION_CODE, BASELINE_CODE, REGEXP_CODE, OTHER_CODE };
+  enum CodeKind { ION_CODE = 0, BASELINE_CODE, REGEXP_CODE, OTHER_CODE };
 
   // These are reference-counted. A new one starts with a count of 1.
   class ExecutablePool {
 
     friend class ExecutableAllocator;
 private:
     struct Allocation {
         char* pages;
@@ -125,16 +125,41 @@ public:
     void release(bool willDestroy = false)
     {
         JS_ASSERT(m_refCount != 0);
         // XXX: disabled, see bug 654820.
         //JS_ASSERT_IF(willDestroy, m_refCount == 1);
         if (--m_refCount == 0)
             js_delete(this);
     }
+    void release(size_t n, CodeKind kind)
+    {
+        switch (kind) {
+          case ION_CODE:
+            m_ionCodeBytes -= n;
+            MOZ_ASSERT(m_ionCodeBytes < m_allocation.size); // Shouldn't underflow.
+            break;
+          case BASELINE_CODE:
+            m_baselineCodeBytes -= n;
+            MOZ_ASSERT(m_baselineCodeBytes < m_allocation.size);
+            break;
+          case REGEXP_CODE:
+            m_regexpCodeBytes -= n;
+            MOZ_ASSERT(m_regexpCodeBytes < m_allocation.size);
+            break;
+          case OTHER_CODE:
+            m_otherCodeBytes -= n;
+            MOZ_ASSERT(m_otherCodeBytes < m_allocation.size);
+            break;
+          default:
+            MOZ_ASSUME_UNREACHABLE("bad code kind");
+        }
+
+        release();
+    }
 
     ExecutablePool(ExecutableAllocator* allocator, Allocation a)
       : m_allocator(allocator), m_freePtr(a.pages), m_end(m_freePtr + a.size), m_allocation(a),
         m_refCount(1), m_ionCodeBytes(0), m_baselineCodeBytes(0), m_regexpCodeBytes(0),
         m_otherCodeBytes(0), m_destroy(false), m_gcNumber(0)
     { }
 
     ~ExecutablePool();
@@ -218,20 +243,21 @@ public:
         m_smallPools.clear();
     }
 
     // alloc() returns a pointer to some memory, and also (by reference) a
     // pointer to reference-counted pool. The caller owns a reference to the
     // pool; i.e. alloc() increments the count before returning the object.
     void* alloc(size_t n, ExecutablePool** poolp, CodeKind type)
     {
-        // Round 'n' up to a multiple of word size; if all allocations are of
-        // word sized quantities, then all subsequent allocations will be
+        // Caller must ensure 'n' is word-size aligned. If all allocations are
+        // of word sized quantities, then all subsequent allocations will be
         // aligned.
-        n = roundUpAllocationSize(n, sizeof(void*));
+        JS_ASSERT(roundUpAllocationSize(n, sizeof(void*)) == n);
+
         if (n == OVERSIZE_ALLOCATION) {
             *poolp = NULL;
             return NULL;
         }
 
         *poolp = poolForSize(n);
         if (!*poolp)
             return NULL;
@@ -342,17 +368,17 @@ public:
         // If the request is large, we just provide a unshared allocator
         if (n > largeAllocSize)
             return createPool(n);
 
         // Create a new allocator
         ExecutablePool* pool = createPool(largeAllocSize);
         if (!pool)
             return NULL;
-  	    // At this point, local |pool| is the owner.
+        // At this point, local |pool| is the owner.
 
         if (m_smallPools.length() < maxSmallPools) {
             // We haven't hit the maximum number of live pools;  add the new pool.
             m_smallPools.append(pool);
             pool->addRef();
         } else {
             // Find the pool with the least space.
             int iMin = 0;
@@ -368,17 +394,17 @@ public:
             ExecutablePool *minPool = m_smallPools[iMin];
             if ((pool->available() - n) > minPool->available()) {
                 minPool->release();
                 m_smallPools[iMin] = pool;
                 pool->addRef();
             }
         }
 
-   	    // Pass ownership to the caller.
+        // Pass ownership to the caller.
         return pool;
     }
 
 #if ENABLE_ASSEMBLER_WX_EXCLUSIVE
     static void makeWritable(void* start, size_t size)
     {
         reprotectRegion(start, size, Writable);
     }
rename from js/src/jit-test/tests/ion/bug980960.js
rename to js/src/jit-test/tests/ion/bug980860.js
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -610,35 +610,38 @@ JitRuntime::getVMWrapper(const VMFunctio
     JitRuntime::VMWrapperMap::Ptr p = functionWrappers_->readonlyThreadsafeLookup(&f);
     JS_ASSERT(p);
 
     return p->value();
 }
 
 template <AllowGC allowGC>
 JitCode *
-JitCode::New(JSContext *cx, uint8_t *code, uint32_t bufferSize, JSC::ExecutablePool *pool)
+JitCode::New(JSContext *cx, uint8_t *code, uint32_t bufferSize, uint32_t headerSize,
+             JSC::ExecutablePool *pool, JSC::CodeKind kind)
 {
     JitCode *codeObj = js::NewJitCode<allowGC>(cx);
     if (!codeObj) {
-        pool->release();
+        pool->release(headerSize + bufferSize, kind);
         return nullptr;
     }
 
-    new (codeObj) JitCode(code, bufferSize, pool);
+    new (codeObj) JitCode(code, bufferSize, headerSize, pool, kind);
     return codeObj;
 }
 
 template
 JitCode *
-JitCode::New<CanGC>(JSContext *cx, uint8_t *code, uint32_t bufferSize, JSC::ExecutablePool *pool);
+JitCode::New<CanGC>(JSContext *cx, uint8_t *code, uint32_t bufferSize, uint32_t headerSize,
+                    JSC::ExecutablePool *pool, JSC::CodeKind kind);
 
 template
 JitCode *
-JitCode::New<NoGC>(JSContext *cx, uint8_t *code, uint32_t bufferSize, JSC::ExecutablePool *pool);
+JitCode::New<NoGC>(JSContext *cx, uint8_t *code, uint32_t bufferSize, uint32_t headerSize,
+                   JSC::ExecutablePool *pool, JSC::CodeKind kind);
 
 void
 JitCode::copyFrom(MacroAssembler &masm)
 {
     // Store the JitCode pointer right before the code buffer, so we can
     // recover the gcthing from relocation tables.
     *(JitCode **)(code_ - sizeof(JitCode *)) = this;
     insnSize_ = masm.instructionsSize();
@@ -691,17 +694,17 @@ JitCode::finalize(FreeOp *fop)
     code_ = nullptr;
 
     // Code buffers are stored inside JSC pools.
     // Pools are refcounted. Releasing the pool may free it.
     if (pool_) {
         // 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())
-            pool_->release();
+            pool_->release(headerSize_ + bufferSize_, JSC::CodeKind(kind_));
         pool_ = nullptr;
     }
 }
 
 void
 JitCode::togglePreBarriers(bool enabled)
 {
     uint8_t *start = code_ + preBarrierTableOffset();
--- a/js/src/jit/IonCode.h
+++ b/js/src/jit/IonCode.h
@@ -9,16 +9,17 @@
 
 #include "mozilla/Atomics.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 
 #include "jsinfer.h"
 #include "jstypes.h"
 
+#include "assembler/jit/ExecutableAllocator.h"
 #include "gc/Heap.h"
 #include "jit/IonOptimizationLevels.h"
 #include "jit/IonTypes.h"
 
 namespace JSC {
     class ExecutablePool;
 }
 
@@ -32,45 +33,53 @@ class MacroAssembler;
 class CodeOffsetLabel;
 class PatchableBackedge;
 
 class JitCode : public gc::BarrieredCell<JitCode>
 {
   protected:
     uint8_t *code_;
     JSC::ExecutablePool *pool_;
-    uint32_t bufferSize_;             // Total buffer size.
+    uint32_t bufferSize_;             // Total buffer size. Does not include headerSize_.
     uint32_t insnSize_;               // Instruction stream size.
     uint32_t dataSize_;               // Size of the read-only data area.
     uint32_t jumpRelocTableBytes_;    // Size of the jump relocation table.
     uint32_t dataRelocTableBytes_;    // Size of the data relocation table.
     uint32_t preBarrierTableBytes_;   // Size of the prebarrier table.
-    bool invalidated_;                // Whether the code object has been invalidated.
+    uint8_t headerSize_ : 5;          // Number of bytes allocated before codeStart.
+    uint8_t kind_ : 3;                // JSC::CodeKind, for the memory reporters.
+    bool invalidated_ : 1;            // Whether the code object has been invalidated.
                                       // This is necessary to prevent GC tracing.
 
 #if JS_BITS_PER_WORD == 32
     // Ensure JitCode is gc::Cell aligned.
     uint32_t padding_;
 #endif
 
     JitCode()
       : code_(nullptr),
         pool_(nullptr)
     { }
-    JitCode(uint8_t *code, uint32_t bufferSize, JSC::ExecutablePool *pool)
+    JitCode(uint8_t *code, uint32_t bufferSize, uint32_t headerSize, JSC::ExecutablePool *pool,
+            JSC::CodeKind kind)
       : code_(code),
         pool_(pool),
         bufferSize_(bufferSize),
         insnSize_(0),
         dataSize_(0),
         jumpRelocTableBytes_(0),
         dataRelocTableBytes_(0),
         preBarrierTableBytes_(0),
+        headerSize_(headerSize),
+        kind_(kind),
         invalidated_(false)
-    { }
+    {
+        MOZ_ASSERT(JSC::CodeKind(kind_) == kind);
+        MOZ_ASSERT(headerSize_ == headerSize);
+    }
 
     uint32_t dataOffset() const {
         return insnSize_;
     }
     uint32_t jumpRelocTableOffset() const {
         return dataOffset() + dataSize_;
     }
     uint32_t dataRelocTableOffset() const {
@@ -121,17 +130,18 @@ class JitCode : public gc::BarrieredCell
     uint8_t *jumpRelocTable() {
         return code_ + jumpRelocTableOffset();
     }
 
     // Allocates a new JitCode object which will be managed by the GC. If no
     // object can be allocated, nullptr is returned. On failure, |pool| is
     // automatically released, so the code may be freed.
     template <AllowGC allowGC>
-    static JitCode *New(JSContext *cx, uint8_t *code, uint32_t bufferSize, JSC::ExecutablePool *pool);
+    static JitCode *New(JSContext *cx, uint8_t *code, uint32_t bufferSize, uint32_t headerSize,
+                        JSC::ExecutablePool *pool, JSC::CodeKind kind);
 
   public:
     static inline ThingRootKind rootKind() { return THING_ROOT_JIT_CODE; }
 };
 
 class SnapshotWriter;
 class SafepointWriter;
 class SafepointIndex;
--- a/js/src/jit/IonLinker.h
+++ b/js/src/jit/IonLinker.h
@@ -39,28 +39,31 @@ class Linker
         if (masm.oom())
             return fail(cx);
 
         JSC::ExecutablePool *pool;
         size_t bytesNeeded = masm.bytesNeeded() + sizeof(JitCode *) + CodeAlignment;
         if (bytesNeeded >= MAX_BUFFER_SIZE)
             return fail(cx);
 
+        // ExecutableAllocator requires bytesNeeded to be word-size aligned.
+        bytesNeeded = AlignBytes(bytesNeeded, sizeof(void *));
+
         uint8_t *result = (uint8_t *)execAlloc->alloc(bytesNeeded, &pool, kind);
         if (!result)
             return fail(cx);
 
         // The JitCode pointer will be stored right before the code buffer.
         uint8_t *codeStart = result + sizeof(JitCode *);
 
         // Bump the code up to a nice alignment.
         codeStart = (uint8_t *)AlignBytes((uintptr_t)codeStart, CodeAlignment);
         uint32_t headerSize = codeStart - result;
-        JitCode *code = JitCode::New<allowGC>(cx, codeStart,
-                                              bytesNeeded - headerSize, pool);
+        JitCode *code = JitCode::New<allowGC>(cx, codeStart, bytesNeeded - headerSize,
+                                              headerSize, pool, kind);
         if (!code)
             return nullptr;
         if (masm.oom())
             return fail(cx);
         code->copyFrom(masm);
         masm.link(code);
 #ifdef JSGC_GENERATIONAL
         if (masm.embedsNurseryPointers())
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2544,17 +2544,17 @@ DefineConstructorAndPrototype(JSContext 
         ctor = proto;
     } else {
         /*
          * Create the constructor, not using GlobalObject::createConstructor
          * because the constructor currently must have |obj| as its parent.
          * (FIXME: remove this dependency on the exact identity of the parent,
          * perhaps as part of bug 638316.)
          */
-        RootedFunction fun(cx, NewFunction(cx, NullPtr(), constructor, nargs,
+        RootedFunction fun(cx, NewFunction(cx, js::NullPtr(), constructor, nargs,
                                            JSFunction::NATIVE_CTOR, obj, atom, ctorKind));
         if (!fun)
             goto bad;
 
         /*
          * Set the class object early for standard class constructors. Type
          * inference may need to access these, and js::GetBuiltinPrototype will
          * fail if it tries to do a reentrant reconstruction of the class.
--- a/js/src/yarr/YarrJIT.h
+++ b/js/src/yarr/YarrJIT.h
@@ -77,26 +77,26 @@ public:
     ~YarrCodeBlock()
     {
     }
 
     void setFallBack(bool fallback) { m_needFallBack = fallback; }
     bool isFallBack() { return m_needFallBack; }
 
 #ifdef YARR_8BIT_CHAR_SUPPORT
-    bool has8BitCode() const { return m_ref8.size(); }
+    bool has8BitCode() const { return m_ref8.allocSize(); }
     void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; }
-    bool has8BitCodeMatchOnly() const { return m_matchOnly8.size(); }
+    bool has8BitCodeMatchOnly() const { return m_matchOnly8.allocSize(); }
     void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; }
 #endif
 
-    bool has16BitCode() const { return m_ref16.size(); }
+    bool has16BitCode() const { return m_ref16.allocSize(); }
     void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; }
 
-    bool has16BitCodeMatchOnly() const { return m_matchOnly16.size(); }
+    bool has16BitCodeMatchOnly() const { return m_matchOnly16.allocSize(); }
     void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; }
 
 #if YARR_8BIT_CHAR_SUPPORT
     MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output)
     {
         ASSERT(has8BitCode());
 
 #if JS_TRACE_LOGGING
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3756,19 +3756,16 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
 
   RecomputeVisibilityForItems(entry->mItems, builder, aRegionToDraw,
                               offset, appUnitsPerDevPixel,
                               userData->mXScale, userData->mYScale);
 
   nsRefPtr<nsRenderingContext> rc = new nsRenderingContext();
   rc->Init(presContext->DeviceContext(), aContext);
 
-  nsIntRegion temp = builder->GetRegionToClear();
-  builder->ResetRegionToClear();
-
   if (shouldDrawRectsSeparately) {
     nsIntRegionRectIterator it(aRegionToDraw);
     while (const nsIntRect* iterRect = it.Next()) {
       gfxContextAutoSaveRestore save(aContext);
       aContext->NewPath();
       aContext->Rectangle(*iterRect, aClip == DrawRegionClip::DRAW_SNAPPED);
       aContext->Clip();
 
@@ -3800,22 +3797,16 @@ FrameLayerBuilder::DrawThebesLayer(Thebe
 
   if (presContext->GetPaintFlashing()) {
     FlashPaint(aContext);
   }
 
   if (!aRegionToInvalidate.IsEmpty()) {
     aLayer->AddInvalidRect(aRegionToInvalidate.GetBounds());
   }
-
-  if (!builder->GetRegionToClear().IsEmpty()) {
-    aLayer->Manager()->SetRegionToClear(builder->GetRegionToClear());
-  }
-  builder->ResetRegionToClear();
-  builder->AddRegionToClear(temp);
 }
 
 bool
 FrameLayerBuilder::CheckDOMModified()
 {
   if (!mRootPresContext ||
       mInitialDOMGeneration == mRootPresContext->GetDOMGeneration())
     return false;
--- a/layout/base/nsCaret.cpp
+++ b/layout/base/nsCaret.cpp
@@ -849,30 +849,30 @@ nsCaret::GetCaretFrameForNodeOffset(nsIC
 
   NS_ASSERTION(!theFrame || theFrame->PresContext()->PresShell() == presShell,
                "caret frame is in wrong document");
   *aReturnFrame = theFrame;
   *aReturnOffset = theFrameOffset;
   return NS_OK;
 }
 
-nsresult nsCaret::CheckCaretDrawingState()
+void
+nsCaret::CheckCaretDrawingState()
 {
   if (mDrawn) {
     // The caret is drawn; if it shouldn't be, erase it.
     if (!mVisible || !MustDrawCaret(true))
       EraseCaret();
   }
   else
   {
     // The caret is not drawn; if it should be, draw it.
     if (mPendingDraw && (mVisible && MustDrawCaret(true)))
       DrawCaret(true);
   }
-  return NS_OK;
 }
 
 /*-----------------------------------------------------------------------------
 
   MustDrawCaret
   
   Find out if we need to do any caret drawing. This returns true if
   either:
--- a/layout/base/nsCaret.h
+++ b/layout/base/nsCaret.h
@@ -158,17 +158,17 @@ class nsCaret : public nsISelectionListe
 
     nsresult      GetCaretFrameForNodeOffset(nsIContent* aContentNode,
                                              int32_t aOffset,
                                              nsFrameSelection::HINT aFrameHint,
                                              uint8_t aBidiLevel,
                                              nsIFrame** aReturnFrame,
                                              int32_t* aReturnOffset);
 
-    NS_IMETHOD CheckCaretDrawingState();
+    void CheckCaretDrawingState();
 
 protected:
 
     void          KillTimer();
     nsresult      PrimeTimer();
 
     void          StartBlinking();
     void          StopBlinking();
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2353,16 +2353,17 @@ nsDisplayThemedBackground::nsDisplayThem
 
   // Perform necessary RegisterThemeGeometry
   switch (disp->mAppearance) {
     case NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR:
     case NS_THEME_TOOLBAR:
     case NS_THEME_WINDOW_TITLEBAR:
     case NS_THEME_WINDOW_BUTTON_BOX:
     case NS_THEME_MOZ_MAC_FULLSCREEN_BUTTON:
+    case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
       RegisterThemeGeometry(aBuilder, aFrame);
       break;
     case NS_THEME_WIN_BORDERLESS_GLASS:
     case NS_THEME_WIN_GLASS:
       aBuilder->SetGlassDisplayItem(this);
       break;
   }
 
@@ -2440,21 +2441,17 @@ nsDisplayThemedBackground::PaintInternal
   // XXXzw this ignores aClipRect.
   nsPresContext* presContext = mFrame->PresContext();
   nsITheme *theme = presContext->GetTheme();
   nsRect borderArea(ToReferenceFrame(), mFrame->GetSize());
   nsRect drawing(borderArea);
   theme->GetWidgetOverflow(presContext->DeviceContext(), mFrame, mAppearance,
                            &drawing);
   drawing.IntersectRect(drawing, aBounds);
-  nsIntRegion clear;
-  theme->DrawWidgetBackground(aCtx, mFrame, mAppearance, borderArea, drawing, &clear);
-  MOZ_ASSERT(clear.IsEmpty() || ReferenceFrame() == aBuilder->RootReferenceFrame(),
-             "Can't add to clear region if we're transformed!");
-  aBuilder->AddRegionToClear(clear);
+  theme->DrawWidgetBackground(aCtx, mFrame, mAppearance, borderArea, drawing);
 }
 
 bool nsDisplayThemedBackground::IsWindowActive()
 {
   nsEventStates docState = mFrame->GetContent()->OwnerDoc()->GetDocumentState();
   return !docState.HasState(NS_DOCUMENT_STATE_WINDOW_INACTIVE);
 }
 
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -636,20 +636,16 @@ public:
    * has a blend mode attached. We do this so we can insert a 
    * nsDisplayBlendContainer in the parent stacking context.
    */
   void SetContainsBlendMode(bool aContainsBlendMode) { mContainsBlendMode = aContainsBlendMode; }
   bool ContainsBlendMode() const { return mContainsBlendMode; }
 
   DisplayListClipState& ClipState() { return mClipState; }
 
-  void AddRegionToClear(const nsIntRegion& aRegion) { mRegionToClear.Or(mRegionToClear, aRegion); }
-  const nsIntRegion& GetRegionToClear() { return mRegionToClear; }
-  void ResetRegionToClear() { mRegionToClear.SetEmpty(); }
-
 private:
   void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
                                     const nsRect& aDirtyRect);
 
   struct PresShellState {
     nsIPresShell* mPresShell;
     nsIFrame*     mCaretFrame;
     uint32_t      mFirstFrameMarkedForDisplay;
@@ -673,18 +669,16 @@ private:
   DisplayListClipState           mClipState;
   const nsRegion*                mFinalTransparentRegion;
   // When mCachedOffsetFrame is non-null, mCachedOffset is the offset from
   // mCachedOffsetFrame to mReferenceFrame.
   const nsIFrame*                mCachedOffsetFrame;
   const nsIFrame*                mCachedReferenceFrame;
   nsPoint                        mCachedOffset;
   nsRegion                       mExcludedGlassRegion;
-  // Area of the window (in pixels) to clear so the OS can draw them.
-  nsIntRegion                    mRegionToClear;
   // The display item for the Windows window glass background, if any
   nsDisplayItem*                 mGlassDisplayItem;
   nsTArray<DisplayItemClip*>     mDisplayItemClipsToDestroy;
   Mode                           mMode;
   bool                           mBuildCaret;
   bool                           mIgnoreSuppression;
   bool                           mHadToIgnoreSuppression;
   bool                           mIsAtRootOfPseudoStackingContext;
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -289,16 +289,17 @@ pref("media.navigator.enabled", true);
 #endif
 
 pref("media.tabstreaming.width", 320);
 pref("media.tabstreaming.height", 240);
 pref("media.tabstreaming.time_per_frame", 40);
 
 // TextTrack support
 pref("media.webvtt.enabled", true);
+pref("media.webvtt.regions.enabled", false);
 
 // Whether to enable MediaSource support
 pref("media.mediasource.enabled", false);
 
 #ifdef MOZ_WEBSPEECH
 pref("media.webspeech.recognition.enable", false);
 #endif
 #ifdef MOZ_WEBM_ENCODER
--- a/widget/cocoa/nsNativeThemeCocoa.h
+++ b/widget/cocoa/nsNativeThemeCocoa.h
@@ -29,18 +29,17 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // The nsITheme interface.
   NS_IMETHOD DrawWidgetBackground(nsRenderingContext* aContext,
                                   nsIFrame* aFrame,
                                   uint8_t aWidgetType,
                                   const nsRect& aRect,
-                                  const nsRect& aDirtyRect,
-                                  nsIntRegion* aRegionToClear);
+                                  const nsRect& aDirtyRect);
   NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, 
                              nsIFrame* aFrame,
                              uint8_t aWidgetType,
                              nsIntMargin* aResult);
 
   virtual bool GetWidgetPadding(nsDeviceContext* aContext,
                                   nsIFrame* aFrame,
                                   uint8_t aWidgetType,
--- a/widget/cocoa/nsNativeThemeCocoa.mm
+++ b/widget/cocoa/nsNativeThemeCocoa.mm
@@ -2075,18 +2075,17 @@ IsHiDPIContext(nsDeviceContext* aContext
     2 * aContext->UnscaledAppUnitsPerDevPixel();
 }
 
 NS_IMETHODIMP
 nsNativeThemeCocoa::DrawWidgetBackground(nsRenderingContext* aContext,
                                          nsIFrame* aFrame,
                                          uint8_t aWidgetType,
                                          const nsRect& aRect,
-                                         const nsRect& aDirtyRect,
-                                         nsIntRegion* aRegionToClear)
+                                         const nsRect& aDirtyRect)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   // setup to draw into the correct port
   int32_t p2a = aContext->AppUnitsPerDevPixel();
 
   gfxRect nativeDirtyRect(aDirtyRect.x, aDirtyRect.y,
                           aDirtyRect.width, aDirtyRect.height);
--- a/widget/gtk/nsNativeThemeGTK.cpp
+++ b/widget/gtk/nsNativeThemeGTK.cpp
@@ -747,18 +747,17 @@ nsNativeThemeGTK::GetExtraSizeForWidget(
   }
 }
 
 NS_IMETHODIMP
 nsNativeThemeGTK::DrawWidgetBackground(nsRenderingContext* aContext,
                                        nsIFrame* aFrame,
                                        uint8_t aWidgetType,
                                        const nsRect& aRect,
-                                       const nsRect& aDirtyRect,
-                                       nsIntRegion* aRegionToClear)
+                                       const nsRect& aDirtyRect)
 {
   GtkWidgetState state;
   GtkThemeWidgetType gtkWidgetType;
   GtkTextDirection direction = GetTextDirection(aFrame);
   gint flags;
   if (!GetGtkWidgetAndState(aWidgetType, aFrame, gtkWidgetType, &state,
                             &flags))
     return NS_OK;
--- a/widget/gtk/nsNativeThemeGTK.h
+++ b/widget/gtk/nsNativeThemeGTK.h
@@ -19,18 +19,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIOBSERVER
 
   // The nsITheme interface.
   NS_IMETHOD DrawWidgetBackground(nsRenderingContext* aContext,
                                   nsIFrame* aFrame, uint8_t aWidgetType,
                                   const nsRect& aRect,
-                                  const nsRect& aDirtyRect,
-                                  nsIntRegion* aRegionToClear);
+                                  const nsRect& aDirtyRect);
 
   NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, nsIFrame* aFrame,
                              uint8_t aWidgetType, nsIntMargin* aResult);
 
   virtual NS_HIDDEN_(bool) GetWidgetPadding(nsDeviceContext* aContext,
                                               nsIFrame* aFrame,
                                               uint8_t aWidgetType,
                                               nsIntMargin* aResult);
--- a/widget/windows/nsNativeThemeWin.cpp
+++ b/widget/windows/nsNativeThemeWin.cpp
@@ -1531,18 +1531,17 @@ AssumeThemePartAndStateAreTransparent(in
   return false;
 }
 
 NS_IMETHODIMP
 nsNativeThemeWin::DrawWidgetBackground(nsRenderingContext* aContext,
                                        nsIFrame* aFrame,
                                        uint8_t aWidgetType,
                                        const nsRect& aRect,
-                                       const nsRect& aDirtyRect,
-                                       nsIntRegion* aRegionToClear)
+                                       const nsRect& aDirtyRect)
 {
   HANDLE theme = GetTheme(aWidgetType);
   if (!theme)
     return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aDirtyRect); 
 
   // ^^ without the right sdk, assume xp theming and fall through.
   if (nsUXThemeData::CheckForCompositor()) {
     switch (aWidgetType) {
@@ -1563,16 +1562,20 @@ nsNativeThemeWin::DrawWidgetBackground(n
         // through here and call the theme library we'll get aero
         // basic bitmaps. 
         return NS_OK;
       break;
       case NS_THEME_WIN_GLASS:
       case NS_THEME_WIN_BORDERLESS_GLASS:
         // Nothing to draw, this is the glass background.
         return NS_OK;
+      case NS_THEME_WINDOW_BUTTON_BOX:
+      case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
+        // We handle these through nsIWidget::UpdateThemeGeometries
+        return NS_OK;
       break;
     }
   }
 
   int32_t part, state;
   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
   if (NS_FAILED(rv))
     return rv;
@@ -1895,30 +1898,16 @@ RENDER_AGAIN:
     if (GetThemePartSize(theme, hdc, gripPart, state, nullptr, TS_TRUE, &gripSize) == S_OK &&
         GetThemeMargins(theme, hdc, part, state, TMT_CONTENTMARGINS, nullptr, &thumbMgns) == S_OK &&
         gripSize.cx + thumbMgns.cxLeftWidth + thumbMgns.cxRightWidth <= widgetRect.right - widgetRect.left &&
         gripSize.cy + thumbMgns.cyTopHeight + thumbMgns.cyBottomHeight <= widgetRect.bottom - widgetRect.top)
     {
       DrawThemeBackground(theme, hdc, gripPart, state, &widgetRect, &clipRect);
     }
   }
-  else if ((aWidgetType == NS_THEME_WINDOW_BUTTON_BOX ||
-            aWidgetType == NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED) &&
-            nsUXThemeData::CheckForCompositor())
-  {
-    // The caption buttons are drawn by the DWM, we just need to clear the area where they
-    // are because we might have drawn something above them (like a background-image).
-    NS_ASSERTION(aRegionToClear, "Must have a clear region to set!");
-    if (aRegionToClear) {
-      // Create a rounded rectangle to follow the buttons' look.
-      *aRegionToClear = nsIntRect(dr.X(), dr.Y(), dr.Width(), dr.Height() - 2.0);
-      aRegionToClear->Or(*aRegionToClear, nsIntRect(dr.X() + 1.0, dr.YMost() - 2.0, dr.Width() - 1.0, 1.0));
-      aRegionToClear->Or(*aRegionToClear, nsIntRect(dr.X() + 2.0, dr.YMost() - 1.0, dr.Width() - 3.0, 1.0));
-    }
-  }
 
   nativeDrawing.EndNativeDrawing();
 
   if (nativeDrawing.ShouldRenderAgain())
     goto RENDER_AGAIN;
 
   nativeDrawing.PaintToContext();
 
--- a/widget/windows/nsNativeThemeWin.h
+++ b/widget/windows/nsNativeThemeWin.h
@@ -26,18 +26,17 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
 
   // The nsITheme interface.
   NS_IMETHOD DrawWidgetBackground(nsRenderingContext* aContext,
                                   nsIFrame* aFrame,
                                   uint8_t aWidgetType,
                                   const nsRect& aRect,
-                                  const nsRect& aDirtyRect,
-                                  nsIntRegion* aRegionToClear);
+                                  const nsRect& aDirtyRect);
 
   NS_IMETHOD GetWidgetBorder(nsDeviceContext* aContext, 
                              nsIFrame* aFrame,
                              uint8_t aWidgetType,
                              nsIntMargin* aResult);
 
   virtual bool GetWidgetPadding(nsDeviceContext* aContext,
                                   nsIFrame* aFrame,
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -122,16 +122,17 @@
 #include "WinUtils.h"
 #include "WidgetUtils.h"
 #include "nsIWidgetListener.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/gfx/2D.h"
 #include "nsToolkitCompsCID.h"
 #include "nsIAppStartup.h"
 #include "mozilla/WindowsVersion.h"
+#include "nsThemeConstants.h"
 
 #ifdef MOZ_ENABLE_D3D9_LAYER
 #include "LayerManagerD3D9.h"
 #endif
 
 #ifdef MOZ_ENABLE_D3D10_LAYER
 #include "LayerManagerD3D10.h"
 #endif
@@ -3551,16 +3552,38 @@ nsWindow::EndRemoteDrawing()
     UpdateTranslucentWindow();
   }
   if (mCompositeDC) {
     FreeNativeData(mCompositeDC, NS_NATIVE_GRAPHIC);
   }
   mCompositeDC = nullptr;
 }
 
+void
+nsWindow::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries)
+{
+  nsIntRegion clearRegion;
+  for (size_t i = 0; i < aThemeGeometries.Length(); i++) {
+    if ((aThemeGeometries[i].mWidgetType == NS_THEME_WINDOW_BUTTON_BOX ||
+         aThemeGeometries[i].mWidgetType == NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED) &&
+        nsUXThemeData::CheckForCompositor())
+    {
+      nsIntRect bounds = aThemeGeometries[i].mRect;
+      clearRegion = nsIntRect(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height() - 2.0);
+      clearRegion.Or(clearRegion, nsIntRect(bounds.X() + 1.0, bounds.YMost() - 2.0, bounds.Width() - 1.0, 1.0));
+      clearRegion.Or(clearRegion, nsIntRect(bounds.X() + 2.0, bounds.YMost() - 1.0, bounds.Width() - 3.0, 1.0));
+    }
+  }
+
+  nsRefPtr<LayerManager> layerManager = GetLayerManager();
+  if (layerManager) {
+    layerManager->SetRegionToClear(clearRegion);
+  }
+}
+
 /**************************************************************
  **************************************************************
  **
  ** BLOCK: Moz Events
  **
  ** Moz GUI event management. 
  **
  **************************************************************
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -191,16 +191,18 @@ public:
 #endif // MOZ_XUL
   virtual nsIMEUpdatePreference GetIMEUpdatePreference();
   NS_IMETHOD              GetNonClientMargins(nsIntMargin &margins);
   NS_IMETHOD              SetNonClientMargins(nsIntMargin &margins);
   void                    SetDrawsInTitlebar(bool aState);
   mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing() MOZ_OVERRIDE;
   virtual void            EndRemoteDrawing() MOZ_OVERRIDE;
 
+  virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) MOZ_OVERRIDE;
+
   /**
    * Event helpers
    */
   virtual bool            DispatchMouseEvent(uint32_t aEventType, WPARAM wParam,
                                              LPARAM lParam,
                                              bool aIsContextMenuKey = false,
                                              int16_t aButton = mozilla::WidgetMouseEvent::eLeftButton,
                                              uint16_t aInputSource = nsIDOMMouseEvent::MOZ_SOURCE_MOUSE);