Merge inbound to m-c. FIREFOX_AURORA_30_BASE
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 17 Mar 2014 13:16:53 -0400
changeset 191127 83c9853e136451474dfa6d1aaa60a7fca7d2d83a
parent 191112 803a735d9cf24eb698ff6fc3ff53bf25f76409ba (current diff)
parent 191126 233a33ca8ef81fca3d2b08f5f1a085ab6385fd39 (diff)
child 191128 85031ae07876659c28cf38d7fec89050aa515f49
child 192433 4811c0f6bf3faa76981665514b88400c716133ec
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone30.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 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);