Merge m-i to m-c
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 18 Jan 2014 15:17:10 -0800
changeset 164141 61fd0f987cf2e037ff209ce9e48a30a545dd4bf7
parent 164140 b3c08e6fa7901d1e6ee7728a1c42e35e57e053fe (current diff)
parent 164138 239b4d95624a6a9538cba0376d2fb5bc91f55757 (diff)
child 164142 f21e31b7f3365ee5a6cf2eb26ca079a562f6c2f4
child 164191 f038d28c034953de0633a62d7ae6f3f3e2ea2f81
child 164447 07195f5c3eb3d327b7a9c4f0dd7bfe5ec9bd30d7
push id38643
push userphilringnalda@gmail.com
push dateSat, 18 Jan 2014 23:31:24 +0000
treeherdermozilla-inbound@61fd0f987cf2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.0a1
first release with
nightly linux32
61fd0f987cf2 / 29.0a1 / 20140119030202 / files
nightly linux64
61fd0f987cf2 / 29.0a1 / 20140119030202 / files
nightly mac
61fd0f987cf2 / 29.0a1 / 20140119030202 / files
nightly win32
61fd0f987cf2 / 29.0a1 / 20140119030202 / files
nightly win64
61fd0f987cf2 / 29.0a1 / 20140119030202 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-i to m-c
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -63,16 +63,20 @@ pref("network.http.max-persistent-connec
 
 // spdy
 pref("network.http.spdy.push-allowance", 32768);
 
 // See bug 545869 for details on why these are set the way they are
 pref("network.buffer.cache.count", 24);
 pref("network.buffer.cache.size",  16384);
 
+// predictive actions
+pref("network.seer.max-db-size", 2097152); // bytes
+pref("network.seer.preserve", 50); // percentage of seer data to keep when cleaning up
+
 /* session history */
 pref("browser.sessionhistory.max_total_viewers", 1);
 pref("browser.sessionhistory.max_entries", 50);
 
 /* session store */
 pref("browser.sessionstore.resume_session_once", false);
 pref("browser.sessionstore.resume_from_crash", true);
 pref("browser.sessionstore.resume_from_crash_timeout", 60); // minutes
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -59,9 +59,11 @@ if test "$OS_TARGET" = "WINNT" -o "$OS_T
   MOZ_FOLD_LIBS=1
 fi
 MOZ_WEBGL_CONFORMANT=1
 # Enable navigator.mozPay
 MOZ_PAY=1
 # Enable activities. These are used for FxOS developers currently.
 MOZ_ACTIVITIES=1
 MOZ_JSDOWNLOADS=1
+# Enable exact rooting on desktop.
+JSGC_USE_EXACT_ROOTING=1
 
--- a/browser/metro/base/tests/mochitest/head.js
+++ b/browser/metro/base/tests/mochitest/head.js
@@ -877,16 +877,18 @@ TouchDragAndHold.prototype = {
     this._utils = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                          .getInterface(Ci.nsIDOMWindowUtils);
     this._endPoint = { xPos: aEndX, yPos: aEndY };
     this._currentPoint = { xPos: aStartX, yPos: aStartY };
     this._step = { steps: 0, x: (aEndX - aStartX) / this._numSteps, y: (aEndY - aStartY) / this._numSteps };
     if (this._debug) {
       info("[0] touchstart " + aStartX + " x " + aStartY);
     }
+    // flush layout, bug 914847
+    this._utils.elementFromPoint(aStartX, aStartY, false, true);
     if (this._native) {
       this._utils.sendNativeTouchPoint(this._pointerId, this._dui.TOUCH_CONTACT,
                                        aStartX, aStartY, 1, 90);
     } else {
       EventUtils.synthesizeTouchAtPoint(aStartX, aStartY, { type: "touchstart" }, aWindow);
     }
     let self = this;
     setTimeout(function () { self.callback(); }, this._timeoutStep);
@@ -904,17 +906,17 @@ TouchDragAndHold.prototype = {
                    x: (aEndX - this._endPoint.xPos) / this._numSteps,
                    y: (aEndY - this._endPoint.yPos) / this._numSteps };
     this._endPoint = { xPos: aEndX, yPos: aEndY };
     let self = this;
     setTimeout(function () { self.callback(); }, this._timeoutStep);
     return this._defer.promise;
   },
 
-  end: function start() {
+  end: function end() {
     if (this._debug) {
       info("[" + this._step.steps + "] touchend " + this._endPoint.xPos + " x " + this._endPoint.yPos);
       SelectionHelperUI.debugClearDebugPoints();
     }
     if (this._native) {
       this._utils.sendNativeTouchPoint(this._pointerId, this._dui.TOUCH_REMOVE,
                                        this._endPoint.xPos, this._endPoint.yPos,
                                        1, 90);
--- a/build/annotationProcessors/AnnotationInfo.java
+++ b/build/annotationProcessors/AnnotationInfo.java
@@ -6,15 +6,18 @@ package org.mozilla.gecko.annotationProc
 
 /**
  * Object holding annotation data. Used by GeneratableElementIterator.
  */
 public class AnnotationInfo {
     public final String wrapperName;
     public final boolean isStatic;
     public final boolean isMultithreaded;
+    public final boolean noThrow;
 
-    public AnnotationInfo(String aWrapperName, boolean aIsStatic, boolean aIsMultithreaded) {
+    public AnnotationInfo(String aWrapperName, boolean aIsStatic, boolean aIsMultithreaded,
+                          boolean aNoThrow) {
         wrapperName = aWrapperName;
         isStatic = aIsStatic;
         isMultithreaded = aIsMultithreaded;
+        noThrow = aNoThrow;
     }
 }
--- a/build/annotationProcessors/CodeGenerator.java
+++ b/build/annotationProcessors/CodeGenerator.java
@@ -65,21 +65,17 @@ public class CodeGenerator {
      * Emit a static method which takes an instance of the class being wrapped and returns an instance
      * of the C++ wrapper class backed by that object.
      */
     private void generateWrapperMethod() {
         headerPublic.append("    static ").append(mCClassName).append("* Wrap(jobject obj);\n" +
                 "    ").append(mCClassName).append("(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {};\n");
 
         wrapperMethodBodies.append("\n").append(mCClassName).append("* ").append(mCClassName).append("::Wrap(jobject obj) {\n" +
-                "    JNIEnv *env = GetJNIForThread();\n\n" +
-                "    if (!env) {\n" +
-                "        ALOG_BRIDGE(\"Aborted: No env - %s\", __PRETTY_FUNCTION__);\n" +
-                "        return nullptr;\n" +
-                "    }\n\n" +
+                "    JNIEnv *env = GetJNIForThread();\n" +
                 "    ").append(mCClassName).append("* ret = new ").append(mCClassName).append("(obj, env);\n" +
                 "    env->DeleteLocalRef(obj);\n" +
                 "    return ret;\n" +
                 "}\n");
     }
 
     private void generateMemberCommon(Member theMethod, String aCMethodName, Class<?> aClass) {
         ensureClassHeaderAndStartup(aClass);
@@ -109,17 +105,20 @@ public class CodeGenerator {
         // Get the C++ method signature for this method.
         String implementationSignature = Utils.getCImplementationMethodSignature(parameterTypes, returnType, CMethodName, mCClassName);
         String headerSignature = Utils.getCHeaderMethodSignature(parameterTypes, theMethod.getParameterAnnotations(), returnType, CMethodName, mCClassName, shallGenerateStatic);
 
         // Add the header signature to the header file.
         writeSignatureToHeader(headerSignature);
 
         // Use the implementation signature to generate the method body...
-        writeMethodBody(implementationSignature, CMethodName, theMethod, mClassToWrap, aMethodTuple.mAnnotationInfo.isStatic, aMethodTuple.mAnnotationInfo.isMultithreaded);
+        writeMethodBody(implementationSignature, CMethodName, theMethod, mClassToWrap,
+            aMethodTuple.mAnnotationInfo.isStatic,
+            aMethodTuple.mAnnotationInfo.isMultithreaded,
+            aMethodTuple.mAnnotationInfo.noThrow);
     }
 
     private void generateGetterOrSetterBody(Class<?> aFieldType, String aFieldName, boolean aIsFieldStatic, boolean isSetter) {
         StringBuilder argumentContent = null;
 
         if (isSetter) {
             Class<?>[] setterArguments = new Class<?>[]{aFieldType};
             // Marshall the argument..
@@ -224,17 +223,19 @@ public class CodeGenerator {
         // Slice off the "void " from the start of the constructor declaration.
         headerSignature = headerSignature.substring(5);
         implementationSignature = implementationSignature.substring(5);
 
         // Add the header signatures to the header file.
         writeSignatureToHeader(headerSignature);
 
         // Use the implementation signature to generate the method body...
-        writeCtorBody(implementationSignature, theCtor, aCtorTuple.mAnnotationInfo.isMultithreaded);
+        writeCtorBody(implementationSignature, theCtor,
+            aCtorTuple.mAnnotationInfo.isMultithreaded,
+            aCtorTuple.mAnnotationInfo.noThrow);
 
         if (theCtor.getParameterTypes().length == 0) {
             mHasEncounteredDefaultConstructor = true;
         }
     }
 
     /**
      * Writes the appropriate header and startup code to ensure the existence of a reference to the
@@ -281,30 +282,27 @@ public class CodeGenerator {
                            .append(" {\n");
 
         wrapperMethodBodies.append("    JNIEnv *env = ");
         if (!aIsThreaded) {
             wrapperMethodBodies.append("AndroidBridge::GetJNIEnv();\n");
         } else {
             wrapperMethodBodies.append("GetJNIForThread();\n");
         }
-        wrapperMethodBodies.append("    if (!env) {\n" +
-                                   "        ALOG_BRIDGE(\"Aborted: No env - %s\", __PRETTY_FUNCTION__);\n" +
-                                   "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
-                "    }\n\n");
     }
 
     /**
      * Write out the appropriate JNI frame pushing boilerplate for a call to the member provided (
      * which must be a constructor or method).
      *
      * @param aMethod A constructor/method being wrapped.
      * @param aIsObjectReturningMethod Does the method being wrapped return an object?
      */
-    private void writeFramePushBoilerplate(Member aMethod, boolean aIsObjectReturningMethod) {
+    private void writeFramePushBoilerplate(Member aMethod,
+            boolean aIsObjectReturningMethod, boolean aNoThrow) {
         if (aMethod instanceof Field) {
             throw new IllegalArgumentException("Tried to push frame for a FIELD?!");
         }
 
         Method m;
         Constructor c;
 
         Class<?> returnType;
@@ -320,23 +318,28 @@ public class CodeGenerator {
             localReferencesNeeded = Utils.enumerateReferenceArguments(c.getParameterTypes());
         }
 
         // Determine the number of local refs required for our local frame..
         // AutoLocalJNIFrame is not applicable here due to it's inability to handle return values.
         if (aIsObjectReturningMethod) {
             localReferencesNeeded++;
         }
-        wrapperMethodBodies.append("    if (env->PushLocalFrame(").append(localReferencesNeeded).append(") != 0) {\n" +
-                "        ALOG_BRIDGE(\"Exceptional exit of: %s\", __PRETTY_FUNCTION__);\n" +
-                "        env->ExceptionDescribe();\n"+
-                "        env->ExceptionClear();\n" +
-                "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
+        wrapperMethodBodies.append(
+                "    if (env->PushLocalFrame(").append(localReferencesNeeded).append(") != 0) {\n");
+        if (!aNoThrow) {
+            wrapperMethodBodies.append(
+                "        AndroidBridge::HandleUncaughtException(env);\n" +
+                "        MOZ_ASSUME_UNREACHABLE(\"Exception should have caused crash.\");\n");
+        } else {
+            wrapperMethodBodies.append(
+                "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n");
+        }
+        wrapperMethodBodies.append(
                 "    }\n\n");
-
     }
 
     private StringBuilder getArgumentMarshalling(Class<?>[] argumentTypes) {
         StringBuilder argumentContent = new StringBuilder();
 
         // If we have >2 arguments, use the jvalue[] calling approach.
         argumentContent.append(", ");
         if (argumentTypes.length > 2) {
@@ -371,22 +374,23 @@ public class CodeGenerator {
             if (needsNewline) {
                 wrapperMethodBodies.append('\n');
             }
         }
 
         return argumentContent;
     }
 
-    private void writeCtorBody(String implementationSignature, Constructor theCtor, boolean aIsThreaded) {
+    private void writeCtorBody(String implementationSignature, Constructor theCtor,
+            boolean aIsThreaded, boolean aNoThrow) {
         Class<?>[] argumentTypes = theCtor.getParameterTypes();
 
         writeFunctionStartupBoilerPlate(implementationSignature, Void.class, false, aIsThreaded);
 
-        writeFramePushBoilerplate(theCtor, false);
+        writeFramePushBoilerplate(theCtor, false, aNoThrow);
 
         // Marshall arguments for this constructor, if any...
         boolean hasArguments = argumentTypes.length != 0;
 
         StringBuilder argumentContent = new StringBuilder();
         if (hasArguments) {
             argumentContent = getArgumentMarshalling(argumentTypes);
         }
@@ -415,25 +419,27 @@ public class CodeGenerator {
      * Generates the method body of the C++ wrapper function for the Java method indicated.
      *
      * @param methodSignature The previously-generated C++ method signature for the method to be
      *                        generated.
      * @param aCMethodName    The C++ method name for the method to be generated.
      * @param aMethod         The Java method to be wrapped by the C++ method being generated.
      * @param aClass          The Java class to which the method belongs.
      */
-    private void writeMethodBody(String methodSignature, String aCMethodName, Method aMethod, Class<?> aClass, boolean aIsStaticBridgeMethod, boolean aIsMultithreaded) {
+    private void writeMethodBody(String methodSignature, String aCMethodName, Method aMethod,
+            Class<?> aClass, boolean aIsStaticBridgeMethod, boolean aIsMultithreaded,
+            boolean aNoThrow) {
         Class<?>[] argumentTypes = aMethod.getParameterTypes();
         Class<?> returnType = aMethod.getReturnType();
 
         writeFunctionStartupBoilerPlate(methodSignature, returnType, aIsStaticBridgeMethod, aIsMultithreaded);
 
         boolean isObjectReturningMethod = !returnType.getCanonicalName().equals("void") && Utils.isObjectType(returnType);
 
-        writeFramePushBoilerplate(aMethod, isObjectReturningMethod);
+        writeFramePushBoilerplate(aMethod, isObjectReturningMethod, aNoThrow);
 
         // Marshall arguments, if we have any.
         boolean hasArguments = argumentTypes.length != 0;
 
         // We buffer the arguments to the call separately to avoid needing to repeatedly iterate the
         // argument list while building this line. In the coming code block, we simultaneously
         // construct any argument marshalling code (Creation of jstrings, placement of arguments
         // into an argument array, etc. and the actual argument list passed to the function (in
@@ -472,26 +478,22 @@ public class CodeGenerator {
             // call.
             wrapperMethodBodies.append(Utils.getClassReferenceName(aClass)).append(", ");
         }
 
         wrapperMethodBodies.append(mMembersToIds.get(aMethod));
 
         // Tack on the arguments, if any..
         wrapperMethodBodies.append(argumentContent)
-                           .append(");\n\n");
+                           .append(");\n");
 
-        // Check for exception and return the failure value..
-        wrapperMethodBodies.append("    if (env->ExceptionCheck()) {\n" +
-                                   "        ALOG_BRIDGE(\"Exceptional exit of: %s\", __PRETTY_FUNCTION__);\n" +
-                                   "        env->ExceptionDescribe();\n" +
-                                   "        env->ExceptionClear();\n" +
-                                   "        env->PopLocalFrame(nullptr);\n" +
-                                   "        return").append(Utils.getFailureReturnForType(returnType)).append(";\n" +
-                                   "    }\n\n");
+        // Check for exception and crash if any...
+        if (!aNoThrow) {
+            wrapperMethodBodies.append("    AndroidBridge::HandleUncaughtException(env);\n");
+        }
 
         // If we're returning an object, pop the callee's stack frame extracting our ref as the return
         // value.
         if (isObjectReturningMethod) {
             wrapperMethodBodies.append("    ")
                                .append(Utils.getCReturnType(returnType))
                                .append(" ret = static_cast<").append(Utils.getCReturnType(returnType)).append(">(env->PopLocalFrame(temp));\n" +
                                        "    return ret;\n");
--- a/build/annotationProcessors/utils/GeneratableElementIterator.java
+++ b/build/annotationProcessors/utils/GeneratableElementIterator.java
@@ -70,31 +70,38 @@ public class GeneratableElementIterator 
             for (Annotation annotation : ((AnnotatedElement) candidateElement).getDeclaredAnnotations()) {
                 // WrappedJNIMethod has parameters. Use Reflection to obtain them.
                 Class<? extends Annotation> annotationType = annotation.annotationType();
                 final String annotationTypeName = annotationType.getName();
                 if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI")) {
                     String stubName = null;
                     boolean isStaticStub = false;
                     boolean isMultithreadedStub = false;
+                    boolean noThrow = false;
                     try {
                         // Determine the explicitly-given name of the stub to generate, if any.
                         final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
                         stubNameMethod.setAccessible(true);
                         stubName = (String) stubNameMethod.invoke(annotation);
 
                         // Detemine if the generated stub should be static.
                         final Method staticStubMethod = annotationType.getDeclaredMethod("generateStatic");
                         staticStubMethod.setAccessible(true);
                         isStaticStub = (Boolean) staticStubMethod.invoke(annotation);
 
                         // Determine if the generated stub is to allow calls from multiple threads.
                         final Method multithreadedStubMethod = annotationType.getDeclaredMethod("allowMultithread");
                         multithreadedStubMethod.setAccessible(true);
                         isMultithreadedStub = (Boolean) multithreadedStubMethod.invoke(annotation);
+
+                        // Determine if ignoring exceptions
+                        final Method noThrowMethod = annotationType.getDeclaredMethod("noThrow");
+                        noThrowMethod.setAccessible(true);
+                        noThrow = (Boolean) noThrowMethod.invoke(annotation);
+
                     } catch (NoSuchMethodException e) {
                         System.err.println("Unable to find expected field on WrapElementForJNI annotation. Did the signature change?");
                         e.printStackTrace(System.err);
                         System.exit(3);
                     } catch (IllegalAccessException e) {
                         System.err.println("IllegalAccessException reading fields on WrapElementForJNI annotation. Seems the semantics of Reflection have changed...");
                         e.printStackTrace(System.err);
                         System.exit(4);
@@ -105,26 +112,28 @@ public class GeneratableElementIterator 
                     }
 
                     // If the method name was not explicitly given in the annotation generate one...
                     if (stubName.isEmpty()) {
                         String aMethodName = candidateElement.getName();
                         stubName = aMethodName.substring(0, 1).toUpperCase() + aMethodName.substring(1);
                     }
 
-                    AnnotationInfo annotationInfo = new AnnotationInfo(stubName, isStaticStub, isMultithreadedStub);
+                    AnnotationInfo annotationInfo = new AnnotationInfo(
+                        stubName, isStaticStub, isMultithreadedStub, noThrow);
                     mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
                     return;
                 }
             }
 
             // If no annotation found, we might be expected to generate anyway using default arguments,
             // thanks to the "Generate everything" annotation.
             if (mIterateEveryEntry) {
-                AnnotationInfo annotationInfo = new AnnotationInfo(candidateElement.getName(), false, false);
+                AnnotationInfo annotationInfo = new AnnotationInfo(
+                    candidateElement.getName(), false, false, false);
                 mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
                 return;
             }
         }
         mNextReturnValue = null;
     }
 
     @Override
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -95,17 +95,17 @@ nsScriptSecurityManager::SubjectIsPrivil
 static inline const char16_t *
 IDToString(JSContext *cx, jsid id_)
 {
     JS::RootedId id(cx, id_);
     if (JSID_IS_STRING(id))
         return JS_GetInternedStringChars(JSID_TO_STRING(id));
 
     JS::Rooted<JS::Value> idval(cx);
-    if (!JS_IdToValue(cx, id, idval.address()))
+    if (!JS_IdToValue(cx, id, &idval))
         return nullptr;
     JSString *str = JS::ToString(cx, idval);
     if(!str)
         return nullptr;
     return JS_GetStringCharsZ(cx, str);
 }
 
 class nsAutoInPrincipalDomainOriginSetter {
--- a/configure.in
+++ b/configure.in
@@ -1545,60 +1545,16 @@ if test "$MOZ_PROFILING" -a -z "$STRIP_F
     case "$OS_TARGET" in
     Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
         STRIP_FLAGS="--strip-debug"
         ;;
     esac
 fi
 
 dnl ========================================================
-dnl = Use incremental GC
-dnl ========================================================
-JSGC_INCREMENTAL=1
-MOZ_ARG_DISABLE_BOOL(gcincremental,
-[  --disable-gcincremental Disable incremental GC],
-    JSGC_INCREMENTAL= )
-if test -n "$JSGC_INCREMENTAL"; then
-    AC_DEFINE(JSGC_INCREMENTAL)
-fi
-
-dnl ========================================================
-dnl = Use generational GC
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(gcgenerational,
-[  --enable-gcgenerational Enable generational GC],
-    JSGC_GENERATIONAL=1,
-    JSGC_GENERATIONAL= )
-if test -n "$JSGC_GENERATIONAL"; then
-    AC_DEFINE(JSGC_GENERATIONAL)
-fi
-
-dnl ========================================================
-dnl = Perform moving GC stack rooting analysis
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(root-analysis,
-[  --enable-root-analysis  Enable moving GC stack root analysis],
-    JSGC_ROOT_ANALYSIS=1,
-    JSGC_ROOT_ANALYSIS= )
-if test -n "$JSGC_ROOT_ANALYSIS"; then
-    AC_DEFINE(JSGC_ROOT_ANALYSIS)
-fi
-
-dnl ========================================================
-dnl = Use exact stack rooting for GC
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(exact-rooting,
-[  --enable-exact-rooting  Enable use of exact stack roots for GC],
-    JSGC_USE_EXACT_ROOTING=1,
-    JSGC_USE_EXACT_ROOTING= )
-if test -n "$JSGC_USE_EXACT_ROOTING"; then
-    AC_DEFINE(JSGC_USE_EXACT_ROOTING)
-fi
-
-dnl ========================================================
 dnl = Use Valgrind
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(valgrind,
 [  --enable-valgrind       Enable Valgrind integration hooks (default=no)],
     MOZ_VALGRIND=1,
     MOZ_VALGRIND= )
 if test -n "$MOZ_VALGRIND"; then
     MOZ_CHECK_HEADER([valgrind/valgrind.h], [],
@@ -4059,16 +4015,17 @@ MOZ_ANDROID_BEAM=
 MOZ_ANDROID_SYNTHAPKS=
 ACCESSIBILITY=1
 MOZ_TIME_MANAGER=
 MOZ_PAY=
 MOZ_AUDIO_CHANNEL_MANAGER=
 NSS_NO_LIBPKIX=
 MOZ_CONTENT_SANDBOX=
 MOZ_CONTENT_SANDBOX_REPORTER=
+JSGC_USE_EXACT_ROOTING=
 
 case "$target_os" in
     mingw*)
         NS_ENABLE_TSF=1
         AC_DEFINE(NS_ENABLE_TSF)
         ;;
 esac
 
@@ -4203,16 +4160,20 @@ MOZ_ARG_WITH_STRING(app-name,
 [--with-app-name=APPNAME sets MOZ_APP_NAME to APPNAME],
 WITH_APP_NAME=$withval,
 )
 
 if test -n "$WITH_APP_NAME" ; then
     MOZ_APP_NAME="$WITH_APP_NAME"
 fi
 
+if test -z "$MOZ_APP_NAME"; then
+   MOZ_APP_NAME=`echo $MOZ_APP_BASENAME | tr A-Z a-z`
+fi
+
 MOZ_ARG_WITH_STRING(app-basename,
 [--with-app-basename=BASENAME sets MOZ_APP_BASENAME to BASENAME],
 WITH_APP_BASENAME=$withval,
 )
 
 if test -n "$WITH_APP_BASENAME" ; then
     MOZ_APP_BASENAME="$WITH_APP_BASENAME"
 fi
@@ -7069,16 +7030,17 @@ MOZ_ARG_ENABLE_BOOL(wrap-malloc,
     _WRAP_MALLOC=1,
     _WRAP_MALLOC= )
 
 if test -n "$_WRAP_MALLOC"; then
     if test -n "$GNU_CC"; then
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=malloc,--wrap=calloc,--wrap=valloc,--wrap=free,--wrap=realloc,--wrap=memalign"
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=__builtin_new,--wrap=__builtin_vec_new,--wrap=__builtin_delete,--wrap=__builtin_vec_delete"
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=strdup,--wrap=strndup"
+        WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=vasprintf,--wrap=asprintf"
         WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=posix_memalign,--wrap=malloc_usable_size"
         dnl Wrap operator new and operator delete on Android.
         if test "$OS_TARGET" = "Android"; then
             WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=_Znwj,--wrap=_Znaj,--wrap=_ZdlPv,--wrap=_ZdaPv"
             dnl Wrap the nothrow variants too.
             WRAP_LDFLAGS="${WRAP_LDFLAGS} -Wl,--wrap=_ZnwjRKSt9nothrow_t,--wrap=_ZnajRKSt9nothrow_t,--wrap=_ZdlPvRKSt9nothrow_t,--wrap=_ZdaPvRKSt9nothrow_t"
         fi
     else
@@ -7100,47 +7062,80 @@ MOZ_ARG_ENABLE_BOOL(trace-jscalls,
 [  --enable-trace-jscalls  Enable JS call enter/exit callback (default=no)],
     MOZ_TRACE_JSCALLS=1,
     MOZ_TRACE_JSCALLS= )
 if test -n "$MOZ_TRACE_JSCALLS"; then
     AC_DEFINE(MOZ_TRACE_JSCALLS)
 fi
 
 dnl ========================================================
+dnl JS opt-mode assertions and minidump instrumentation
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(js-diagnostics,
+[  --enable-js-diagnostics
+                          Enable JS diagnostic assertions and breakpad data],
+    JS_CRASH_DIAGNOSTICS=1,
+    JS_CRASH_DIAGNOSTICS= )
+if test -n "$JS_CRASH_DIAGNOSTICS"; then
+    AC_DEFINE(JS_CRASH_DIAGNOSTICS)
+fi
+
+dnl ========================================================
 dnl = Use incremental GC
 dnl ========================================================
 JSGC_INCREMENTAL=1
 MOZ_ARG_DISABLE_BOOL(gcincremental,
 [  --disable-gcincremental Disable incremental GC],
     JSGC_INCREMENTAL= )
 if test -n "$JSGC_INCREMENTAL"; then
     AC_DEFINE(JSGC_INCREMENTAL)
 fi
 
 dnl ========================================================
+dnl = Use exact stack rooting for GC
+dnl ========================================================
+MOZ_ARG_DISABLE_BOOL(exact-rooting,
+[  --disable-exact-rooting  Enable use of conservative stack scanning for GC],
+    JSGC_USE_EXACT_ROOTING= ,
+    JSGC_USE_EXACT_ROOTING=1 )
+if test -n "$JSGC_USE_EXACT_ROOTING"; then
+    AC_DEFINE(JSGC_USE_EXACT_ROOTING)
+fi
+
+dnl ========================================================
+dnl = Use generational GC
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(gcgenerational,
+[  --enable-gcgenerational Enable generational GC],
+    JSGC_GENERATIONAL=1,
+    JSGC_GENERATIONAL= )
+if test -n "$JSGC_GENERATIONAL"; then
+    AC_DEFINE(JSGC_GENERATIONAL)
+fi
+
+dnl ========================================================
 dnl Zealous JavaScript GC
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(gczeal,
 [  --enable-gczeal         Enable zealous JavaScript GCing],
     JS_GC_ZEAL=1,
     JS_GC_ZEAL= )
 if test -n "$JS_GC_ZEAL" -o -n "$MOZ_DEBUG"; then
     AC_DEFINE(JS_GC_ZEAL)
 fi
 
 dnl ========================================================
-dnl JS opt-mode assertions and minidump instrumentation
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(js-diagnostics,
-[  --enable-js-diagnostics
-                          Enable JS diagnostic assertions and breakpad data],
-    JS_CRASH_DIAGNOSTICS=1,
-    JS_CRASH_DIAGNOSTICS= )
-if test -n "$JS_CRASH_DIAGNOSTICS"; then
-    AC_DEFINE(JS_CRASH_DIAGNOSTICS)
+dnl = Perform moving GC stack rooting analysis
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(root-analysis,
+[  --enable-root-analysis  Enable moving GC stack root analysis],
+    JSGC_ROOT_ANALYSIS=1,
+    JSGC_ROOT_ANALYSIS= )
+if test -n "$JSGC_ROOT_ANALYSIS"; then
+    AC_DEFINE(JSGC_ROOT_ANALYSIS)
 fi
 
 MOZ_CHECK_CCACHE
 MOZ_CHECK_COMPILER_WRAPPER
 
 dnl ========================================================
 dnl = Enable static checking using gcc-dehydra
 dnl ========================================================
@@ -8457,20 +8452,16 @@ AC_SUBST(MOZ_CHILD_PROCESS_BUNDLE)
 # defaults to a lowercase form of MOZ_APP_BASENAME.
 # - MOZ_APP_PROFILE: When set, used for application.ini's
 # "Profile" field, which controls profile location.
 # - MOZ_APP_ID: When set, used for application.ini's "ID" field, and
 # crash reporter server url.
 # - MOZ_PROFILE_MIGRATOR: When set, enables profile migrator.
 # - MOZ_EXTENSION_MANAGER: When set, enabled extension manager.
 
-if test -z "$MOZ_APP_NAME"; then
-   MOZ_APP_NAME=`echo $MOZ_APP_BASENAME | tr A-Z a-z`
-fi
-
 # For extensions and langpacks, we require a max version that is compatible
 # across security releases. MOZ_APP_MAXVERSION is our method for doing that.
 # 10.0a1 and 10.0a2 aren't affected
 # 10.0 becomes 10.0.*
 # 10.0.1 becomes 10.0.*
 IS_ALPHA=`echo $MOZ_APP_VERSION | grep a`
 if test -z "$IS_ALPHA"; then
   changequote(,)
@@ -9109,16 +9100,19 @@ if test "$BUILD_CTYPES"; then
     ac_configure_args="$ac_configure_args --enable-ctypes"
 fi
 if test -z "$JS_SHARED_LIBRARY" ; then
     ac_configure_args="$ac_configure_args --disable-shared-js"
     if test -n "$MOZ_DISABLE_EXPORT_JS"; then
         ac_configure_args="$ac_configure_args --disable-export-js"
     fi
 fi
+if test -z "$JSGC_USE_EXACT_ROOTING" ; then
+    ac_configure_args="$ac_configure_args --disable-exact-rooting"
+fi
 if test -z "$MOZ_NATIVE_NSPR"; then
     ac_configure_args="$ac_configure_args --with-nspr-cflags='$NSPR_CFLAGS'"
     ac_configure_args="$ac_configure_args --with-nspr-libs='$NSPR_LIBS'"
 fi
 ac_configure_args="$ac_configure_args --with-dist-dir=../../dist"
 ac_configure_args="$ac_configure_args --prefix=$dist"
 if test "$MOZ_MEMORY"; then
    ac_configure_args="$ac_configure_args --enable-jemalloc"
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5381,17 +5381,17 @@ nsDocument::Register(JSContext* aCx, con
 
   nsContentUtils::DispatchTrustedEvent(this, static_cast<nsIDocument*>(this),
                                        NS_LITERAL_STRING("elementupgrade"),
                                        true, true);
 
   // Create constructor to return. Store the name of the custom element as the
   // name of the function.
   JSFunction* constructor = JS_NewFunction(aCx, CustomElementConstructor, 0,
-                                           JSFUN_CONSTRUCTOR, nullptr,
+                                           JSFUN_CONSTRUCTOR, JS::NullPtr(),
                                            NS_ConvertUTF16toUTF8(lcName).get());
   JSObject* constructorObject = JS_GetFunctionObject(constructor);
   return constructorObject;
 }
 
 NS_IMETHODIMP
 nsDocument::GetElementsByTagName(const nsAString& aTagname,
                                  nsIDOMNodeList** aReturn)
--- a/content/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/content/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -252,18 +252,19 @@ MediaEngineTabVideoSource::Draw() {
   gfxPoint pt(0, 0);
   context->Translate(pt);
   context->Scale(scale * size.width / srcW, scale * size.height / srcH);
   rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
 
   NS_ENSURE_SUCCESS_VOID(rv);
 
   layers::CairoImage::Data cairoData;
-  cairoData.mSurface = surf;
+  cairoData.mDeprecatedSurface = surf;
   cairoData.mSize = size;
+  cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surf);
 
   nsRefPtr<layers::CairoImage> image = new layers::CairoImage();
 
   image->SetData(cairoData);
 
   MonitorAutoLock mon(mMonitor);
   mImage = image;
 }
--- a/content/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
+++ b/content/media/webspeech/synth/ipc/SpeechSynthesisChild.cpp
@@ -107,24 +107,16 @@ bool
 SpeechSynthesisRequestChild::RecvOnResume(const float& aElapsedTime,
                                           const uint32_t& aCharIndex)
 {
   mTask->DispatchResumeImpl(aElapsedTime, aCharIndex);
   return true;
 }
 
 bool
-SpeechSynthesisRequestChild::RecvOnError(const float& aElapsedTime,
-                                         const uint32_t& aCharIndex)
-{
-  mTask->DispatchErrorImpl(aElapsedTime, aCharIndex);
-  return true;
-}
-
-bool
 SpeechSynthesisRequestChild::RecvOnBoundary(const nsString& aName,
                                             const float& aElapsedTime,
                                             const uint32_t& aCharIndex)
 {
   mTask->DispatchBoundaryImpl(aName, aElapsedTime, aCharIndex);
   return true;
 }
 
--- a/content/media/webspeech/synth/ipc/SpeechSynthesisChild.h
+++ b/content/media/webspeech/synth/ipc/SpeechSynthesisChild.h
@@ -17,59 +17,57 @@ class nsSynthVoiceRegistry;
 class SpeechSynthesisRequestChild;
 class SpeechTaskChild;
 
 class SpeechSynthesisChild : public PSpeechSynthesisChild
 {
   friend class nsSynthVoiceRegistry;
 
 public:
-  bool RecvVoiceAdded(const RemoteVoice& aVoice);
+  bool RecvVoiceAdded(const RemoteVoice& aVoice) MOZ_OVERRIDE;
 
-  bool RecvVoiceRemoved(const nsString& aUri);
+  bool RecvVoiceRemoved(const nsString& aUri) MOZ_OVERRIDE;
 
-  bool RecvSetDefaultVoice(const nsString& aUri, const bool& aIsDefault);
+  bool RecvSetDefaultVoice(const nsString& aUri, const bool& aIsDefault) MOZ_OVERRIDE;
 
 protected:
   SpeechSynthesisChild();
   virtual ~SpeechSynthesisChild();
 
   PSpeechSynthesisRequestChild* AllocPSpeechSynthesisRequestChild(const nsString& aLang,
                                                                   const nsString& aUri,
                                                                   const nsString& aText,
                                                                   const float& aVolume,
                                                                   const float& aPitch,
-                                                                  const float& aRate);
-  bool DeallocPSpeechSynthesisRequestChild(PSpeechSynthesisRequestChild* aActor);
+                                                                  const float& aRate) MOZ_OVERRIDE;
+  bool DeallocPSpeechSynthesisRequestChild(PSpeechSynthesisRequestChild* aActor) MOZ_OVERRIDE;
 };
 
 class SpeechSynthesisRequestChild : public PSpeechSynthesisRequestChild
 {
 public:
   SpeechSynthesisRequestChild(SpeechTaskChild* aTask);
   virtual ~SpeechSynthesisRequestChild();
 
 protected:
-  virtual bool RecvOnStart();
+  virtual bool RecvOnStart() MOZ_OVERRIDE;
 
   virtual bool Recv__delete__(const bool& aIsError,
                               const float& aElapsedTime,
-                              const uint32_t& aCharIndex);
-
-  virtual bool RecvOnPause(const float& aElapsedTime, const uint32_t& aCharIndex);
+                              const uint32_t& aCharIndex) MOZ_OVERRIDE;
 
-  virtual bool RecvOnResume(const float& aElapsedTime, const uint32_t& aCharIndex);
+  virtual bool RecvOnPause(const float& aElapsedTime, const uint32_t& aCharIndex) MOZ_OVERRIDE;
 
-  virtual bool RecvOnError(const float& aElapsedTime, const uint32_t& aCharIndex);
+  virtual bool RecvOnResume(const float& aElapsedTime, const uint32_t& aCharIndex) MOZ_OVERRIDE;
 
   virtual bool RecvOnBoundary(const nsString& aName, const float& aElapsedTime,
-                              const uint32_t& aCharIndex);
+                              const uint32_t& aCharIndex) MOZ_OVERRIDE;
 
   virtual bool RecvOnMark(const nsString& aName, const float& aElapsedTime,
-                          const uint32_t& aCharIndex);
+                          const uint32_t& aCharIndex) MOZ_OVERRIDE;
 
   nsRefPtr<SpeechTaskChild> mTask;
 };
 
 class SpeechTaskChild : public nsSpeechTask
 {
   friend class SpeechSynthesisRequestChild;
 public:
--- a/content/media/webspeech/synth/ipc/SpeechSynthesisParent.h
+++ b/content/media/webspeech/synth/ipc/SpeechSynthesisParent.h
@@ -18,54 +18,55 @@ class SpeechSynthesisRequestParent;
 
 class SpeechSynthesisParent : public PSpeechSynthesisParent
 {
   friend class ContentParent;
   friend class SpeechSynthesisRequestParent;
 
 public:
   bool RecvReadVoiceList(InfallibleTArray<RemoteVoice>* aVoices,
-                         InfallibleTArray<nsString>* aDefaults);
+                         InfallibleTArray<nsString>* aDefaults) MOZ_OVERRIDE;
 
 protected:
   SpeechSynthesisParent();
   virtual ~SpeechSynthesisParent();
   PSpeechSynthesisRequestParent* AllocPSpeechSynthesisRequestParent(const nsString& aText,
                                                                     const nsString& aLang,
                                                                     const nsString& aUri,
                                                                     const float& aVolume,
                                                                     const float& aRate,
-                                                                    const float& aPitch);
+                                                                    const float& aPitch)
+                                                                    MOZ_OVERRIDE;
 
-  bool DeallocPSpeechSynthesisRequestParent(PSpeechSynthesisRequestParent* aActor);
+  bool DeallocPSpeechSynthesisRequestParent(PSpeechSynthesisRequestParent* aActor) MOZ_OVERRIDE;
 
   bool RecvPSpeechSynthesisRequestConstructor(PSpeechSynthesisRequestParent* aActor,
                                               const nsString& aText,
                                               const nsString& aLang,
                                               const nsString& aUri,
                                               const float& aVolume,
                                               const float& aRate,
-                                              const float& aPitch);
+                                              const float& aPitch) MOZ_OVERRIDE;
 };
 
 class SpeechSynthesisRequestParent : public PSpeechSynthesisRequestParent
 {
 public:
   SpeechSynthesisRequestParent(SpeechTaskParent* aTask);
   virtual ~SpeechSynthesisRequestParent();
 
   nsRefPtr<SpeechTaskParent> mTask;
 
 protected:
 
-  virtual bool RecvPause();
+  virtual bool RecvPause() MOZ_OVERRIDE;
 
-  virtual bool RecvResume();
+  virtual bool RecvResume() MOZ_OVERRIDE;
 
-  virtual bool RecvCancel();
+  virtual bool RecvCancel() MOZ_OVERRIDE;
 };
 
 class SpeechTaskParent : public nsSpeechTask
 {
   friend class SpeechSynthesisRequestParent;
 public:
   SpeechTaskParent(float aVolume, const nsAString& aUtterance)
     : nsSpeechTask(aVolume, aUtterance) {}
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -585,17 +585,17 @@ FindObjectClass(JSContext* cx, JSObject*
 }
 
 static inline JSString *
 IdToString(JSContext *cx, jsid id)
 {
   if (JSID_IS_STRING(id))
     return JSID_TO_STRING(id);
   JS::Rooted<JS::Value> idval(cx);
-  if (!::JS_IdToValue(cx, id, idval.address()))
+  if (!::JS_IdToValue(cx, id, &idval))
     return nullptr;
   return JS::ToString(cx, idval);
 }
 
 static inline nsresult
 WrapNative(JSContext *cx, JSObject *scope, nsISupports *native,
            nsWrapperCache *cache, const nsIID* aIID, JS::MutableHandle<JS::Value> vp,
            bool aAllowWrapping)
@@ -1306,17 +1306,17 @@ nsDOMClassInfo::GetArrayIndexFromId(JSCo
   }
 
   int i;
   if (JSID_IS_INT(id)) {
       i = JSID_TO_INT(id);
   } else {
       JS::Rooted<JS::Value> idval(cx);
       double array_index;
-      if (!::JS_IdToValue(cx, id, idval.address()) ||
+      if (!::JS_IdToValue(cx, id, &idval) ||
           !JS::ToNumber(cx, idval, &array_index) ||
           !::JS_DoubleIsInt32(array_index, &i)) {
         return -1;
       }
   }
 
   if (aIsNumber) {
     *aIsNumber = true;
@@ -4353,17 +4353,19 @@ nsStorage2SH::NewEnumerate(nsIXPConnectW
     (nsTArray<nsString> *)JSVAL_TO_PRIVATE(*statep);
 
   if (enum_op == JSENUMERATE_NEXT && keys->Length() != 0) {
     nsString& key = keys->ElementAt(0);
     JSString *str =
       JS_NewUCStringCopyN(cx, key.get(), key.Length());
     NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY);
 
-    JS_ValueToId(cx, STRING_TO_JSVAL(str), idp);
+    JS::Rooted<jsid> id(cx);
+    JS_ValueToId(cx, JS::StringValue(str), &id);
+    *idp = id;
 
     keys->RemoveElementAt(0);
 
     return NS_OK;
   }
 
   // destroy the keys array if we have no keys or if we're done
   NS_ABORT_IF_FALSE(enum_op == JSENUMERATE_DESTROY ||
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -1474,17 +1474,17 @@ AppendNamedPropertyIds(JSContext* cx, JS
 {
   for (uint32_t i = 0; i < names.Length(); ++i) {
     JS::Rooted<JS::Value> v(cx);
     if (!xpc::NonVoidStringToJsval(cx, names[i], &v)) {
       return false;
     }
 
     JS::Rooted<jsid> id(cx);
-    if (!JS_ValueToId(cx, v, id.address())) {
+    if (!JS_ValueToId(cx, v, &id)) {
       return false;
     }
 
     if (shadowPrototypeProperties || !HasPropertyOnPrototype(cx, proxy, id)) {
       if (!props.append(id)) {
         return false;
       }
     }
@@ -1604,17 +1604,18 @@ NativeToString(JSContext* cx, JS::Handle
           str = JS_NewStringCopyZ(cx, clasp->name);
           str = ConcatJSString(cx, "[object ", str, "]");
         } else if (IsDOMIfaceAndProtoClass(clasp)) {
           const DOMIfaceAndProtoJSClass* ifaceAndProtoJSClass =
             DOMIfaceAndProtoJSClass::FromJSClass(clasp);
           str = JS_NewStringCopyZ(cx, ifaceAndProtoJSClass->mToString);
         } else {
           MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
-          str = JS_DecompileFunction(cx, JS_GetObjectFunction(obj), 0);
+          JS::Rooted<JSFunction*> fun(cx, JS_GetObjectFunction(obj));
+          str = JS_DecompileFunction(cx, fun, 0);
         }
       }
       str = ConcatJSString(cx, pre, str, post);
     }
   }
 
   if (!str) {
     return false;
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -5220,17 +5220,18 @@ if (!${obj}) {
             if (self.idlNode.getExtendedAttribute("Cached") and
                 self.descriptor.wrapperCache):
                 preserveWrapper = "PreserveWrapper(self);\n"
             else:
                 preserveWrapper = ""
             if self.idlNode.getExtendedAttribute("Frozen"):
                 assert self.idlNode.type.isSequence()
                 freezeValue = CGGeneric(
-                    "if (!JS_FreezeObject(cx, &args.rval().toObject())) {\n"
+                    "JS::Rooted<JSObject*> rvalObj(cx, &args.rval().toObject());\n"
+                    "if (!JS_FreezeObject(cx, rvalObj)) {\n"
                     "  return false;\n"
                     "}")
                 if self.idlNode.type.nullable():
                     freezeValue = CGIfWrapper(freezeValue,
                                               "args.rval().isObject()")
                 freezeValue = freezeValue.define() + "\n"
             else:
                 freezeValue = ""
@@ -5900,17 +5901,17 @@ class CGGenericMethod(CGAbstractBindingM
         CGAbstractBindingMethod.__init__(self, descriptor, name,
                                          args,
                                          unwrapFailureCode=unwrapFailureCode,
                                          allowCrossOriginThis=allowCrossOriginThis)
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
             "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
-            "MOZ_ASSERT(info->type == JSJitInfo::Method);\n"
+            "MOZ_ASSERT(info->type() == JSJitInfo::Method);\n"
             "JSJitMethodOp method = info->method;\n"
             "return method(cx, obj, self, JSJitMethodCallArgs(args));"))
 
 class CGSpecializedMethod(CGAbstractStaticMethod):
     """
     A class for generating the C++ code for a specialized method that the JIT
     can call with lower overhead.
     """
@@ -6105,17 +6106,17 @@ class CGGenericGetter(CGAbstractBindingM
                 descriptor.interface.identifier.name)
         CGAbstractBindingMethod.__init__(self, descriptor, name, args,
                                          unwrapFailureCode,
                                          allowCrossOriginThis=allowCrossOriginThis)
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
             "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
-            "MOZ_ASSERT(info->type == JSJitInfo::Getter);\n"
+            "MOZ_ASSERT(info->type() == JSJitInfo::Getter);\n"
             "JSJitGetterOp getter = info->getter;\n"
             "return getter(cx, obj, self, JSJitGetterCallArgs(args));"))
 
 class CGSpecializedGetter(CGAbstractStaticMethod):
     """
     A class for generating the code for a specialized attribute getter
     that the JIT can call with lower overhead.
     """
@@ -6221,17 +6222,17 @@ class CGGenericSetter(CGAbstractBindingM
                                          allowCrossOriginThis=allowCrossOriginThis)
 
     def generate_code(self):
         return CGIndenter(CGGeneric(
                 "if (args.length() == 0) {\n"
                 '  return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "%s attribute setter");\n'
                 "}\n"
                 "const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));\n"
-                "MOZ_ASSERT(info->type == JSJitInfo::Setter);\n"
+                "MOZ_ASSERT(info->type() == JSJitInfo::Setter);\n"
                 "JSJitSetterOp setter = info->setter;\n"
                 "if (!setter(cx, obj, self, JSJitSetterCallArgs(args))) {\n"
                 "  return false;\n"
                 "}\n"
                 "args.rval().set(JSVAL_VOID);\n"
                 "return true;" % self.descriptor.interface.identifier.name))
 
 class CGSpecializedSetter(CGAbstractStaticMethod):
@@ -6352,26 +6353,26 @@ class CGMemberJITInfo(CGThing):
                             "")
         def jitInfoInitializer(isTypedMethod):
             typedMethodStr = toStringBool(isTypedMethod)
             return ("{\n"
                     " { %s },\n"
                     "  %s,\n"
                     "  %s,\n"
                     "  JSJitInfo::%s,\n"
+                    "  JSJitInfo::%s, /* aliasSet.  Not relevant for setters. */\n"
                     "  %s,  /* returnType.  Not relevant for setters. */\n"
                     "  %s,  /* isInfallible. False in setters. */\n"
                     "  %s,  /* isMovable.  Not relevant for setters. */\n"
                     "  %s,  /* isInSlot.  Only relevant for getters. */\n"
                     "  %s,  /* isTypedMethod.  Only relevant for methods. */\n"
-                    "  %s,  /* Reserved slot index, if we're stored in a slot, else 0. */\n"
-                    "  JSJitInfo::%s  /* aliasSet.  Not relevant for setters. */\n"
-                    "}" % (opName, protoID, depth, opType,
+                    "  %s   /* Reserved slot index, if we're stored in a slot, else 0. */\n"
+                    "}" % (opName, protoID, depth, opType, aliasSet,
                            returnType, failstr, movablestr, slotStr,
-                           typedMethodStr, slotIndex, aliasSet))
+                           typedMethodStr, slotIndex))
         if args is not None:
             argTypes = "%s_argTypes" % infoName
             args = [CGMemberJITInfo.getJSArgType(arg.type) for arg in args]
             args.append("JSJitInfo::ArgTypeListEnd")
             argTypesDecl = (
                 "static const JSJitInfo::ArgType %s[] = { %s };\n" %
                 (argTypes, ", ".join(args)))
             return ("\n"
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -280,17 +280,17 @@ DOMProxyHandler::has(JSContext* cx, JS::
 }
 
 int32_t
 IdToInt32(JSContext* cx, JS::Handle<jsid> id)
 {
   JS::Rooted<JS::Value> idval(cx);
   double array_index;
   int32_t i;
-  if (!::JS_IdToValue(cx, id, idval.address()) ||
+  if (!::JS_IdToValue(cx, id, &idval) ||
       !JS::ToNumber(cx, idval, &array_index) ||
       !::JS_DoubleIsInt32(array_index, &i)) {
     return -1;
   }
 
   return i;
 }
 
--- a/dom/events/nsEventListenerService.cpp
+++ b/dom/events/nsEventListenerService.cpp
@@ -89,17 +89,17 @@ nsEventListenerInfo::GetJSVal(JSContext*
       return false;
     }
     aAc.construct(aCx, object);
     *aJSVal = OBJECT_TO_JSVAL(object);
     return true;
   }
 
   nsCOMPtr<nsIJSEventListener> jsl = do_QueryInterface(mListener);
-  if (jsl) {
+  if (jsl && jsl->GetHandler().HasEventHandler()) {
     JS::Handle<JSObject*> handler(jsl->GetHandler().Ptr()->Callable());
     if (handler) {
       aAc.construct(aCx, handler);
       *aJSVal = OBJECT_TO_JSVAL(handler);
       return true;
     }
   }
   return false;
--- a/dom/events/nsIMEStateManager.cpp
+++ b/dom/events/nsIMEStateManager.cpp
@@ -63,16 +63,20 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
 
   void     Init(nsIWidget* aWidget,
                 nsPresContext* aPresContext,
                 nsIContent* aContent);
   void     Destroy(void);
   bool     IsManaging(nsPresContext* aPresContext, nsIContent* aContent);
+  bool     KeepAliveDuringDeactive() const
+  {
+    return !!(mObserving & nsIMEUpdatePreference::NOTIFY_DURING_DEACTIVE);
+  }
 
   nsCOMPtr<nsIWidget>            mWidget;
   nsCOMPtr<nsISelection>         mSel;
   nsCOMPtr<nsIContent>           mRootContent;
   nsCOMPtr<nsINode>              mEditableNode;
 
 private:
   void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
@@ -221,16 +225,17 @@ nsIMEStateManager::OnChangeFocusInternal
     // If we're deactivating, we shouldn't commit composition forcibly because
     // the user may want to continue the composition.
     if (aPresContext) {
       NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
     }
   }
 
   if (sTextStateObserver &&
+      (aPresContext || !sTextStateObserver->KeepAliveDuringDeactive()) &&
       !sTextStateObserver->IsManaging(aPresContext, aContent)) {
     DestroyTextStateManager();
   }
 
   if (!aPresContext) {
     return NS_OK;
   }
 
--- a/dom/events/test/test_bug448602.html
+++ b/dom/events/test/test_bug448602.html
@@ -56,16 +56,24 @@ function runTests() {
     jsd.on();
     ok(jsd.isOn, "JSD should be running.");
   }
   var jsdvalue = infos[0].getDebugObject().QueryInterface(SpecialPowers.Ci.jsdIValue);
   is(jsdvalue.jsType, 3, "Event listener should be a function! (1)");
 */
 
   root.removeAttribute("onclick");
+  root.setAttribute("onclick", "...invalid script...");
+  SimpleTest.expectUncaughtException(true);
+  infos = els.getListenerInfoFor(root, {});
+  SimpleTest.expectUncaughtException(false);
+  is(infos.length, 1);
+  is(infos[0].listenerObject, null);
+
+  root.removeAttribute("onclick");
   infos = els.getListenerInfoFor(root, {});
   is(infos.length, 0, "Element shouldn't have listeners (2)");
 
   var l = function (e) { alert(e); };
   root.addEventListener("foo", l, true, true);
   root.addEventListener("foo", l, false, false);
   infos = els.getListenerInfoFor(root, {});
   is(infos.length, 2, "Element should have listeners (2)");
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -81,176 +81,179 @@ public:
 
     PCompositorChild*
     AllocPCompositorChild(mozilla::ipc::Transport* aTransport,
                           base::ProcessId aOtherProcess) MOZ_OVERRIDE;
     PImageBridgeChild*
     AllocPImageBridgeChild(mozilla::ipc::Transport* aTransport,
                            base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
-    virtual bool RecvSetProcessPrivileges(const ChildPrivileges& aPrivs);
+    virtual bool RecvSetProcessPrivileges(const ChildPrivileges& aPrivs) MOZ_OVERRIDE;
 
     virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext &aContext,
                                               const uint32_t &chromeFlags);
     virtual bool DeallocPBrowserChild(PBrowserChild*);
 
     virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequestChild(const DeviceStorageParams&);
     virtual bool DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild*);
 
     virtual PBlobChild* AllocPBlobChild(const BlobConstructorParams& aParams);
     virtual bool DeallocPBlobChild(PBlobChild*);
 
     virtual PCrashReporterChild*
     AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
-                             const uint32_t& processType);
+                             const uint32_t& processType) MOZ_OVERRIDE;
     virtual bool
-    DeallocPCrashReporterChild(PCrashReporterChild*);
+    DeallocPCrashReporterChild(PCrashReporterChild*) MOZ_OVERRIDE;
 
     virtual PHalChild* AllocPHalChild() MOZ_OVERRIDE;
     virtual bool DeallocPHalChild(PHalChild*) MOZ_OVERRIDE;
 
-    virtual PIndexedDBChild* AllocPIndexedDBChild();
-    virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor);
+    virtual PIndexedDBChild* AllocPIndexedDBChild() MOZ_OVERRIDE;
+    virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor) MOZ_OVERRIDE;
 
     virtual PMemoryReportRequestChild*
-    AllocPMemoryReportRequestChild(const uint32_t& generation);
+    AllocPMemoryReportRequestChild(const uint32_t& generation) MOZ_OVERRIDE;
 
     virtual bool
-    DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor);
+    DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) MOZ_OVERRIDE;
 
     virtual bool
     RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child,
-                                        const uint32_t& generation);
+                                        const uint32_t& generation) MOZ_OVERRIDE;
 
     virtual bool
-    RecvAudioChannelNotify();
+    RecvAudioChannelNotify() MOZ_OVERRIDE;
 
     virtual bool
     RecvDumpMemoryInfoToTempDir(const nsString& aIdentifier,
                                 const bool& aMinimizeMemoryUsage,
-                                const bool& aDumpChildProcesses);
+                                const bool& aDumpChildProcesses) MOZ_OVERRIDE;
     virtual bool
     RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
                               const bool& aDumpAllTraces,
-                              const bool& aDumpChildProcesses);
+                              const bool& aDumpChildProcesses) MOZ_OVERRIDE;
 
-    virtual PTestShellChild* AllocPTestShellChild();
-    virtual bool DeallocPTestShellChild(PTestShellChild*);
-    virtual bool RecvPTestShellConstructor(PTestShellChild*);
+    virtual PTestShellChild* AllocPTestShellChild() MOZ_OVERRIDE;
+    virtual bool DeallocPTestShellChild(PTestShellChild*) MOZ_OVERRIDE;
+    virtual bool RecvPTestShellConstructor(PTestShellChild*) MOZ_OVERRIDE;
     jsipc::JavaScriptChild *GetCPOWManager();
 
-    virtual PNeckoChild* AllocPNeckoChild();
-    virtual bool DeallocPNeckoChild(PNeckoChild*);
+    virtual PNeckoChild* AllocPNeckoChild() MOZ_OVERRIDE;
+    virtual bool DeallocPNeckoChild(PNeckoChild*) MOZ_OVERRIDE;
 
     virtual PExternalHelperAppChild *AllocPExternalHelperAppChild(
             const OptionalURIParams& uri,
             const nsCString& aMimeContentType,
             const nsCString& aContentDisposition,
             const bool& aForceSave,
             const int64_t& aContentLength,
             const OptionalURIParams& aReferrer,
-            PBrowserChild* aBrowser);
-    virtual bool DeallocPExternalHelperAppChild(PExternalHelperAppChild *aService);
+            PBrowserChild* aBrowser) MOZ_OVERRIDE;
+    virtual bool DeallocPExternalHelperAppChild(PExternalHelperAppChild *aService) MOZ_OVERRIDE;
 
-    virtual PSmsChild* AllocPSmsChild();
-    virtual bool DeallocPSmsChild(PSmsChild*);
+    virtual PSmsChild* AllocPSmsChild() MOZ_OVERRIDE;
+    virtual bool DeallocPSmsChild(PSmsChild*) MOZ_OVERRIDE;
 
-    virtual PTelephonyChild* AllocPTelephonyChild();
-    virtual bool DeallocPTelephonyChild(PTelephonyChild*);
+    virtual PTelephonyChild* AllocPTelephonyChild() MOZ_OVERRIDE;
+    virtual bool DeallocPTelephonyChild(PTelephonyChild*) MOZ_OVERRIDE;
 
-    virtual PStorageChild* AllocPStorageChild();
-    virtual bool DeallocPStorageChild(PStorageChild* aActor);
+    virtual PStorageChild* AllocPStorageChild() MOZ_OVERRIDE;
+    virtual bool DeallocPStorageChild(PStorageChild* aActor) MOZ_OVERRIDE;
 
-    virtual PBluetoothChild* AllocPBluetoothChild();
-    virtual bool DeallocPBluetoothChild(PBluetoothChild* aActor);
+    virtual PBluetoothChild* AllocPBluetoothChild() MOZ_OVERRIDE;
+    virtual bool DeallocPBluetoothChild(PBluetoothChild* aActor) MOZ_OVERRIDE;
 
-    virtual PFMRadioChild* AllocPFMRadioChild();
-    virtual bool DeallocPFMRadioChild(PFMRadioChild* aActor);
+    virtual PFMRadioChild* AllocPFMRadioChild() MOZ_OVERRIDE;
+    virtual bool DeallocPFMRadioChild(PFMRadioChild* aActor) MOZ_OVERRIDE;
 
     virtual PAsmJSCacheEntryChild* AllocPAsmJSCacheEntryChild(
                                  const asmjscache::OpenMode& aOpenMode,
                                  const asmjscache::WriteParams& aWriteParams,
                                  const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
     virtual bool DeallocPAsmJSCacheEntryChild(
                                     PAsmJSCacheEntryChild* aActor) MOZ_OVERRIDE;
 
-    virtual PSpeechSynthesisChild* AllocPSpeechSynthesisChild();
-    virtual bool DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor);
+    virtual PSpeechSynthesisChild* AllocPSpeechSynthesisChild() MOZ_OVERRIDE;
+    virtual bool DeallocPSpeechSynthesisChild(PSpeechSynthesisChild* aActor) MOZ_OVERRIDE;
 
     virtual bool RecvRegisterChrome(const InfallibleTArray<ChromePackage>& packages,
                                     const InfallibleTArray<ResourceMapping>& resources,
                                     const InfallibleTArray<OverrideMapping>& overrides,
-                                    const nsCString& locale);
+                                    const nsCString& locale) MOZ_OVERRIDE;
 
-    virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild();
-    virtual bool DeallocPJavaScriptChild(mozilla::jsipc::PJavaScriptChild*);
+    virtual mozilla::jsipc::PJavaScriptChild* AllocPJavaScriptChild() MOZ_OVERRIDE;
+    virtual bool DeallocPJavaScriptChild(mozilla::jsipc::PJavaScriptChild*) MOZ_OVERRIDE;
 
-    virtual bool RecvSetOffline(const bool& offline);
+    virtual bool RecvSetOffline(const bool& offline) MOZ_OVERRIDE;
 
-    virtual bool RecvSpeakerManagerNotify();
+    virtual bool RecvSpeakerManagerNotify() MOZ_OVERRIDE;
 
-    virtual bool RecvNotifyVisited(const URIParams& aURI);
+    virtual bool RecvNotifyVisited(const URIParams& aURI) MOZ_OVERRIDE;
     // auto remove when alertfinished is received.
     nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver);
 
-    virtual bool RecvPreferenceUpdate(const PrefSetting& aPref);
+    virtual bool RecvPreferenceUpdate(const PrefSetting& aPref) MOZ_OVERRIDE;
 
-    virtual bool RecvNotifyAlertsObserver(const nsCString& aType, const nsString& aData);
+    virtual bool RecvNotifyAlertsObserver(const nsCString& aType,
+                                          const nsString& aData) MOZ_OVERRIDE;
 
     virtual bool RecvAsyncMessage(const nsString& aMsg,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
-                                  const IPC::Principal& aPrincipal);
+                                  const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
-    virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere);
+    virtual bool RecvGeolocationUpdate(const GeoPosition& somewhere) MOZ_OVERRIDE;
 
-    virtual bool RecvAddPermission(const IPC::Permission& permission);
+    virtual bool RecvAddPermission(const IPC::Permission& permission) MOZ_OVERRIDE;
 
-    virtual bool RecvScreenSizeChanged(const gfxIntSize &size);
+    virtual bool RecvScreenSizeChanged(const gfxIntSize &size) MOZ_OVERRIDE;
 
-    virtual bool RecvFlushMemory(const nsString& reason);
+    virtual bool RecvFlushMemory(const nsString& reason) MOZ_OVERRIDE;
 
-    virtual bool RecvActivateA11y();
+    virtual bool RecvActivateA11y() MOZ_OVERRIDE;
 
-    virtual bool RecvGarbageCollect();
-    virtual bool RecvCycleCollect();
+    virtual bool RecvGarbageCollect() MOZ_OVERRIDE;
+    virtual bool RecvCycleCollect() MOZ_OVERRIDE;
 
     virtual bool RecvAppInfo(const nsCString& version, const nsCString& buildID,
-                             const nsCString& name, const nsCString& UAName);
+                             const nsCString& name, const nsCString& UAName) MOZ_OVERRIDE;
 
-    virtual bool RecvLastPrivateDocShellDestroyed();
+    virtual bool RecvLastPrivateDocShellDestroyed() MOZ_OVERRIDE;
 
     virtual bool RecvFilePathUpdate(const nsString& aStorageType,
                                     const nsString& aStorageName,
                                     const nsString& aPath,
-                                    const nsCString& aReason);
+                                    const nsCString& aReason) MOZ_OVERRIDE;
     virtual bool RecvFileSystemUpdate(const nsString& aFsName,
                                       const nsString& aVolumeName,
                                       const int32_t& aState,
                                       const int32_t& aMountGeneration,
                                       const bool& aIsMediaPresent,
                                       const bool& aIsSharing,
-                                      const bool& aIsFormatting);
+                                      const bool& aIsFormatting) MOZ_OVERRIDE;
 
     virtual bool RecvNuwaFork() MOZ_OVERRIDE;
 
-    virtual bool RecvNotifyProcessPriorityChanged(const hal::ProcessPriority& aPriority);
-    virtual bool RecvMinimizeMemoryUsage();
-    virtual bool RecvCancelMinimizeMemoryUsage();
+    virtual bool
+    RecvNotifyProcessPriorityChanged(const hal::ProcessPriority& aPriority) MOZ_OVERRIDE;
+    virtual bool RecvMinimizeMemoryUsage() MOZ_OVERRIDE;
+    virtual bool RecvCancelMinimizeMemoryUsage() MOZ_OVERRIDE;
 
-    virtual bool RecvLoadAndRegisterSheet(const URIParams& aURI, const uint32_t& aType);
-    virtual bool RecvUnregisterSheet(const URIParams& aURI, const uint32_t& aType);
+    virtual bool RecvLoadAndRegisterSheet(const URIParams& aURI,
+                                          const uint32_t& aType) MOZ_OVERRIDE;
+    virtual bool RecvUnregisterSheet(const URIParams& aURI, const uint32_t& aType) MOZ_OVERRIDE;
 
-    virtual bool RecvNotifyPhoneStateChange(const nsString& state);
+    virtual bool RecvNotifyPhoneStateChange(const nsString& state) MOZ_OVERRIDE;
 
     void AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS);
     void RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS);
     virtual bool RecvNotifyIdleObserver(const uint64_t& aObserver,
                                         const nsCString& aTopic,
-                                        const nsString& aData);
+                                        const nsString& aData) MOZ_OVERRIDE;
 #ifdef ANDROID
     gfxIntSize GetScreenSize() { return mScreenSize; }
 #endif
 
     // Get the directory for IndexedDB files. We query the parent for this and
     // cache the value
     nsString &GetIndexedDBPath();
 
@@ -259,17 +262,17 @@ public:
     bool IsForApp() { return mIsForApp; }
     bool IsForBrowser() { return mIsForBrowser; }
 
     BlobChild* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
 
 protected:
     virtual bool RecvPBrowserConstructor(PBrowserChild* actor,
                                          const IPCTabContext& context,
-                                         const uint32_t& chromeFlags);
+                                         const uint32_t& chromeFlags) MOZ_OVERRIDE;
 
 private:
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     virtual void ProcessingError(Result what) MOZ_OVERRIDE;
 
     /**
      * Exit *now*.  Do not shut down XPCOM, do not pass Go, do not run
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -184,17 +184,17 @@ public:
     virtual void OnChannelError() MOZ_OVERRIDE;
 
     virtual PIndexedDBParent* AllocPIndexedDBParent() MOZ_OVERRIDE;
     virtual bool
     RecvPIndexedDBConstructor(PIndexedDBParent* aActor) MOZ_OVERRIDE;
 
     virtual PCrashReporterParent*
     AllocPCrashReporterParent(const NativeThreadId& tid,
-                        const uint32_t& processType) MOZ_OVERRIDE;
+                              const uint32_t& processType) MOZ_OVERRIDE;
     virtual bool
     RecvPCrashReporterConstructor(PCrashReporterParent* actor,
                                   const NativeThreadId& tid,
                                   const uint32_t& processType) MOZ_OVERRIDE;
 
     virtual PNeckoParent* AllocPNeckoParent() MOZ_OVERRIDE;
     virtual bool RecvPNeckoConstructor(PNeckoParent* aActor) MOZ_OVERRIDE {
         return PContentParent::RecvPNeckoConstructor(aActor);
@@ -218,17 +218,17 @@ public:
     }
 
     virtual bool RecvRecordingDeviceEvents(const nsString& aRecordingStatus,
                                            const nsString& aPageURL,
                                            const bool& aIsAudio,
                                            const bool& aIsVideo) MOZ_OVERRIDE;
 protected:
     void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
-    virtual void ActorDestroy(ActorDestroyReason why);
+    virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
     void OnNuwaForkTimeout();
 
     bool ShouldContinueFromReplyTimeout() MOZ_OVERRIDE;
     bool ShouldSandboxContentProcesses();
 
 private:
     static nsDataHashtable<nsStringHashKey, ContentParent*> *sAppContentParents;
     static nsTArray<ContentParent*>* sNonAppContentParents;
@@ -326,209 +326,218 @@ private:
     AllocPImageBridgeParent(mozilla::ipc::Transport* aTransport,
                             base::ProcessId aOtherProcess) MOZ_OVERRIDE;
 
     virtual bool RecvGetProcessAttributes(uint64_t* aId,
                                           bool* aIsForApp,
                                           bool* aIsForBrowser) MOZ_OVERRIDE;
     virtual bool RecvGetXPCOMProcessAttributes(bool* aIsOffline) MOZ_OVERRIDE;
 
-    virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*);
+    virtual bool DeallocPJavaScriptParent(mozilla::jsipc::PJavaScriptParent*) MOZ_OVERRIDE;
 
     virtual PBrowserParent* AllocPBrowserParent(const IPCTabContext& aContext,
-                                                const uint32_t& aChromeFlags);
-    virtual bool DeallocPBrowserParent(PBrowserParent* frame);
+                                                const uint32_t& aChromeFlags) MOZ_OVERRIDE;
+    virtual bool DeallocPBrowserParent(PBrowserParent* frame) MOZ_OVERRIDE;
 
-    virtual PDeviceStorageRequestParent* AllocPDeviceStorageRequestParent(const DeviceStorageParams&);
-    virtual bool DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent*);
+    virtual PDeviceStorageRequestParent*
+    AllocPDeviceStorageRequestParent(const DeviceStorageParams&) MOZ_OVERRIDE;
+    virtual bool DeallocPDeviceStorageRequestParent(PDeviceStorageRequestParent*) MOZ_OVERRIDE;
 
-    virtual PBlobParent* AllocPBlobParent(const BlobConstructorParams& aParams);
-    virtual bool DeallocPBlobParent(PBlobParent*);
+    virtual PBlobParent* AllocPBlobParent(const BlobConstructorParams& aParams) MOZ_OVERRIDE;
+    virtual bool DeallocPBlobParent(PBlobParent*) MOZ_OVERRIDE;
 
-    virtual bool DeallocPCrashReporterParent(PCrashReporterParent* crashreporter);
+    virtual bool DeallocPCrashReporterParent(PCrashReporterParent* crashreporter) MOZ_OVERRIDE;
 
     virtual bool RecvGetRandomValues(const uint32_t& length,
-                                     InfallibleTArray<uint8_t>* randomValues);
+                                     InfallibleTArray<uint8_t>* randomValues) MOZ_OVERRIDE;
 
     virtual bool DeallocPHalParent(PHalParent*) MOZ_OVERRIDE;
 
-    virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor);
-
-    virtual PMemoryReportRequestParent* AllocPMemoryReportRequestParent(const uint32_t& generation);
-    virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor);
+    virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor) MOZ_OVERRIDE;
 
-    virtual PTestShellParent* AllocPTestShellParent();
-    virtual bool DeallocPTestShellParent(PTestShellParent* shell);
+    virtual PMemoryReportRequestParent*
+    AllocPMemoryReportRequestParent(const uint32_t& generation) MOZ_OVERRIDE;
+    virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) MOZ_OVERRIDE;
 
-    virtual bool DeallocPNeckoParent(PNeckoParent* necko);
+    virtual PTestShellParent* AllocPTestShellParent() MOZ_OVERRIDE;
+    virtual bool DeallocPTestShellParent(PTestShellParent* shell) MOZ_OVERRIDE;
+
+    virtual bool DeallocPNeckoParent(PNeckoParent* necko) MOZ_OVERRIDE;
 
     virtual PExternalHelperAppParent* AllocPExternalHelperAppParent(
             const OptionalURIParams& aUri,
             const nsCString& aMimeContentType,
             const nsCString& aContentDisposition,
             const bool& aForceSave,
             const int64_t& aContentLength,
             const OptionalURIParams& aReferrer,
-            PBrowserParent* aBrowser);
-    virtual bool DeallocPExternalHelperAppParent(PExternalHelperAppParent* aService);
+            PBrowserParent* aBrowser) MOZ_OVERRIDE;
+    virtual bool DeallocPExternalHelperAppParent(PExternalHelperAppParent* aService) MOZ_OVERRIDE;
 
-    virtual PSmsParent* AllocPSmsParent();
-    virtual bool DeallocPSmsParent(PSmsParent*);
+    virtual PSmsParent* AllocPSmsParent() MOZ_OVERRIDE;
+    virtual bool DeallocPSmsParent(PSmsParent*) MOZ_OVERRIDE;
 
-    virtual PTelephonyParent* AllocPTelephonyParent();
-    virtual bool DeallocPTelephonyParent(PTelephonyParent*);
+    virtual PTelephonyParent* AllocPTelephonyParent() MOZ_OVERRIDE;
+    virtual bool DeallocPTelephonyParent(PTelephonyParent*) MOZ_OVERRIDE;
 
-    virtual bool DeallocPStorageParent(PStorageParent* aActor);
+    virtual bool DeallocPStorageParent(PStorageParent* aActor) MOZ_OVERRIDE;
 
-    virtual PBluetoothParent* AllocPBluetoothParent();
-    virtual bool DeallocPBluetoothParent(PBluetoothParent* aActor);
-    virtual bool RecvPBluetoothConstructor(PBluetoothParent* aActor);
+    virtual PBluetoothParent* AllocPBluetoothParent() MOZ_OVERRIDE;
+    virtual bool DeallocPBluetoothParent(PBluetoothParent* aActor) MOZ_OVERRIDE;
+    virtual bool RecvPBluetoothConstructor(PBluetoothParent* aActor) MOZ_OVERRIDE;
 
-    virtual PFMRadioParent* AllocPFMRadioParent();
-    virtual bool DeallocPFMRadioParent(PFMRadioParent* aActor);
+    virtual PFMRadioParent* AllocPFMRadioParent() MOZ_OVERRIDE;
+    virtual bool DeallocPFMRadioParent(PFMRadioParent* aActor) MOZ_OVERRIDE;
 
     virtual PAsmJSCacheEntryParent* AllocPAsmJSCacheEntryParent(
                                  const asmjscache::OpenMode& aOpenMode,
                                  const asmjscache::WriteParams& aWriteParams,
                                  const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
     virtual bool DeallocPAsmJSCacheEntryParent(
                                    PAsmJSCacheEntryParent* aActor) MOZ_OVERRIDE;
 
-    virtual PSpeechSynthesisParent* AllocPSpeechSynthesisParent();
-    virtual bool DeallocPSpeechSynthesisParent(PSpeechSynthesisParent* aActor);
-    virtual bool RecvPSpeechSynthesisConstructor(PSpeechSynthesisParent* aActor);
+    virtual PSpeechSynthesisParent* AllocPSpeechSynthesisParent() MOZ_OVERRIDE;
+    virtual bool DeallocPSpeechSynthesisParent(PSpeechSynthesisParent* aActor) MOZ_OVERRIDE;
+    virtual bool RecvPSpeechSynthesisConstructor(PSpeechSynthesisParent* aActor) MOZ_OVERRIDE;
 
-    virtual bool RecvReadPrefsArray(InfallibleTArray<PrefSetting>* aPrefs);
-    virtual bool RecvReadFontList(InfallibleTArray<FontListEntry>* retValue);
+    virtual bool RecvReadPrefsArray(InfallibleTArray<PrefSetting>* aPrefs) MOZ_OVERRIDE;
+    virtual bool RecvReadFontList(InfallibleTArray<FontListEntry>* retValue) MOZ_OVERRIDE;
 
-    virtual bool RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions);
+    virtual bool RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions) MOZ_OVERRIDE;
 
-    virtual bool RecvSetClipboardText(const nsString& text, const bool& isPrivateData, const int32_t& whichClipboard);
-    virtual bool RecvGetClipboardText(const int32_t& whichClipboard, nsString* text);
-    virtual bool RecvEmptyClipboard();
-    virtual bool RecvClipboardHasText(bool* hasText);
+    virtual bool RecvSetClipboardText(const nsString& text,
+                                      const bool& isPrivateData,
+                                      const int32_t& whichClipboard) MOZ_OVERRIDE;
+    virtual bool RecvGetClipboardText(const int32_t& whichClipboard, nsString* text) MOZ_OVERRIDE;
+    virtual bool RecvEmptyClipboard() MOZ_OVERRIDE;
+    virtual bool RecvClipboardHasText(bool* hasText) MOZ_OVERRIDE;
 
-    virtual bool RecvGetSystemColors(const uint32_t& colorsCount, InfallibleTArray<uint32_t>* colors);
-    virtual bool RecvGetIconForExtension(const nsCString& aFileExt, const uint32_t& aIconSize, InfallibleTArray<uint8_t>* bits);
-    virtual bool RecvGetShowPasswordSetting(bool* showPassword);
+    virtual bool RecvGetSystemColors(const uint32_t& colorsCount,
+                                     InfallibleTArray<uint32_t>* colors) MOZ_OVERRIDE;
+    virtual bool RecvGetIconForExtension(const nsCString& aFileExt,
+                                         const uint32_t& aIconSize,
+                                         InfallibleTArray<uint8_t>* bits) MOZ_OVERRIDE;
+    virtual bool RecvGetShowPasswordSetting(bool* showPassword) MOZ_OVERRIDE;
 
-    virtual bool RecvStartVisitedQuery(const URIParams& uri);
+    virtual bool RecvStartVisitedQuery(const URIParams& uri) MOZ_OVERRIDE;
 
     virtual bool RecvVisitURI(const URIParams& uri,
                               const OptionalURIParams& referrer,
-                              const uint32_t& flags);
+                              const uint32_t& flags) MOZ_OVERRIDE;
 
     virtual bool RecvSetURITitle(const URIParams& uri,
-                                 const nsString& title);
+                                 const nsString& title) MOZ_OVERRIDE;
 
     virtual bool RecvShowFilePicker(const int16_t& mode,
                                     const int16_t& selectedType,
                                     const bool& addToRecentDocs,
                                     const nsString& title,
                                     const nsString& defaultFile,
                                     const nsString& defaultExtension,
                                     const InfallibleTArray<nsString>& filters,
                                     const InfallibleTArray<nsString>& filterNames,
                                     InfallibleTArray<nsString>* files,
                                     int16_t* retValue,
-                                    nsresult* result);
+                                    nsresult* result) MOZ_OVERRIDE;
 
     virtual bool RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle,
                                            const nsString& aText, const bool& aTextClickable,
                                            const nsString& aCookie, const nsString& aName,
                                            const nsString& aBidi, const nsString& aLang,
-                                           const IPC::Principal& aPrincipal);
+                                           const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
     virtual bool RecvCloseAlert(const nsString& aName,
-                                const IPC::Principal& aPrincipal);
+                                const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
-    virtual bool RecvLoadURIExternal(const URIParams& uri);
+    virtual bool RecvLoadURIExternal(const URIParams& uri) MOZ_OVERRIDE;
 
     virtual bool RecvSyncMessage(const nsString& aMsg,
                                  const ClonedMessageData& aData,
                                  const InfallibleTArray<CpowEntry>& aCpows,
                                  const IPC::Principal& aPrincipal,
-                                 InfallibleTArray<nsString>* aRetvals);
+                                 InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
     virtual bool AnswerRpcMessage(const nsString& aMsg,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
                                   const IPC::Principal& aPrincipal,
-                                  InfallibleTArray<nsString>* aRetvals);
+                                  InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
     virtual bool RecvAsyncMessage(const nsString& aMsg,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
-                                  const IPC::Principal& aPrincipal);
+                                  const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
     virtual bool RecvFilePathUpdateNotify(const nsString& aType,
                                           const nsString& aStorageName,
                                           const nsString& aFilePath,
-                                          const nsCString& aReason);
+                                          const nsCString& aReason) MOZ_OVERRIDE;
 
     virtual bool RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
-                                            const bool& aHighAccuracy);
-    virtual bool RecvRemoveGeolocationListener();
-    virtual bool RecvSetGeolocationHigherAccuracy(const bool& aEnable);
+                                            const bool& aHighAccuracy) MOZ_OVERRIDE;
+    virtual bool RecvRemoveGeolocationListener() MOZ_OVERRIDE;
+    virtual bool RecvSetGeolocationHigherAccuracy(const bool& aEnable) MOZ_OVERRIDE;
 
-    virtual bool RecvConsoleMessage(const nsString& aMessage);
+    virtual bool RecvConsoleMessage(const nsString& aMessage) MOZ_OVERRIDE;
     virtual bool RecvScriptError(const nsString& aMessage,
                                  const nsString& aSourceName,
                                  const nsString& aSourceLine,
                                  const uint32_t& aLineNumber,
                                  const uint32_t& aColNumber,
                                  const uint32_t& aFlags,
-                                 const nsCString& aCategory);
+                                 const nsCString& aCategory) MOZ_OVERRIDE;
 
-    virtual bool RecvPrivateDocShellsExist(const bool& aExist);
+    virtual bool RecvPrivateDocShellsExist(const bool& aExist) MOZ_OVERRIDE;
 
-    virtual bool RecvFirstIdle();
+    virtual bool RecvFirstIdle() MOZ_OVERRIDE;
 
     virtual bool RecvAudioChannelGetState(const AudioChannelType& aType,
                                           const bool& aElementHidden,
                                           const bool& aElementWasHidden,
-                                          AudioChannelState* aValue);
+                                          AudioChannelState* aValue) MOZ_OVERRIDE;
 
     virtual bool RecvAudioChannelRegisterType(const AudioChannelType& aType,
-                                              const bool& aWithVideo);
+                                              const bool& aWithVideo) MOZ_OVERRIDE;
     virtual bool RecvAudioChannelUnregisterType(const AudioChannelType& aType,
                                                 const bool& aElementHidden,
-                                                const bool& aWithVideo);
+                                                const bool& aWithVideo) MOZ_OVERRIDE;
 
-    virtual bool RecvAudioChannelChangedNotification();
+    virtual bool RecvAudioChannelChangedNotification() MOZ_OVERRIDE;
 
-    virtual bool RecvAudioChannelChangeDefVolChannel(
-      const AudioChannelType& aType, const bool& aHidden);
+    virtual bool RecvAudioChannelChangeDefVolChannel(const AudioChannelType& aType,
+                                                     const bool& aHidden) MOZ_OVERRIDE;
 
-    virtual bool RecvBroadcastVolume(const nsString& aVolumeName);
+    virtual bool RecvBroadcastVolume(const nsString& aVolumeName) MOZ_OVERRIDE;
 
-    virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue);
+    virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) MOZ_OVERRIDE;
 
-    virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable);
+    virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable) MOZ_OVERRIDE;
 
     virtual bool RecvSystemMessageHandled() MOZ_OVERRIDE;
 
     virtual bool RecvNuwaReady() MOZ_OVERRIDE;
 
     virtual bool RecvAddNewProcess(const uint32_t& aPid,
                                    const InfallibleTArray<ProtocolFdMapping>& aFds) MOZ_OVERRIDE;
 
     virtual bool RecvCreateFakeVolume(const nsString& fsName, const nsString& mountPoint) MOZ_OVERRIDE;
 
     virtual bool RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState) MOZ_OVERRIDE;
 
     virtual bool RecvKeywordToURI(const nsCString& aKeyword, OptionalInputStreamParams* aPostData,
-                                  OptionalURIParams* aURI);
+                                  OptionalURIParams* aURI) MOZ_OVERRIDE;
 
     virtual void ProcessingError(Result what) MOZ_OVERRIDE;
 
     virtual bool RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
                                               int32_t* aStatus,
-                                              bool* aSuccess);
+                                              bool* aSuccess) MOZ_OVERRIDE;
 
-    virtual bool RecvAddIdleObserver(const uint64_t& observerId, const uint32_t& aIdleTimeInS);
-    virtual bool RecvRemoveIdleObserver(const uint64_t& observerId, const uint32_t& aIdleTimeInS);
+    virtual bool RecvAddIdleObserver(const uint64_t& observerId,
+                                     const uint32_t& aIdleTimeInS) MOZ_OVERRIDE;
+    virtual bool RecvRemoveIdleObserver(const uint64_t& observerId,
+                                        const uint32_t& aIdleTimeInS) MOZ_OVERRIDE;
 
     // If you add strong pointers to cycle collected objects here, be sure to
     // release these objects in ShutDownProcess.  See the comment there for more
     // details.
 
     GeckoChildProcessHost* mSubprocess;
     base::ChildPrivileges mOSPrivileges;
 
--- a/dom/ipc/CrashReporterParent.h
+++ b/dom/ipc/CrashReporterParent.h
@@ -73,22 +73,22 @@ public:
     return mChildDumpID;
   }
 
   void
   AnnotateCrashReport(const nsCString& key, const nsCString& data);
 
  protected:
   virtual bool
-    RecvAnnotateCrashReport(const nsCString& key, const nsCString& data) {
+    RecvAnnotateCrashReport(const nsCString& key, const nsCString& data) MOZ_OVERRIDE {
     AnnotateCrashReport(key, data);
     return true;
   }
   virtual bool
-    RecvAppendAppNotes(const nsCString& data);
+    RecvAppendAppNotes(const nsCString& data) MOZ_OVERRIDE;
   virtual mozilla::ipc::IProtocol*
   CloneProtocol(Channel* aChannel,
                 mozilla::ipc::ProtocolCloneContext *aCtx) MOZ_OVERRIDE;
 
 #ifdef MOZ_CRASHREPORTER
   AnnotationTable mNotes;
 #endif
   nsCString mAppNotes;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -204,105 +204,112 @@ public:
                                        InfallibleTArray<nsString>* aJSONRetVal,
                                        bool aIsSync) MOZ_OVERRIDE;
     virtual bool DoSendAsyncMessage(JSContext* aCx,
                                     const nsAString& aMessage,
                                     const mozilla::dom::StructuredCloneData& aData,
                                     JS::Handle<JSObject *> aCpows,
                                     nsIPrincipal* aPrincipal) MOZ_OVERRIDE;
 
-    virtual bool RecvLoadURL(const nsCString& uri);
+    virtual bool RecvLoadURL(const nsCString& uri) MOZ_OVERRIDE;
     virtual bool RecvCacheFileDescriptor(const nsString& aPath,
                                          const FileDescriptor& aFileDescriptor)
                                          MOZ_OVERRIDE;
-    virtual bool RecvShow(const nsIntSize& size);
-    virtual bool RecvUpdateDimensions(const nsRect& rect, const nsIntSize& size, const ScreenOrientation& orientation);
-    virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
-    virtual bool RecvHandleDoubleTap(const CSSIntPoint& aPoint);
-    virtual bool RecvHandleSingleTap(const CSSIntPoint& aPoint);
-    virtual bool RecvHandleLongTap(const CSSIntPoint& aPoint);
-    virtual bool RecvHandleLongTapUp(const CSSIntPoint& aPoint);
-    virtual bool RecvNotifyTransformBegin(const ViewID& aViewId);
-    virtual bool RecvNotifyTransformEnd(const ViewID& aViewId);
-    virtual bool RecvActivate();
-    virtual bool RecvDeactivate();
+    virtual bool RecvShow(const nsIntSize& size) MOZ_OVERRIDE;
+    virtual bool RecvUpdateDimensions(const nsRect& rect,
+                                      const nsIntSize& size,
+                                      const ScreenOrientation& orientation) MOZ_OVERRIDE;
+    virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE;
+    virtual bool RecvHandleDoubleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
+    virtual bool RecvHandleSingleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
+    virtual bool RecvHandleLongTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
+    virtual bool RecvHandleLongTapUp(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
+    virtual bool RecvNotifyTransformBegin(const ViewID& aViewId) MOZ_OVERRIDE;
+    virtual bool RecvNotifyTransformEnd(const ViewID& aViewId) MOZ_OVERRIDE;
+    virtual bool RecvActivate() MOZ_OVERRIDE;
+    virtual bool RecvDeactivate() MOZ_OVERRIDE;
     virtual bool RecvMouseEvent(const nsString& aType,
                                 const float&    aX,
                                 const float&    aY,
                                 const int32_t&  aButton,
                                 const int32_t&  aClickCount,
                                 const int32_t&  aModifiers,
-                                const bool&     aIgnoreRootScrollFrame);
-    virtual bool RecvRealMouseEvent(const mozilla::WidgetMouseEvent& event);
-    virtual bool RecvRealKeyEvent(const mozilla::WidgetKeyboardEvent& event);
-    virtual bool RecvMouseWheelEvent(const mozilla::WidgetWheelEvent& event);
+                                const bool&     aIgnoreRootScrollFrame) MOZ_OVERRIDE;
+    virtual bool RecvRealMouseEvent(const mozilla::WidgetMouseEvent& event) MOZ_OVERRIDE;
+    virtual bool RecvRealKeyEvent(const mozilla::WidgetKeyboardEvent& event) MOZ_OVERRIDE;
+    virtual bool RecvMouseWheelEvent(const mozilla::WidgetWheelEvent& event) MOZ_OVERRIDE;
     virtual bool RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
-                                    const ScrollableLayerGuid& aGuid);
+                                    const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
     virtual bool RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent,
-                                        const ScrollableLayerGuid& aGuid);
+                                        const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE;
     virtual bool RecvKeyEvent(const nsString& aType,
                               const int32_t&  aKeyCode,
                               const int32_t&  aCharCode,
                               const int32_t&  aModifiers,
-                              const bool&     aPreventDefault);
-    virtual bool RecvCompositionEvent(const mozilla::WidgetCompositionEvent& event);
-    virtual bool RecvTextEvent(const mozilla::WidgetTextEvent& event);
-    virtual bool RecvSelectionEvent(const mozilla::WidgetSelectionEvent& event);
-    virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& capture);
-    virtual bool RecvLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope);
+                              const bool&     aPreventDefault) MOZ_OVERRIDE;
+    virtual bool RecvCompositionEvent(const mozilla::WidgetCompositionEvent& event) MOZ_OVERRIDE;
+    virtual bool RecvTextEvent(const mozilla::WidgetTextEvent& event) MOZ_OVERRIDE;
+    virtual bool RecvSelectionEvent(const mozilla::WidgetSelectionEvent& event) MOZ_OVERRIDE;
+    virtual bool RecvActivateFrameEvent(const nsString& aType, const bool& capture) MOZ_OVERRIDE;
+    virtual bool RecvLoadRemoteScript(const nsString& aURL,
+                                      const bool& aRunInGlobalScope) MOZ_OVERRIDE;
     virtual bool RecvAsyncMessage(const nsString& aMessage,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
                                   const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
     virtual PDocumentRendererChild*
     AllocPDocumentRendererChild(const nsRect& documentRect, const gfx::Matrix& transform,
                                 const nsString& bgcolor,
                                 const uint32_t& renderFlags, const bool& flushLayout,
-                                const nsIntSize& renderSize);
-    virtual bool DeallocPDocumentRendererChild(PDocumentRendererChild* actor);
+                                const nsIntSize& renderSize) MOZ_OVERRIDE;
+    virtual bool DeallocPDocumentRendererChild(PDocumentRendererChild* actor) MOZ_OVERRIDE;
     virtual bool RecvPDocumentRendererConstructor(PDocumentRendererChild* actor,
                                                   const nsRect& documentRect,
                                                   const gfx::Matrix& transform,
                                                   const nsString& bgcolor,
                                                   const uint32_t& renderFlags,
                                                   const bool& flushLayout,
-                                                  const nsIntSize& renderSize);
+                                                  const nsIntSize& renderSize) MOZ_OVERRIDE;
 
     virtual PContentDialogChild* AllocPContentDialogChild(const uint32_t&,
                                                           const nsCString&,
                                                           const nsCString&,
                                                           const InfallibleTArray<int>&,
-                                                          const InfallibleTArray<nsString>&);
-    virtual bool DeallocPContentDialogChild(PContentDialogChild* aDialog);
+                                                          const InfallibleTArray<nsString>&)
+                                                          MOZ_OVERRIDE;
+    virtual bool DeallocPContentDialogChild(PContentDialogChild* aDialog) MOZ_OVERRIDE;
     static void ParamsToArrays(nsIDialogParamBlock* aParams,
                                InfallibleTArray<int>& aIntParams,
                                InfallibleTArray<nsString>& aStringParams);
     static void ArraysToParams(const InfallibleTArray<int>& aIntParams,
                                const InfallibleTArray<nsString>& aStringParams,
                                nsIDialogParamBlock* aParams);
 
 #ifdef DEBUG
     virtual PContentPermissionRequestChild*
     SendPContentPermissionRequestConstructor(PContentPermissionRequestChild* aActor,
                                              const nsCString& aType,
                                              const nsCString& aAccess,
                                              const IPC::Principal& aPrincipal);
 #endif /* DEBUG */
 
-    virtual PContentPermissionRequestChild* AllocPContentPermissionRequestChild(const nsCString& aType,
-                                                                                const nsCString& aAccess,
-                                                                                const IPC::Principal& aPrincipal);
-    virtual bool DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor);
+    virtual PContentPermissionRequestChild*
+    AllocPContentPermissionRequestChild(const nsCString& aType,
+                                        const nsCString& aAccess,
+                                        const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
+    virtual bool
+    DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) MOZ_OVERRIDE;
 
     virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdateChild(
             const URIParams& manifestURI,
             const URIParams& documentURI,
-            const bool& stickDocument);
-    virtual bool DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* offlineCacheUpdate);
+            const bool& stickDocument) MOZ_OVERRIDE;
+    virtual bool
+    DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* offlineCacheUpdate) MOZ_OVERRIDE;
 
     nsIWebNavigation* WebNavigation() { return mWebNav; }
 
     nsIPrincipal* GetPrincipal() { return mPrincipal; }
 
     /** Return the DPI of the widget this TabChild draws to. */
     void GetDPI(float* aDPI);
     void GetDefaultScale(double *aScale);
@@ -371,19 +378,19 @@ protected:
     virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) MOZ_OVERRIDE;
     virtual bool RecvDestroy() MOZ_OVERRIDE;
     virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) MOZ_OVERRIDE;
 
     nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& event);
 
     virtual PIndexedDBChild* AllocPIndexedDBChild(const nsCString& aGroup,
                                                   const nsCString& aASCIIOrigin,
-                                                  bool* /* aAllowed */);
+                                                  bool* /* aAllowed */) MOZ_OVERRIDE;
 
-    virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor);
+    virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor) MOZ_OVERRIDE;
 
 private:
     /**
      * Create a new TabChild object.
      *
      * |aOwnOrContainingAppId| is the app-id of our frame or of the closest app
      * frame in the hierarchy which contains us.
      *
@@ -397,17 +404,17 @@ private:
     // sets the appropriate app-id and is-browser flags on our docshell.)
     //
     // You should call this after calling TabContext::SetTabContext().  We also
     // call this during Init().
     void NotifyTabContextUpdated();
 
     bool UseDirectCompositor();
 
-    void ActorDestroy(ActorDestroyReason why);
+    void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     enum FrameScriptLoading { DONT_LOAD_SCRIPTS, DEFAULT_LOAD_SCRIPTS };
     bool InitTabChildGlobal(FrameScriptLoading aScriptLoading = DEFAULT_LOAD_SCRIPTS);
     bool InitRenderingState();
     void DestroyWindow();
     void SetProcessNameToAppName();
     bool ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
 
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -105,91 +105,92 @@ public:
      *
      * It's an error to call TryCapture() if this isn't the event
      * capturer.
      */
     bool TryCapture(const WidgetGUIEvent& aEvent);
 
     void Destroy();
 
-    virtual bool RecvMoveFocus(const bool& aForward);
-    virtual bool RecvEvent(const RemoteDOMEvent& aEvent);
-    virtual bool RecvPRenderFrameConstructor(PRenderFrameParent* actor);
+    virtual bool RecvMoveFocus(const bool& aForward) MOZ_OVERRIDE;
+    virtual bool RecvEvent(const RemoteDOMEvent& aEvent) MOZ_OVERRIDE;
+    virtual bool RecvPRenderFrameConstructor(PRenderFrameParent* actor) MOZ_OVERRIDE;
     virtual bool RecvInitRenderFrame(PRenderFrameParent* aFrame,
                                      ScrollingBehavior* scrolling,
                                      TextureFactoryIdentifier* identifier,
                                      uint64_t* layersId,
-                                     bool *aSuccess);
+                                     bool *aSuccess) MOZ_OVERRIDE;
     virtual bool RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
                                             const nsString& aURL,
                                             const nsString& aName,
                                             const nsString& aFeatures,
-                                            bool* aOutWindowOpened);
-    virtual bool AnswerCreateWindow(PBrowserParent** retval);
+                                            bool* aOutWindowOpened) MOZ_OVERRIDE;
+    virtual bool AnswerCreateWindow(PBrowserParent** retval) MOZ_OVERRIDE;
     virtual bool RecvSyncMessage(const nsString& aMessage,
                                  const ClonedMessageData& aData,
                                  const InfallibleTArray<CpowEntry>& aCpows,
                                  const IPC::Principal& aPrincipal,
-                                 InfallibleTArray<nsString>* aJSONRetVal);
+                                 InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
     virtual bool AnswerRpcMessage(const nsString& aMessage,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
                                   const IPC::Principal& aPrincipal,
-                                  InfallibleTArray<nsString>* aJSONRetVal);
+                                  InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
     virtual bool RecvAsyncMessage(const nsString& aMessage,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
-                                  const IPC::Principal& aPrincipal);
+                                  const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMEFocus(const bool& aFocus,
                                     nsIMEUpdatePreference* aPreference,
-                                    uint32_t* aSeqno);
+                                    uint32_t* aSeqno) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMETextChange(const uint32_t& aStart,
                                          const uint32_t& aEnd,
-                                         const uint32_t& aNewEnd);
+                                         const uint32_t& aNewEnd) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMESelectedCompositionRect(const uint32_t& aOffset,
                                                       const nsIntRect& aRect,
                                                       const nsIntRect& aCaretRect) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMESelection(const uint32_t& aSeqno,
                                         const uint32_t& aAnchor,
-                                        const uint32_t& aFocus);
-    virtual bool RecvNotifyIMETextHint(const nsString& aText);
+                                        const uint32_t& aFocus) MOZ_OVERRIDE;
+    virtual bool RecvNotifyIMETextHint(const nsString& aText) MOZ_OVERRIDE;
     virtual bool RecvEndIMEComposition(const bool& aCancel,
-                                       nsString* aComposition);
+                                       nsString* aComposition) MOZ_OVERRIDE;
     virtual bool RecvGetInputContext(int32_t* aIMEEnabled,
                                      int32_t* aIMEOpen,
-                                     intptr_t* aNativeIMEContext);
+                                     intptr_t* aNativeIMEContext) MOZ_OVERRIDE;
     virtual bool RecvSetInputContext(const int32_t& aIMEEnabled,
                                      const int32_t& aIMEOpen,
                                      const nsString& aType,
                                      const nsString& aInputmode,
                                      const nsString& aActionHint,
                                      const int32_t& aCause,
-                                     const int32_t& aFocusChange);
-    virtual bool RecvRequestFocus(const bool& aCanRaise);
-    virtual bool RecvSetCursor(const uint32_t& aValue);
-    virtual bool RecvSetBackgroundColor(const nscolor& aValue);
-    virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus);
-    virtual bool RecvGetDPI(float* aValue);
-    virtual bool RecvGetDefaultScale(double* aValue);
-    virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue);
+                                     const int32_t& aFocusChange) MOZ_OVERRIDE;
+    virtual bool RecvRequestFocus(const bool& aCanRaise) MOZ_OVERRIDE;
+    virtual bool RecvSetCursor(const uint32_t& aValue) MOZ_OVERRIDE;
+    virtual bool RecvSetBackgroundColor(const nscolor& aValue) MOZ_OVERRIDE;
+    virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus) MOZ_OVERRIDE;
+    virtual bool RecvGetDPI(float* aValue) MOZ_OVERRIDE;
+    virtual bool RecvGetDefaultScale(double* aValue) MOZ_OVERRIDE;
+    virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) MOZ_OVERRIDE;
     virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
                                 const ViewID& aViewId,
-                                const CSSRect& aRect);
+                                const CSSRect& aRect) MOZ_OVERRIDE;
     virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
                                            const ViewID& aViewId,
                                            const bool& aIsRoot,
-                                           const ZoomConstraints& aConstraints);
+                                           const ZoomConstraints& aConstraints) MOZ_OVERRIDE;
     virtual bool RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
-                                          const bool& aPreventDefault);
-    virtual PContentDialogParent* AllocPContentDialogParent(const uint32_t& aType,
-                                                            const nsCString& aName,
-                                                            const nsCString& aFeatures,
-                                                            const InfallibleTArray<int>& aIntParams,
-                                                            const InfallibleTArray<nsString>& aStringParams);
-    virtual bool DeallocPContentDialogParent(PContentDialogParent* aDialog)
+                                          const bool& aPreventDefault) MOZ_OVERRIDE;
+    virtual PContentDialogParent*
+    AllocPContentDialogParent(const uint32_t& aType,
+                              const nsCString& aName,
+                              const nsCString& aFeatures,
+                              const InfallibleTArray<int>& aIntParams,
+                              const InfallibleTArray<nsString>& aStringParams) MOZ_OVERRIDE;
+    virtual bool DeallocPContentDialogParent(PContentDialogParent* aDialog) MOZ_OVERRIDE
     {
       delete aDialog;
       return true;
     }
 
 
     void LoadURL(nsIURI* aURI);
     // XXX/cjones: it's not clear what we gain by hiding these
@@ -222,40 +223,44 @@ public:
     bool SendRealKeyEvent(mozilla::WidgetKeyboardEvent& event);
     bool SendRealTouchEvent(WidgetTouchEvent& event);
     bool SendHandleSingleTap(const CSSIntPoint& aPoint);
     bool SendHandleLongTap(const CSSIntPoint& aPoint);
     bool SendHandleLongTapUp(const CSSIntPoint& aPoint);
     bool SendHandleDoubleTap(const CSSIntPoint& aPoint);
 
     virtual PDocumentRendererParent*
-    AllocPDocumentRendererParent(const nsRect& documentRect, const gfx::Matrix& transform,
+    AllocPDocumentRendererParent(const nsRect& documentRect,
+                                 const gfx::Matrix& transform,
                                  const nsString& bgcolor,
-                                 const uint32_t& renderFlags, const bool& flushLayout,
-                                 const nsIntSize& renderSize);
-    virtual bool DeallocPDocumentRendererParent(PDocumentRendererParent* actor);
+                                 const uint32_t& renderFlags,
+                                 const bool& flushLayout,
+                                 const nsIntSize& renderSize) MOZ_OVERRIDE;
+    virtual bool DeallocPDocumentRendererParent(PDocumentRendererParent* actor) MOZ_OVERRIDE;
 
     virtual PContentPermissionRequestParent*
-    AllocPContentPermissionRequestParent(const nsCString& aType, const nsCString& aAccess, const IPC::Principal& aPrincipal);
-    virtual bool DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor);
+    AllocPContentPermissionRequestParent(const nsCString& aType,
+                                         const nsCString& aAccess,
+                                         const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
+    virtual bool
+    DeallocPContentPermissionRequestParent(PContentPermissionRequestParent* actor) MOZ_OVERRIDE;
 
     virtual POfflineCacheUpdateParent*
     AllocPOfflineCacheUpdateParent(const URIParams& aManifestURI,
                                    const URIParams& aDocumentURI,
                                    const bool& aStickDocument) MOZ_OVERRIDE;
     virtual bool
     RecvPOfflineCacheUpdateConstructor(POfflineCacheUpdateParent* aActor,
                                        const URIParams& aManifestURI,
                                        const URIParams& aDocumentURI,
                                        const bool& stickDocument) MOZ_OVERRIDE;
     virtual bool
-    DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor)
-                                     MOZ_OVERRIDE;
+    DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor) MOZ_OVERRIDE;
 
-    virtual bool RecvSetOfflinePermission(const IPC::Principal& principal);
+    virtual bool RecvSetOfflinePermission(const IPC::Principal& principal) MOZ_OVERRIDE;
 
     bool GetGlobalJSObject(JSContext* cx, JSObject** globalp);
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIAUTHPROMPTPROVIDER
     NS_DECL_NSISECUREBROWSERUI
 
     void HandleDelayedDialogs();
@@ -287,25 +292,25 @@ protected:
 
     virtual bool Recv__delete__() MOZ_OVERRIDE;
 
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
     virtual PIndexedDBParent* AllocPIndexedDBParent(
                                                   const nsCString& aGroup,
                                                   const nsCString& aASCIIOrigin,
-                                                  bool* /* aAllowed */);
+                                                  bool* /* aAllowed */) MOZ_OVERRIDE;
 
-    virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor);
+    virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor) MOZ_OVERRIDE;
 
     virtual bool
     RecvPIndexedDBConstructor(PIndexedDBParent* aActor,
                               const nsCString& aGroup,
                               const nsCString& aASCIIOrigin,
-                              bool* aAllowed);
+                              bool* aAllowed) MOZ_OVERRIDE;
 
     Element* mFrameElement;
     nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
 
     struct DelayedDialogData
     {
       DelayedDialogData(PContentDialogParent* aDialog, uint32_t aType,
                         const nsCString& aName,
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -100,17 +100,17 @@ static nsresult CompareDictionaries(JSCo
     JS::Rooted<JS::Value> bprop(aCx);
     if (!JS_GetPropertyById(aCx, b, props[i], &bprop)) {
       LOG(("Error parsing dictionary!\n"));
       return NS_ERROR_UNEXPECTED;
     }
     if (bprop.isUndefined()) {
       // Unknown property found in A. Bail with name
       JS::Rooted<JS::Value> nameval(aCx);
-      bool success = JS_IdToValue(aCx, props[i], nameval.address());
+      bool success = JS_IdToValue(aCx, props[i], &nameval);
       NS_ENSURE_TRUE(success, NS_ERROR_UNEXPECTED);
 
       JS::Rooted<JSString*> namestr(aCx, JS::ToString(aCx, nameval));
       NS_ENSURE_TRUE(namestr, NS_ERROR_UNEXPECTED);
       aDifference->Assign(JS_GetStringCharsZ(aCx, namestr));
       return NS_OK;
     }
   }
--- a/dom/plugins/base/PluginPRLibrary.cpp
+++ b/dom/plugins/base/PluginPRLibrary.cpp
@@ -33,18 +33,16 @@ using namespace mozilla::layers;
 
 namespace mozilla {
 #ifdef MOZ_WIDGET_ANDROID
 nsresult
 PluginPRLibrary::NP_Initialize(NPNetscapeFuncs* bFuncs,
 			       NPPluginFuncs* pFuncs, NPError* error)
 {
   JNIEnv* env = GetJNIForThread();
-  if (!env)
-    return NS_ERROR_FAILURE;
 
   mozilla::AutoLocalJNIFrame jniFrame(env);
 
   if (mNP_Initialize) {
     *error = mNP_Initialize(bFuncs, pFuncs, env);
   } else {
     NP_InitializeFunc pfNP_Initialize = (NP_InitializeFunc)
       PR_FindFunctionSymbol(mLibrary, "NP_Initialize");
--- a/dom/plugins/base/android/ANPAudio.cpp
+++ b/dom/plugins/base/android/ANPAudio.cpp
@@ -120,18 +120,16 @@ public:
 };
 
 NS_IMETHODIMP
 AudioRunnable::Run()
 {
   PR_SetCurrentThreadName("Android Audio");
 
   JNIEnv* jenv = GetJNIForThread();
-  if (!jenv)
-    return NS_ERROR_FAILURE;
 
   mozilla::AutoLocalJNIFrame autoFrame(jenv, 2);
 
   jbyteArray bytearray = jenv->NewByteArray(mTrack->bufferSize);
   if (!bytearray) {
     LOG("AudioRunnable:: Run.  Could not create bytearray");
     return NS_ERROR_FAILURE;
   }
@@ -205,18 +203,16 @@ anp_audio_newTrack(uint32_t sampleRate, 
                    void* user)
 {
   ANPAudioTrack *s = new ANPAudioTrack();
   if (s == nullptr) {
     return nullptr;
   }
 
   JNIEnv *jenv = GetJNIForThread();
-  if (!jenv)
-    return nullptr;
 
   s->at_class = init_jni_bindings(jenv);
   s->rate = sampleRate;
   s->channels = channelCount;
   s->bufferSize = s->rate * s->channels;
   s->isStopped = true;
   s->keepGoing = false;
   s->user = user;
@@ -303,18 +299,16 @@ anp_audio_start(ANPAudioTrack* s)
   }
 
   if (s->keepGoing) {
     // we are already playing.  Ignore.
     return;
   }
 
   JNIEnv *jenv = GetJNIForThread();
-  if (!jenv)
-    return;
 
   mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
   jenv->CallVoidMethod(s->output_unit, at.play);
 
   if (autoFrame.CheckForException()) {
     jenv->DeleteGlobalRef(s->at_class);
     free(s);
     return;
@@ -333,34 +327,30 @@ anp_audio_start(ANPAudioTrack* s)
 void
 anp_audio_pause(ANPAudioTrack* s)
 {
   if (s == nullptr || s->output_unit == nullptr) {
     return;
   }
 
   JNIEnv *jenv = GetJNIForThread();
-  if (!jenv)
-    return;
 
   mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
   jenv->CallVoidMethod(s->output_unit, at.pause);
 }
 
 void
 anp_audio_stop(ANPAudioTrack* s)
 {
   if (s == nullptr || s->output_unit == nullptr) {
     return;
   }
 
   s->isStopped = true;
   JNIEnv *jenv = GetJNIForThread();
-  if (!jenv)
-    return;
 
   mozilla::AutoLocalJNIFrame autoFrame(jenv, 0);
   jenv->CallVoidMethod(s->output_unit, at.stop);
 }
 
 bool
 anp_audio_isStopped(ANPAudioTrack* s)
 {
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -894,17 +894,17 @@ nsJSObjWrapper::NP_Enumerate(NPObject *n
   *idarray = (NPIdentifier *)PR_Malloc(*count * sizeof(NPIdentifier));
   if (!*idarray) {
     ThrowJSException(cx, "Memory allocation failed for NPIdentifier!");
     return false;
   }
 
   for (uint32_t i = 0; i < *count; i++) {
     JS::Rooted<JS::Value> v(cx);
-    if (!JS_IdToValue(cx, ida[i], v.address())) {
+    if (!JS_IdToValue(cx, ida[i], &v)) {
       PR_Free(*idarray);
       return false;
     }
 
     NPIdentifier id;
     if (v.isString()) {
       JS::Rooted<JSString*> str(cx, v.toString());
       str = JS_InternJSString(cx, str);
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1564,20 +1564,20 @@ void nsPluginInstanceOwner::ExitFullScre
   // This will cause Paint() to be called, which is where
   // we normally add/update views and layers
   Invalidate();
 }
 
 void nsPluginInstanceOwner::ExitFullScreen(jobject view) {
   JNIEnv* env = AndroidBridge::GetJNIEnv();
 
-  if (env && sFullScreenInstance && sFullScreenInstance->mInstance &&
+  if (sFullScreenInstance && sFullScreenInstance->mInstance &&
       env->IsSameObject(view, (jobject)sFullScreenInstance->mInstance->GetJavaSurface())) {
     sFullScreenInstance->ExitFullScreen();
-  } 
+  }
 }
 
 #endif
 
 nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
 {
 #ifdef MOZ_WIDGET_ANDROID
   if (mInstance) {
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -638,18 +638,19 @@ PluginInstanceParent::RecvShow(const NPR
         surface->MarkDirty(ur);
 
         ImageContainer *container = GetImageContainer();
         ImageFormat format = CAIRO_SURFACE;
         nsRefPtr<Image> image = container->CreateImage(&format, 1);
         NS_ASSERTION(image->GetFormat() == CAIRO_SURFACE, "Wrong format?");
         CairoImage* cairoImage = static_cast<CairoImage*>(image.get());
         CairoImage::Data cairoData;
-        cairoData.mSurface = surface;
+        cairoData.mDeprecatedSurface = surface;
         cairoData.mSize = surface->GetSize().ToIntSize();
+        cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface);
         cairoImage->SetData(cairoData);
 
         container->SetCurrentImage(cairoImage);
     }
     else if (mImageContainer) {
         mImageContainer->SetCurrentImage(nullptr);
     }
 
--- a/dom/tests/mochitest/localstorage/test_localStorageEnablePref.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageEnablePref.html
@@ -11,16 +11,19 @@ function checkException(func, exc)
 {
   var exceptionThrew = false;
   try {
     func();
   }
   catch (ex) {
     exceptionThrew = true;
     is(ex.name, exc, "Expected "+exc+" exception");
+    if (ex.name != exc) {
+      ok(true, "The exception which was thrown is: " + ex);
+    }
   }
   ok(exceptionThrew, "Exception "+exc+" threw");
 }
 
 var storage;
 function test1() {
   is(typeof(window.localStorage), "object", "Storage is present");
   storage = window.localStorage;
--- a/dom/xbl/nsXBLProtoImplField.cpp
+++ b/dom/xbl/nsXBLProtoImplField.cpp
@@ -185,17 +185,17 @@ InstallXBLField(JSContext* cx,
 
     JS::Rooted<JSObject*> xblProto(cx);
     xblProto = &js::GetFunctionNativeReserved(callee, XBLPROTO_SLOT).toObject();
 
     JS::Rooted<JS::Value> name(cx, js::GetFunctionNativeReserved(callee, FIELD_SLOT));
     JSFlatString* fieldStr = JS_ASSERT_STRING_IS_FLAT(name.toString());
     fieldName.init(fieldStr);
 
-    MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp.address()));
+    MOZ_ALWAYS_TRUE(JS_ValueToId(cx, name, idp));
 
     // If a separate XBL scope is being used, the callee is not same-compartment
     // with the xbl prototype, and the object is a cross-compartment wrapper.
     xblProto = js::UncheckedUnwrap(xblProto);
     JSAutoCompartment ac2(cx, xblProto);
     JS::Value slotVal = ::JS_GetReservedSlot(xblProto, 0);
     protoBinding = static_cast<nsXBLPrototypeBinding*>(slotVal.toPrivate());
     MOZ_ASSERT(protoBinding);
--- a/dom/xbl/nsXBLProtoImplMethod.cpp
+++ b/dom/xbl/nsXBLProtoImplMethod.cpp
@@ -315,17 +315,18 @@ nsXBLProtoImplAnonymousMethod::Execute(n
 
   JSAutoCompartment ac(cx, scopeObject);
   if (!JS_WrapObject(cx, &thisObject))
       return NS_ERROR_OUT_OF_MEMORY;
 
   // Clone the function object, using thisObject as the parent so "this" is in
   // the scope chain of the resulting function (for backwards compat to the
   // days when this was an event handler).
-  JS::Rooted<JSObject*> method(cx, ::JS_CloneFunctionObject(cx, GetCompiledMethod(), thisObject));
+  JS::Rooted<JSObject*> jsMethodObject(cx, GetCompiledMethod());
+  JS::Rooted<JSObject*> method(cx, ::JS_CloneFunctionObject(cx, jsMethodObject, thisObject));
   if (!method)
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Now call the method
 
   // Check whether script is enabled.
   bool scriptAllowed = nsContentUtils::GetSecurityManager()->
                          ScriptAllowed(js::GetGlobalForObjectCrossCompartment(method));
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -307,17 +307,18 @@ nsXBLPrototypeHandler::ExecuteHandler(Ev
   // scope if one doesn't already exist, and potentially wraps it cross-
   // compartment into our scope (via aAllowWrapping=true).
   JS::Rooted<JS::Value> targetV(cx, JS::UndefinedValue());
   rv = nsContentUtils::WrapNative(cx, scopeObject, scriptTarget, &targetV,
                                   /* aAllowWrapping = */ true);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Next, clone the generic handler to be parented to the target.
-  JS::Rooted<JSObject*> bound(cx, JS_CloneFunctionObject(cx, genericHandler, &targetV.toObject()));
+  JS::Rooted<JSObject*> target(cx, &targetV.toObject());
+  JS::Rooted<JSObject*> bound(cx, JS_CloneFunctionObject(cx, genericHandler, target));
   NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
 
   // Now, wrap the bound handler into the content compartment and use it.
   JSAutoCompartment ac2(cx, globalObject);
   if (!JS_WrapObject(cx, &bound)) {
     return NS_ERROR_FAILURE;
   }
 
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -361,16 +361,19 @@ GLContextEGL::MakeCurrentImpl(bool aForc
 
     // Assume that EGL has the same problem as WGL does,
     // where MakeCurrent with an already-current context is
     // still expensive.
     if (aForce || sEGLLibrary.fGetCurrentContext() != mContext) {
         EGLSurface surface = mSurfaceOverride != EGL_NO_SURFACE
                               ? mSurfaceOverride
                               : mSurface;
+        if (surface == EGL_NO_SURFACE) {
+            return false;
+        }
         succeeded = sEGLLibrary.fMakeCurrent(EGL_DISPLAY(),
                                               surface, surface,
                                               mContext);
         int eglError = sEGLLibrary.fGetError();
         if (!succeeded) {
             if (eglError == LOCAL_EGL_CONTEXT_LOST) {
                 mContextLost = true;
                 NS_WARNING("EGL context has been lost.");
@@ -409,17 +412,17 @@ GLContextEGL::RenewSurface() {
         return false;
     }
     return MakeCurrent(true);
 }
 
 void
 GLContextEGL::ReleaseSurface() {
     DestroySurface(mSurface);
-    mSurface = nullptr;
+    mSurface = EGL_NO_SURFACE;
 }
 
 bool
 GLContextEGL::SetupLookupFunction()
 {
     mLookupFunc = (PlatformLookupFunction)sEGLLibrary.mSymbols.fGetProcAddress;
     return true;
 }
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -670,10 +670,27 @@ RemoteBitmapImage::DeprecatedGetAsSurfac
     memcpy(newSurf->Data() + newSurf->Stride() * y,
            mData + mStride * y,
            mSize.width * 4);
   }
 
   return newSurf.forget();
 }
 
+TemporaryRef<gfx::SourceSurface>
+RemoteBitmapImage::GetAsSourceSurface()
+{
+  gfx::SurfaceFormat fmt = mFormat == RemoteImageData::BGRX32
+                         ? gfx::SurfaceFormat::B8G8R8X8
+                         : gfx::SurfaceFormat::B8G8R8A8;
+  RefPtr<gfx::DataSourceSurface> newSurf = gfx::Factory::CreateDataSourceSurface(mSize, fmt);
+
+  for (int y = 0; y < mSize.height; y++) {
+    memcpy(newSurf->GetData() + newSurf->Stride() * y,
+           mData + mStride * y,
+           mSize.width * 4);
+  }
+
+  return newSurf;
+}
+
 } // namespace
 } // namespace
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -36,16 +36,19 @@
  * or released off the main thread. We can ensure that we never AddRef
  * a gfxASurface off the main thread, but we might want to Release due
  * to an Image being destroyed off the main thread.
  *
  * We use nsCountedRef<nsMainThreadSurfaceRef> to reference the
  * gfxASurface. When AddRefing, we assert that we're on the main thread.
  * When Releasing, if we're not on the main thread, we post an event to
  * the main thread to do the actual release.
+ *
+ * This should be removed after after Image::DeprecatedGetAsSurface is
+ * removed. It is replaced by nsMainThreadSourceSurfaceRef
  */
 class nsMainThreadSurfaceRef;
 
 template <>
 class nsAutoRefTraits<nsMainThreadSurfaceRef> {
 public:
   typedef gfxASurface* RawRef;
 
@@ -75,16 +78,59 @@ public:
   static void AddRef(RawRef aRawRef)
   {
     NS_ASSERTION(NS_IsMainThread(),
                  "Can only add a reference on the main thread");
     aRawRef->AddRef();
   }
 };
 
+/**
+ * Same purpose as nsMainThreadSurfaceRef byt holds a gfx::SourceSurface instead.
+ * The specialization of nsMainThreadSurfaceRef should be removed after
+ * Image::DeprecatedGetAsSurface is removed
+ */
+class nsMainThreadSourceSurfaceRef;
+
+template <>
+class nsAutoRefTraits<nsMainThreadSourceSurfaceRef> {
+public:
+  typedef mozilla::gfx::SourceSurface* RawRef;
+
+  /**
+   * The XPCOM event that will do the actual release on the main thread.
+   */
+  class SurfaceReleaser : public nsRunnable {
+  public:
+    SurfaceReleaser(RawRef aRef) : mRef(aRef) {}
+    NS_IMETHOD Run() {
+      mRef->Release();
+      return NS_OK;
+    }
+    RawRef mRef;
+  };
+
+  static RawRef Void() { return nullptr; }
+  static void Release(RawRef aRawRef)
+  {
+    if (NS_IsMainThread()) {
+      aRawRef->Release();
+      return;
+    }
+    nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
+    NS_DispatchToMainThread(runnable);
+  }
+  static void AddRef(RawRef aRawRef)
+  {
+    NS_ASSERTION(NS_IsMainThread(),
+                 "Can only add a reference on the main thread");
+    aRawRef->AddRef();
+  }
+};
+
 #endif
 
 #ifdef XP_WIN
 struct ID3D10Texture2D;
 struct ID3D10Device;
 struct ID3D10ShaderResourceView;
 #endif
 
@@ -872,51 +918,67 @@ protected:
 /**
  * Currently, the data in a CairoImage surface is treated as being in the
  * device output color space. This class is very simple as all backends
  * have to know about how to deal with drawing a cairo image.
  */
 class CairoImage : public Image {
 public:
   struct Data {
-    gfxASurface* mSurface;
+    gfxASurface* mDeprecatedSurface;
     gfx::IntSize mSize;
+
+    // mSourceSurface wraps mDeprrecatedSurface's data, therefore it should not
+    // outlive mDeprecatedSurface
+    RefPtr<gfx::SourceSurface> mSourceSurface;
   };
 
   /**
    * This can only be called on the main thread. It may add a reference
    * to the surface (which will eventually be released on the main thread).
    * The surface must not be modified after this call!!!
    */
   void SetData(const Data& aData)
   {
-    mSurface = aData.mSurface;
+    mDeprecatedSurface = aData.mDeprecatedSurface;
     mSize = aData.mSize;
+    mSourceSurface = aData.mSourceSurface;
   }
 
+  virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface()
+  {
+    return mSourceSurface.get();
+  }
 
   virtual already_AddRefed<gfxASurface> DeprecatedGetAsSurface()
   {
-    nsRefPtr<gfxASurface> surface = mSurface.get();
+    nsRefPtr<gfxASurface> surface = mDeprecatedSurface.get();
     return surface.forget();
   }
 
   gfx::IntSize GetSize() { return mSize; }
 
   CairoImage() : Image(nullptr, CAIRO_SURFACE) {}
 
-  nsCountedRef<nsMainThreadSurfaceRef> mSurface;
+private:
+
+  nsCountedRef<nsMainThreadSurfaceRef> mDeprecatedSurface;
   gfx::IntSize mSize;
+
+  // mSourceSurface wraps mDeprrecatedSurface's data, therefore it should not
+  // outlive mDeprecatedSurface
+  nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface;
 };
 
 class RemoteBitmapImage : public Image {
 public:
   RemoteBitmapImage() : Image(nullptr, REMOTE_IMAGE_BITMAP) {}
 
   already_AddRefed<gfxASurface> DeprecatedGetAsSurface();
+  TemporaryRef<gfx::SourceSurface> GetAsSourceSurface();
 
   gfx::IntSize GetSize() { return mSize; }
 
   unsigned char *mData;
   int mStride;
   gfx::IntSize mSize;
   RemoteImageData::Format mFormat;
 };
--- a/gfx/layers/composite/APZCTreeManager.cpp
+++ b/gfx/layers/composite/APZCTreeManager.cpp
@@ -198,17 +198,27 @@ APZCTreeManager::UpdatePanZoomController
           apzc->SetPrevSibling(nullptr);
           apzc->SetLastChild(nullptr);
         }
         APZC_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer, aLayersId, container->GetFrameMetrics().mScrollId);
 
         apzc->NotifyLayersUpdated(container->GetFrameMetrics(),
                                   aIsFirstPaint && (aLayersId == aFirstPaintLayersId));
 
+        // Use the composition bounds as the hit test region.
+        // Optionally, the GeckoContentController can provide a touch-sensitive
+        // region that constrains all frames associated with the controller.
+        // In this case we intersect the composition bounds with that region.
         ScreenRect visible(container->GetFrameMetrics().mCompositionBounds);
+        CSSRect touchSensitiveRegion;
+        if (state->mController->GetTouchSensitiveRegion(&touchSensitiveRegion)) {
+          visible = visible.Intersect(touchSensitiveRegion
+                                      * container->GetFrameMetrics().LayersPixelsPerCSSPixel()
+                                      * LayerToScreenScale(1.0));
+        }
         apzc->SetLayerHitTestData(visible, aTransform, aLayer->GetTransform());
         APZC_LOG("Setting rect(%f %f %f %f) as visible region for APZC %p\n", visible.x, visible.y,
                                                                               visible.width, visible.height,
                                                                               apzc);
 
         // Bind the APZC instance into the tree of APZCs
         if (aNextSibling) {
           aNextSibling->SetPrevSibling(apzc);
--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp
@@ -122,31 +122,32 @@ ImageLayerD3D10::GetImageSRView(Image* a
 
     remoteImage->GetD3D10TextureBackendData(device());
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
   } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(aImage);
 
-    if (!cairoImage->mSurface) {
+    nsRefPtr<gfxASurface> surf = cairoImage->DeprecatedGetAsSurface();
+    if (!surf) {
       return nullptr;
     }
 
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
       nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData());
-      dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
+      dat->mTexture = SurfaceToTexture(device(), surf, cairoImage->GetSize());
 
       if (dat->mTexture) {
         device()->CreateShaderResourceView(dat->mTexture, nullptr, getter_AddRefs(dat->mSRView));
         aImage->SetBackendData(mozilla::layers::LAYERS_D3D10, dat.forget());
       }
     }
 
-    aHasAlpha = cairoImage->mSurface->GetContentType() == GFX_CONTENT_COLOR_ALPHA;
+    aHasAlpha = surf->GetContentType() == GFX_CONTENT_COLOR_ALPHA;
   } else if (aImage->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) {
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
       // Use resource sharing to open the D3D9 texture as a D3D10 texture,
       HRESULT hr;
       D3D9SurfaceImage* d3dImage = reinterpret_cast<D3D9SurfaceImage*>(aImage);
       nsRefPtr<ID3D10Texture2D> texture;
       hr = device()->OpenSharedResource(d3dImage->GetShareHandle(),
                                         IID_ID3D10Texture2D,
@@ -207,24 +208,24 @@ ImageLayerD3D10::RenderLayer()
   }
 
   IntSize size = image->GetSize();
 
   SetEffectTransformAndOpacity();
 
   ID3D10EffectTechnique *technique;
   nsRefPtr<IDXGIKeyedMutex> keyedMutex;
+  nsRefPtr<gfxASurface> surf = image->DeprecatedGetAsSurface();
 
   if (image->GetFormat() == ImageFormat::CAIRO_SURFACE ||
       image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP ||
       image->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE ||
       image->GetFormat() == ImageFormat::D3D9_RGB32_TEXTURE) {
     NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE ||
-                 !static_cast<CairoImage*>(image)->mSurface ||
-                 static_cast<CairoImage*>(image)->mSurface->GetContentType() != GFX_CONTENT_ALPHA,
+                 !surf || surf->GetContentType() != GFX_CONTENT_ALPHA,
                  "Image layer has alpha image");
     bool hasAlpha = false;
 
     nsRefPtr<ID3D10ShaderResourceView> srView = GetImageSRView(image, hasAlpha, getter_AddRefs(keyedMutex));
     if (!srView) {
       return;
     }
 
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -339,29 +339,30 @@ ImageLayerD3D9::GetTexture(Image *aImage
       }
     }
 
     aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
   } else if (aImage->GetFormat() == CAIRO_SURFACE) {
     CairoImage *cairoImage =
       static_cast<CairoImage*>(aImage);
 
-    if (!cairoImage->mSurface) {
+    nsRefPtr<gfxASurface> surf = cairoImage->DeprecatedGetAsSurface();
+    if (!surf) {
       return nullptr;
     }
 
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
       nsAutoPtr<TextureD3D9BackendData> dat(new TextureD3D9BackendData());
-      dat->mTexture = SurfaceToTexture(device(), cairoImage->mSurface, cairoImage->mSize);
+      dat->mTexture = SurfaceToTexture(device(), surf, cairoImage->GetSize());
       if (dat->mTexture) {
         aImage->SetBackendData(mozilla::layers::LAYERS_D3D9, dat.forget());
       }
     }
 
-    aHasAlpha = cairoImage->mSurface->GetContentType() == GFX_CONTENT_COLOR_ALPHA;
+    aHasAlpha = surf->GetContentType() == GFX_CONTENT_COLOR_ALPHA;
   } else if (aImage->GetFormat() == D3D9_RGB32_TEXTURE) {
     if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
       // The texture in which the frame is stored belongs to DXVA's D3D9 device.
       // We need to open it on our device before we can use it.
       nsAutoPtr<TextureD3D9BackendData> backendData(new TextureD3D9BackendData());
       D3D9SurfaceImage* image = static_cast<D3D9SurfaceImage*>(aImage);
       backendData->mTexture = OpenSharedTexture(image->GetDesc(), image->GetShareHandle(), device());
       if (backendData->mTexture) {
@@ -408,19 +409,19 @@ ImageLayerD3D9::RenderLayer()
   SetShaderTransformAndOpacity();
 
   gfx::IntSize size = image->GetSize();
 
   if (image->GetFormat() == CAIRO_SURFACE ||
       image->GetFormat() == REMOTE_IMAGE_BITMAP ||
       image->GetFormat() == D3D9_RGB32_TEXTURE)
   {
+    nsRefPtr<gfxASurface> surf = image->DeprecatedGetAsSurface();
     NS_ASSERTION(image->GetFormat() != CAIRO_SURFACE ||
-                 !static_cast<CairoImage*>(image)->mSurface ||
-                 static_cast<CairoImage*>(image)->mSurface->GetContentType() != GFX_CONTENT_ALPHA,
+                 !surf || surf->GetContentType() != GFX_CONTENT_ALPHA,
                  "Image layer has alpha image");
 
     bool hasAlpha = false;
     nsRefPtr<IDirect3DTexture9> texture = GetTexture(image, hasAlpha);
 
     device()->SetVertexShaderConstantF(CBvLayerQuad,
                                        ShaderConstantRect(0,
                                                           0,
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -1565,16 +1565,17 @@ void AsyncPanZoomController::NotifyLayer
     // determined by Gecko and our copy in mFrameMetrics may be stale.
     mFrameMetrics.mScrollableRect = aLayerMetrics.mScrollableRect;
     mFrameMetrics.mCompositionBounds = aLayerMetrics.mCompositionBounds;
     float parentResolutionChange = aLayerMetrics.GetParentResolution().scale
                                  / mFrameMetrics.GetParentResolution().scale;
     mFrameMetrics.mZoom.scale *= parentResolutionChange;
     mFrameMetrics.mResolution = aLayerMetrics.mResolution;
     mFrameMetrics.mCumulativeResolution = aLayerMetrics.mCumulativeResolution;
+    mFrameMetrics.mHasScrollgrab = aLayerMetrics.mHasScrollgrab;
 
     // If the layers update was not triggered by our own repaint request, then
     // we want to take the new scroll offset.
     if (aLayerMetrics.mUpdateScrollOffset) {
       APZC_LOG("Updating scroll offset from (%f, %f) to (%f, %f)\n",
         mFrameMetrics.mScrollOffset.x, mFrameMetrics.mScrollOffset.y,
         aLayerMetrics.mScrollOffset.x, aLayerMetrics.mScrollOffset.y);
 
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -81,17 +81,17 @@ public:
                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
 
   virtual bool RecvWillStop() MOZ_OVERRIDE;
   virtual bool RecvStop() MOZ_OVERRIDE;
   virtual bool RecvPause() MOZ_OVERRIDE;
   virtual bool RecvResume() MOZ_OVERRIDE;
   virtual bool RecvNotifyChildCreated(const uint64_t& child) MOZ_OVERRIDE;
   virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
-                                SurfaceDescriptor* aOutSnapshot);
+                                SurfaceDescriptor* aOutSnapshot) MOZ_OVERRIDE;
   virtual bool RecvFlushRendering() MOZ_OVERRIDE;
   virtual bool RecvForceComposite() MOZ_OVERRIDE;
 
   virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) MOZ_OVERRIDE;
   virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) MOZ_OVERRIDE;
   virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) MOZ_OVERRIDE;
 
   virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
@@ -234,18 +234,18 @@ public:
    * Returns true if the calling thread is the compositor thread.
    */
   static bool IsInCompositorThread();
 protected:
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
                                  const uint64_t& aId,
                                  TextureFactoryIdentifier* aTextureFactoryIdentifier,
-                                 bool* aSuccess);
-  virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers);
+                                 bool* aSuccess) MOZ_OVERRIDE;
+  virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE;
   virtual void ScheduleTask(CancelableTask*, int);
   void Composite();
   void CompositeInTransaction();
   virtual void ComposeToTarget(gfx::DrawTarget* aTarget);
 
   void SetEGLSurfaceSize(int width, int height);
 
 private:
--- a/gfx/layers/ipc/GeckoContentController.h
+++ b/gfx/layers/ipc/GeckoContentController.h
@@ -77,16 +77,32 @@ public:
    * last known zoom constraints.
    */
   virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
   {
     return false;
   }
 
   /**
+   * APZ uses |FrameMetrics::mCompositionBounds| for hit testing. Sometimes,
+   * widget code has knowledge of a touch-sensitive region that should
+   * additionally constrain hit testing for all frames associated with the
+   * controller. This method allows APZ to query the controller for such a
+   * region. A return value of true indicates that the controller has such a
+   * region, and it is returned in |aOutRegion|.
+   * TODO: once bug 928833 is implemented, this should be removed, as
+   * APZ can then get the correct touch-sensitive region for each frame
+   * directly from the layer.
+   */
+  virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion)
+  {
+    return false;
+  }
+
+  /**
    * General tranformation notices for consumers. These fire any time
    * the apzc is modifying the view, including panning, zooming, and
    * fling.
    */
   virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid) {}
   virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid) {}
 
   GeckoContentController() {}
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -50,18 +50,18 @@ public:
   virtual PGrallocBufferParent*
   AllocPGrallocBufferParent(const IntSize&, const uint32_t&, const uint32_t&,
                             MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE;
 
   virtual bool
   DeallocPGrallocBufferParent(PGrallocBufferParent* actor) MOZ_OVERRIDE;
 
   // PImageBridge
-  virtual bool RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply);
-  virtual bool RecvUpdateNoSwap(const EditArray& aEdits);
+  virtual bool RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply) MOZ_OVERRIDE;
+  virtual bool RecvUpdateNoSwap(const EditArray& aEdits) MOZ_OVERRIDE;
 
   virtual bool IsAsync() const MOZ_OVERRIDE { return true; }
 
   PCompositableParent* AllocPCompositableParent(const TextureInfo& aInfo,
                                                 uint64_t*) MOZ_OVERRIDE;
   bool DeallocPCompositableParent(PCompositableParent* aActor) MOZ_OVERRIDE;
 
   virtual PTextureParent* AllocPTextureParent() MOZ_OVERRIDE;
--- a/gfx/layers/ipc/SharedRGBImage.cpp
+++ b/gfx/layers/ipc/SharedRGBImage.cpp
@@ -235,11 +235,17 @@ SharedRGBImage::GetTextureClient()
 }
 
 already_AddRefed<gfxASurface>
 SharedRGBImage::DeprecatedGetAsSurface()
 {
   return nullptr;
 }
 
+TemporaryRef<gfx::SourceSurface>
+SharedRGBImage::GetAsSourceSurface()
+{
+  return nullptr;
+}
+
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/SharedRGBImage.h
+++ b/gfx/layers/ipc/SharedRGBImage.h
@@ -114,16 +114,18 @@ public:
   virtual uint8_t* GetBuffer() MOZ_OVERRIDE;
 
   gfx::IntSize GetSize();
 
   size_t GetBufferSize();
 
   already_AddRefed<gfxASurface> DeprecatedGetAsSurface();
 
+  TemporaryRef<gfx::SourceSurface> GetAsSourceSurface();
+
   bool Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
 private:
   gfx::IntSize mSize;
   RefPtr<ImageClient> mCompositable;
   RefPtr<BufferTextureClient> mTextureClient;
 };
 
 } // namespace layers
--- a/gfx/thebes/nsSurfaceTexture.cpp
+++ b/gfx/thebes/nsSurfaceTexture.cpp
@@ -22,25 +22,22 @@ static int sNextID = 0;
 
 static class JNIFunctions {
 public:
 
   JNIFunctions() : mInitialized(false)
   {
   }
 
-  
   bool EnsureInitialized()
   {
     if (mInitialized)
       return true;
 
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return false;
 
     AutoLocalJNIFrame jniFrame(env);
 
     jSurfaceTextureClass = (jclass)env->NewGlobalRef(env->FindClass("android/graphics/SurfaceTexture"));
     jSurfaceTexture_Ctor = env->GetMethodID(jSurfaceTextureClass, "<init>", "(I)V");
     jSurfaceTexture_updateTexImage = env->GetMethodID(jSurfaceTextureClass, "updateTexImage", "()V");
     jSurfaceTexture_getTransformMatrix = env->GetMethodID(jSurfaceTextureClass, "getTransformMatrix", "([F)V");
 
@@ -49,48 +46,40 @@ public:
   }
 
   jobject CreateSurfaceTexture(GLuint aTexture)
   {
     if (!EnsureInitialized())
       return nullptr;
 
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return nullptr;
 
     AutoLocalJNIFrame jniFrame(env);
 
     return env->NewGlobalRef(env->NewObject(jSurfaceTextureClass, jSurfaceTexture_Ctor, (int) aTexture));
   }
 
   void ReleaseSurfaceTexture(jobject aSurfaceTexture)
   {
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return;
 
     env->DeleteGlobalRef(aSurfaceTexture);
   }
 
   void UpdateTexImage(jobject aSurfaceTexture)
   {
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return;
 
     AutoLocalJNIFrame jniFrame(env);
     env->CallObjectMethod(aSurfaceTexture, jSurfaceTexture_updateTexImage);
   }
 
   bool GetTransformMatrix(jobject aSurfaceTexture, gfx3DMatrix& aMatrix)
   {
     JNIEnv* env = GetJNIForThread();
-    if (!env)
-      return false;
 
     AutoLocalJNIFrame jniFrame(env);
 
     jfloatArray jarray = env->NewFloatArray(16);
     env->CallVoidMethod(aSurfaceTexture, jSurfaceTexture_getTransformMatrix, jarray);
 
     jfloat* array = env->GetFloatArrayElements(jarray, nullptr);
 
@@ -167,18 +156,16 @@ nsSurfaceTexture::Check()
 
 bool
 nsSurfaceTexture::Init(GLuint aTexture)
 {
   if (!sJNIFunctions.EnsureInitialized())
     return false;
 
   JNIEnv* env = GetJNIForThread();
-  if (!env)
-    return false;
 
   mSurfaceTexture = sJNIFunctions.CreateSurfaceTexture(aTexture);
   if (!mSurfaceTexture)
     return false;
 
   mNativeWindow = AndroidBridge::Bridge()->AcquireNativeWindowFromSurfaceTexture(env, mSurfaceTexture);
 
   mID = ++sNextID;
@@ -199,20 +186,18 @@ nsSurfaceTexture::~nsSurfaceTexture()
   mFrameAvailableCallback = nullptr;
 
   if (mNativeWindow) {
     AndroidBridge::Bridge()->ReleaseNativeWindowForSurfaceTexture(mSurfaceTexture);
     mNativeWindow = nullptr;
   }
 
   JNIEnv* env = GetJNIForThread();
-  if (!env)
-    return;
 
-  if (mSurfaceTexture && env) {
+  if (mSurfaceTexture) {
     GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
 
     env->DeleteGlobalRef(mSurfaceTexture);
     mSurfaceTexture = nullptr;
   }
 }
 
 void*
@@ -254,9 +239,9 @@ nsSurfaceTexture::NotifyFrameAvailable()
       nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &nsSurfaceTexture::NotifyFrameAvailable);
       NS_DispatchToCurrentThread(event);
     } else {
       mFrameAvailableCallback->Run();
     }
   }
 }
 
-#endif // MOZ_WIDGET_ANDROID
\ No newline at end of file
+#endif // MOZ_WIDGET_ANDROID
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -948,19 +948,20 @@ RasterImage::GetCurrentImage()
   nsRefPtr<gfxASurface> imageSurface = GetFrame(FRAME_CURRENT, FLAG_NONE);
   NS_ENSURE_TRUE(imageSurface, nullptr);
 
   if (!mImageContainer) {
     mImageContainer = LayerManager::CreateImageContainer();
   }
 
   CairoImage::Data cairoData;
-  cairoData.mSurface = imageSurface;
+  cairoData.mDeprecatedSurface = imageSurface;
   GetWidth(&cairoData.mSize.width);
   GetHeight(&cairoData.mSize.height);
+  cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, imageSurface);
 
   ImageFormat cairoFormat = CAIRO_SURFACE;
   nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&cairoFormat, 1);
   NS_ASSERTION(image, "Failed to create Image");
 
   NS_ASSERTION(image->GetFormat() == cairoFormat, "Wrong format");
   static_cast<CairoImage*>(image.get())->SetData(cairoData);
 
@@ -2921,17 +2922,17 @@ RasterImage::RequestDecodeIfNeeded(nsres
                                    eShutdownIntent aIntent,
                                    bool aDone,
                                    bool aWasSize)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // If we were a size decode and a full decode was requested, now's the time.
   if (NS_SUCCEEDED(aStatus) &&
-      aIntent != eShutdownIntent_Error &&
+      aIntent == eShutdownIntent_Done &&
       aDone &&
       aWasSize &&
       mWantFullDecode) {
     mWantFullDecode = false;
 
     // If we're not meant to be storing source data and we just got the size,
     // we need to synchronously flush all the data we got to a full decoder.
     // When that decoder is shut down, we'll also clear our source data.
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -100,17 +100,19 @@ MessagePump::Run(MessagePump::Delegate* 
     // here.  To ensure that MessageLoop tasks and XPCOM events have
     // equal priority, we sensitively rely on processing exactly one
     // Task per DoWorkRunnable XPCOM event.
 
 #ifdef MOZ_WIDGET_ANDROID
     // This processes messages in the Android Looper. Note that we only
     // get here if the normal Gecko event loop has been awoken above.
     // Bug 750713
-    did_work |= GeckoAppShell::PumpMessageLoop();
+    if (MOZ_LIKELY(AndroidBridge::HasEnv())) {
+        did_work |= GeckoAppShell::PumpMessageLoop();
+    }
 #endif
 
     did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
 
 if (did_work && delayed_work_time_.is_null()
 #ifdef MOZ_NUWA_PROCESS
     && (!IsNuwaReady() || !IsNuwaProcess())
 #endif
--- a/js/ipc/JavaScriptChild.h
+++ b/js/ipc/JavaScriptChild.h
@@ -20,59 +20,59 @@ class JavaScriptChild
 {
   public:
     JavaScriptChild(JSRuntime *rt);
     ~JavaScriptChild();
 
     bool init();
     void trace(JSTracer *trc);
 
-    bool RecvDropObject(const ObjectId &objId);
+    bool RecvDropObject(const ObjectId &objId) MOZ_OVERRIDE;
 
-    bool AnswerPreventExtensions(const ObjectId &objId, ReturnStatus *rs);
+    bool AnswerPreventExtensions(const ObjectId &objId, ReturnStatus *rs) MOZ_OVERRIDE;
     bool AnswerGetPropertyDescriptor(const ObjectId &objId, const nsString &id,
                                      const uint32_t &flags, ReturnStatus *rs,
-                                     PPropertyDescriptor *out);
+                                     PPropertyDescriptor *out) MOZ_OVERRIDE;
     bool AnswerGetOwnPropertyDescriptor(const ObjectId &objId,
                                         const nsString &id,
                                         const uint32_t &flags,
                                         ReturnStatus *rs,
-                                        PPropertyDescriptor *out);
+                                        PPropertyDescriptor *out) MOZ_OVERRIDE;
     bool AnswerDefineProperty(const ObjectId &objId, const nsString &id,
                               const PPropertyDescriptor &flags,
-                              ReturnStatus *rs);
+                              ReturnStatus *rs) MOZ_OVERRIDE;
     bool AnswerDelete(const ObjectId &objId, const nsString &id,
-                      ReturnStatus *rs, bool *success);
+                      ReturnStatus *rs, bool *success) MOZ_OVERRIDE;
 
     bool AnswerHas(const ObjectId &objId, const nsString &id,
-                       ReturnStatus *rs, bool *bp);
+                       ReturnStatus *rs, bool *bp) MOZ_OVERRIDE;
     bool AnswerHasOwn(const ObjectId &objId, const nsString &id,
-                          ReturnStatus *rs, bool *bp);
+                          ReturnStatus *rs, bool *bp) MOZ_OVERRIDE;
     bool AnswerGet(const ObjectId &objId, const ObjectId &receiverId,
                        const nsString &id,
-                       ReturnStatus *rs, JSVariant *result);
+                       ReturnStatus *rs, JSVariant *result) MOZ_OVERRIDE;
     bool AnswerSet(const ObjectId &objId, const ObjectId &receiverId,
                    const nsString &id, const bool &strict,
-                   const JSVariant &value, ReturnStatus *rs, JSVariant *result);
+                   const JSVariant &value, ReturnStatus *rs, JSVariant *result) MOZ_OVERRIDE;
 
     bool AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs,
-                            bool *result);
+                            bool *result) MOZ_OVERRIDE;
     bool AnswerCall(const ObjectId &objId, const nsTArray<JSParam> &argv,
                     ReturnStatus *rs, JSVariant *result,
-                    nsTArray<JSParam> *outparams);
+                    nsTArray<JSParam> *outparams) MOZ_OVERRIDE;
     bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
-                             bool *result);
-    bool AnswerClassName(const ObjectId &objId, nsString *result);
+                             bool *result) MOZ_OVERRIDE;
+    bool AnswerClassName(const ObjectId &objId, nsString *result) MOZ_OVERRIDE;
 
     bool AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
-                                ReturnStatus *rs, nsTArray<nsString> *names);
+                                ReturnStatus *rs, nsTArray<nsString> *names) MOZ_OVERRIDE;
     bool AnswerInstanceOf(const ObjectId &objId, const JSIID &iid,
-                          ReturnStatus *rs, bool *instanceof);
+                          ReturnStatus *rs, bool *instanceof) MOZ_OVERRIDE;
     bool AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
-                             ReturnStatus *rs, bool *instanceof);
+                             ReturnStatus *rs, bool *instanceof) MOZ_OVERRIDE;
 
   protected:
     JSObject *unwrap(JSContext *cx, ObjectId id);
 
   private:
     bool makeId(JSContext *cx, JSObject *obj, ObjectId *idp);
     bool fail(JSContext *cx, ReturnStatus *rs);
     bool ok(ReturnStatus *rs);
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -132,17 +132,17 @@ JavaScriptShared::init()
         return false;
     return true;
 }
 
 bool
 JavaScriptShared::convertIdToGeckoString(JSContext *cx, JS::HandleId id, nsString *to)
 {
     RootedValue idval(cx);
-    if (!JS_IdToValue(cx, id, idval.address()))
+    if (!JS_IdToValue(cx, id, &idval))
         return false;
 
     RootedString str(cx, ToString(cx, idval));
     if (!str)
         return false;
 
     const jschar *chars = JS_GetStringCharsZ(cx, str);
     if (!chars)
@@ -154,17 +154,17 @@ JavaScriptShared::convertIdToGeckoString
 
 bool
 JavaScriptShared::convertGeckoStringToId(JSContext *cx, const nsString &from, JS::MutableHandleId to)
 {
     RootedString str(cx, JS_NewUCStringCopyN(cx, from.BeginReading(), from.Length()));
     if (!str)
         return false;
 
-    return JS_ValueToId(cx, StringValue(str), to.address());
+    return JS_ValueToId(cx, StringValue(str), to);
 }
 
 bool
 JavaScriptShared::toVariant(JSContext *cx, JS::HandleValue from, JSVariant *to)
 {
     switch (JS_TypeOfValue(cx, from)) {
       case JSTYPE_VOID:
         *to = void_t();
--- a/js/jsd/jsd_val.cpp
+++ b/js/jsd/jsd_val.cpp
@@ -497,17 +497,17 @@ jsd_GetValueProperty(JSDContext* jsdc, J
             if (JS_CompareStrings(cx, propName, name, &result) && !result)
                 return jsdprop;
         }
         JSD_DropProperty(jsdc, jsdprop);
     }
     /* Not found in property list, look it up explicitly */
 
     nameval = STRING_TO_JSVAL(name);
-    if(!JS_ValueToId(cx, nameval, nameid.address()))
+    if(!JS_ValueToId(cx, nameval, &nameid))
         return nullptr;
 
     if(!(obj = JSVAL_TO_OBJECT(jsdval->val)))
         return nullptr;
 
     JS::Rooted<JSPropertyDescriptor> desc(cx);
     {
         JSAutoCompartment ac(cx, obj);
@@ -539,17 +539,17 @@ jsd_GetValueProperty(JSDContext* jsdc, J
             }
         }
         else
         {
             propValue = val;
         }
     }
 
-    if (!JS_IdToValue(cx, nameid, propId.address()))
+    if (!JS_IdToValue(cx, nameid, &propId))
         return nullptr;
 
     propAlias = JSVAL_NULL;
     propFlags |= desc.isEnumerable() ? JSPD_ENUMERATE : 0
         | desc.isReadonly() ? JSPD_READONLY  : 0
         | desc.isPermanent() ? JSPD_PERMANENT : 0;
 
     return _newProperty(jsdc, propId, propValue, propAlias, propFlags, JSDPD_HINTED);
--- a/js/public/OldDebugAPI.h
+++ b/js/public/OldDebugAPI.h
@@ -7,17 +7,17 @@
 #ifndef js_OldDebugAPI_h
 #define js_OldDebugAPI_h
 
 /*
  * JS debugger API.
  */
 
 #include "mozilla/NullPtr.h"
- 
+
 #include "jsbytecode.h"
 
 #include "js/CallArgs.h"
 #include "js/TypeDecls.h"
 
 class JSAtom;
 class JSFreeOp;
 
@@ -138,17 +138,17 @@ typedef void
                     size_t length, void **listenerTSData, void *closure);
 
 
 
 extern JS_PUBLIC_API(JSCompartment *)
 JS_EnterCompartmentOfScript(JSContext *cx, JSScript *target);
 
 extern JS_PUBLIC_API(JSString *)
-JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent);
+JS_DecompileScript(JSContext *cx, JS::HandleScript script, const char *name, unsigned indent);
 
 /*
  * Currently, we only support runtime-wide debugging. In the future, we should
  * be able to support compartment-wide debugging.
  */
 extern JS_PUBLIC_API(void)
 JS_SetRuntimeDebugMode(JSRuntime *rt, bool debug);
 
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -3368,20 +3368,24 @@ MOZ_ARG_ENABLE_BOOL(root-analysis,
     JSGC_ROOT_ANALYSIS= )
 if test -n "$JSGC_ROOT_ANALYSIS"; then
     AC_DEFINE(JSGC_ROOT_ANALYSIS)
 fi
 
 dnl ========================================================
 dnl = Use exact stack rooting for GC
 dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(exact-rooting,
-[  --enable-exact-rooting  Enable use of exact stack roots for GC],
-    JSGC_USE_EXACT_ROOTING=1,
-    JSGC_USE_EXACT_ROOTING= )
+dnl Use exact rooting by default in all shell builds. The top-level mozilla
+dnl configure.in will configure SpiderMonkey with --disable-exact-rooting as
+dnl needed on a per-platform basis.
+JSGC_USE_EXACT_ROOTING=1
+MOZ_ARG_DISABLE_BOOL(exact-rooting,
+[  --disable-exact-rooting  Enable use of conservative stack scanning for GC],
+    JSGC_USE_EXACT_ROOTING= ,
+    JSGC_USE_EXACT_ROOTING=1 )
 if test -n "$JSGC_USE_EXACT_ROOTING"; then
     AC_DEFINE(JSGC_USE_EXACT_ROOTING)
 fi
 
 dnl ========================================================
 dnl = Use Valgrind
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(valgrind,
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -6511,17 +6511,19 @@ frontend::EmitTree(ExclusiveContext *cx,
          * special casing. Note that the array object is a pure stack value,
          * unaliased by blocks, so we can EmitUnaliasedVarOp.
          */
         if (!EmitTree(cx, bce, pn->pn_kid))
             return false;
         uint32_t slot = bce->arrayCompDepth;
         if (!AdjustBlockSlot(cx, bce, &slot))
             return false;
-        if (!EmitUnaliasedVarOp(cx, pn->getOp(), slot, bce))
+        if (!EmitUnaliasedVarOp(cx, JSOP_GETLOCAL, slot, bce))
+            return false;
+        if (Emit1(cx, bce, JSOP_ARRAYPUSH) < 0)
             return false;
         break;
       }
 
       case PNK_ARRAY:
         if (!(pn->pn_xflags & PNX_NONCONST) && pn->pn_head && bce->checkSingletonContext())
             ok = EmitSingletonInitialiser(cx, bce, pn);
         else
--- a/js/src/gdb/tests/test-JSObject.cpp
+++ b/js/src/gdb/tests/test-JSObject.cpp
@@ -1,20 +1,20 @@
 #include "gdb-tests.h"
 #include "jsapi.h"
 
 FRAGMENT(JSObject, simple) {
   JS::Rooted<JSObject *> glob(cx, JS::CurrentGlobalOrNull(cx));
   JS::Rooted<JSObject *> plain(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
+  JS::Rooted<JSObject *> global(cx, JS::CurrentGlobalOrNull(cx));
   JS::Rooted<JSObject *> func(cx, (JSObject *) JS_NewFunction(cx, (JSNative) 1, 0, 0,
-                                                              JS::CurrentGlobalOrNull(cx), "dys"));
-  JS::Rooted<JSObject *> anon(cx, (JSObject *) JS_NewFunction(cx, (JSNative) 1, 0, 0,
-                                                              JS::CurrentGlobalOrNull(cx), 0));
+                                                              global, "dys"));
+  JS::Rooted<JSObject *> anon(cx, (JSObject *) JS_NewFunction(cx, (JSNative) 1, 0, 0, global, 0));
   JS::Rooted<JSFunction *> funcPtr(cx, JS_NewFunction(cx, (JSNative) 1, 0, 0,
-                                                      JS::CurrentGlobalOrNull(cx), "formFollows"));
+                                                      global, "formFollows"));
 
   JSObject &plainRef = *plain;
   JSFunction &funcRef = *funcPtr;
   JSObject *plainRaw = plain;
   JSObject *funcRaw = func;
 
   breakpoint();
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/bug953337.js
@@ -0,0 +1,8 @@
+setJitCompilerOption("ion.usecount.trigger", 20);
+Function.prototype.__proto__ = new Boolean({ get: function() {} }, {});
+function g(x, y) {}
+function f() {
+    g.apply(this, arguments);
+}
+for (var i = 0; i < 130; ++i)
+    f(i, i*2);
--- a/js/src/jit/AsmJSModule.cpp
+++ b/js/src/jit/AsmJSModule.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/AsmJSModule.h"
 
 #ifndef XP_WIN
 # include <sys/mman.h>
 #endif
 
+#include "mozilla/Compression.h"
 #include "mozilla/PodOperations.h"
 
 #include "jslibmath.h"
 #include "jsmath.h"
 #include "jsprf.h"
 #ifdef XP_WIN
 # include "jswin.h"
 #endif
@@ -27,16 +28,17 @@
 #include "jsobjinlines.h"
 
 #include "frontend/ParseNode-inl.h"
 
 using namespace js;
 using namespace jit;
 using namespace frontend;
 using mozilla::PodEqual;
+using mozilla::Compression::LZ4;
 
 void
 AsmJSModule::initHeap(Handle<ArrayBufferObject*> heap, JSContext *cx)
 {
     JS_ASSERT(linked_);
     JS_ASSERT(!maybeHeap_);
     maybeHeap_ = heap;
     heapDatum() = heap->dataPointer();
@@ -809,103 +811,148 @@ struct PropertyNameWrapper
     }
     const uint8_t *deserialize(ExclusiveContext *cx, const uint8_t *cursor) {
         return DeserializeName(cx, cursor, &name);
     }
 };
 
 class ModuleChars
 {
-    uint32_t length_;
-    const jschar *begin_;
+  protected:
     uint32_t isFunCtor_;
     js::Vector<PropertyNameWrapper, 0, SystemAllocPolicy> funCtorArgs_;
 
   public:
     static uint32_t beginOffset(AsmJSParser &parser) {
       return parser.pc->maybeFunction->pn_pos.begin;
     }
 
     static uint32_t endOffset(AsmJSParser &parser) {
       return parser.tokenStream.peekTokenPos().end;
     }
+};
 
-    bool initFromParsedModule(AsmJSParser &parser, const AsmJSModule &module) {
+class ModuleCharsForStore : ModuleChars
+{
+    uint32_t uncompressedSize_;
+    uint32_t compressedSize_;
+    js::Vector<char, 0, SystemAllocPolicy> compressedBuffer_;
+
+  public:
+    bool init(AsmJSParser &parser, const AsmJSModule &module) {
+        JS_ASSERT(beginOffset(parser) < endOffset(parser));
+
+        uncompressedSize_ = (endOffset(parser) - beginOffset(parser)) * sizeof(jschar);
+        size_t maxCompressedSize = LZ4::maxCompressedSize(uncompressedSize_);
+        if (maxCompressedSize < uncompressedSize_)
+            return false;
+
+        if (!compressedBuffer_.resize(maxCompressedSize))
+            return false;
+
+        const jschar *chars = parser.tokenStream.rawBase() + beginOffset(parser);
+        const char *source = reinterpret_cast<const char*>(chars);
+        size_t compressedSize = LZ4::compress(source, uncompressedSize_, compressedBuffer_.begin());
+        if (!compressedSize || compressedSize > UINT32_MAX)
+            return false;
+
+        compressedSize_ = compressedSize;
+
         // For a function statement or named function expression:
         //   function f(x,y,z) { abc }
         // the range [beginOffset, endOffset) captures the source:
         //   f(x,y,z) { abc }
         // An unnamed function expression captures the same thing, sans 'f'.
         // Since asm.js modules do not contain any free variables, equality of
         // [beginOffset, endOffset) is sufficient to guarantee identical code
         // generation, modulo MachineId.
         //
         // For functions created with 'new Function', function arguments are
         // not present in the source so we must manually explicitly serialize
         // and match the formals as a Vector of PropertyName.
-        JS_ASSERT(beginOffset(parser) < endOffset(parser));
-        begin_ = parser.tokenStream.rawBase() + beginOffset(parser);
-        length_ = endOffset(parser) - beginOffset(parser);
         isFunCtor_ = parser.pc->isFunctionConstructorBody();
         if (isFunCtor_) {
             unsigned numArgs;
             ParseNode *arg = FunctionArgsList(parser.pc->maybeFunction, &numArgs);
             for (unsigned i = 0; i < numArgs; i++, arg = arg->pn_next) {
                 if (!funCtorArgs_.append(arg->name()))
                     return false;
             }
         }
+
         return true;
     }
 
     size_t serializedSize() const {
         return sizeof(uint32_t) +
-               length_ * sizeof(jschar) +
+               sizeof(uint32_t) +
+               compressedSize_ +
                sizeof(uint32_t) +
                (isFunCtor_ ? SerializedVectorSize(funCtorArgs_) : 0);
     }
 
     uint8_t *serialize(uint8_t *cursor) const {
-        cursor = WriteScalar<uint32_t>(cursor, length_);
-        cursor = WriteBytes(cursor, begin_, length_ * sizeof(jschar));
+        cursor = WriteScalar<uint32_t>(cursor, uncompressedSize_);
+        cursor = WriteScalar<uint32_t>(cursor, compressedSize_);
+        cursor = WriteBytes(cursor, compressedBuffer_.begin(), compressedSize_);
         cursor = WriteScalar<uint32_t>(cursor, isFunCtor_);
         if (isFunCtor_)
             cursor = SerializeVector(cursor, funCtorArgs_);
         return cursor;
     }
+};
 
+class ModuleCharsForLookup : ModuleChars
+{
+    js::Vector<jschar, 0, SystemAllocPolicy> chars_;
+
+  public:
     const uint8_t *deserialize(ExclusiveContext *cx, const uint8_t *cursor) {
-        cursor = ReadScalar<uint32_t>(cursor, &length_);
-        begin_ = reinterpret_cast<const jschar *>(cursor);
-        cursor += length_ * sizeof(jschar);
+        uint32_t uncompressedSize;
+        cursor = ReadScalar<uint32_t>(cursor, &uncompressedSize);
+
+        uint32_t compressedSize;
+        cursor = ReadScalar<uint32_t>(cursor, &compressedSize);
+
+        if (!chars_.resize(uncompressedSize / sizeof(jschar)))
+            return nullptr;
+
+        const char *source = reinterpret_cast<const char*>(cursor);
+        char *dest = reinterpret_cast<char*>(chars_.begin());
+        if (!LZ4::decompress(source, dest, uncompressedSize))
+            return nullptr;
+
+        cursor += compressedSize;
+
         cursor = ReadScalar<uint32_t>(cursor, &isFunCtor_);
         if (isFunCtor_)
             cursor = DeserializeVector(cx, cursor, &funCtorArgs_);
+
         return cursor;
     }
 
-    bool matchUnparsedModule(AsmJSParser &parser) const {
+    bool match(AsmJSParser &parser) const {
         const jschar *parseBegin = parser.tokenStream.rawBase() + beginOffset(parser);
         const jschar *parseLimit = parser.tokenStream.rawLimit();
         JS_ASSERT(parseLimit >= parseBegin);
-        if (uint32_t(parseLimit - parseBegin) < length_)
+        if (uint32_t(parseLimit - parseBegin) < chars_.length())
             return false;
-        if (!PodEqual(begin_, parseBegin, length_))
+        if (!PodEqual(chars_.begin(), parseBegin, chars_.length()))
             return false;
         if (isFunCtor_ != parser.pc->isFunctionConstructorBody())
             return false;
         if (isFunCtor_) {
             // For function statements, the closing } is included as the last
             // character of the matched source. For Function constructor,
             // parsing terminates with EOF which we must explicitly check. This
             // prevents
             //   new Function('"use asm"; function f() {} return f')
             // from incorrectly matching
             //   new Function('"use asm"; function f() {} return ff')
-            if (parseBegin + length_ != parseLimit)
+            if (parseBegin + chars_.length() != parseLimit)
                 return false;
             unsigned numArgs;
             ParseNode *arg = FunctionArgsList(parser.pc->maybeFunction, &numArgs);
             if (funCtorArgs_.length() != numArgs)
                 return false;
             for (unsigned i = 0; i < funCtorArgs_.length(); i++, arg = arg->pn_next) {
                 if (funCtorArgs_[i].name != arg->name())
                     return false;
@@ -937,18 +984,18 @@ js::StoreAsmJSModuleInCache(AsmJSParser 
                             const AsmJSModule &module,
                             const AsmJSStaticLinkData &linkData,
                             ExclusiveContext *cx)
 {
     MachineId machineId;
     if (!machineId.extractCurrentState(cx))
         return false;
 
-    ModuleChars moduleChars;
-    if (!moduleChars.initFromParsedModule(parser, module))
+    ModuleCharsForStore moduleChars;
+    if (!moduleChars.init(parser, module))
         return false;
 
     size_t serializedSize = machineId.serializedSize() +
                             moduleChars.serializedSize() +
                             module.serializedSize() +
                             linkData.serializedSize();
 
     JS::OpenAsmJSCacheEntryForWriteOp open = cx->asmJSCacheOps().openEntryForWrite;
@@ -1016,19 +1063,19 @@ js::LookupAsmJSModuleInCache(ExclusiveCo
 
     MachineId cachedMachineId;
     cursor = cachedMachineId.deserialize(cx, cursor);
     if (!cursor)
         return false;
     if (machineId != cachedMachineId)
         return true;
 
-    ModuleChars moduleChars;
+    ModuleCharsForLookup moduleChars;
     cursor = moduleChars.deserialize(cx, cursor);
-    if (!moduleChars.matchUnparsedModule(parser))
+    if (!moduleChars.match(parser))
         return true;
 
     ScopedJSDeletePtr<AsmJSModule> module(
         cx->new_<AsmJSModule>(parser.ss, parser.offsetOfCurrentAsmJSModule()));
     if (!module)
         return false;
     cursor = module->deserialize(cx, cursor);
     if (!cursor)
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -5087,17 +5087,17 @@ IonBuilder::testShouldDOMCall(types::Typ
 
     // If all the DOM objects flowing through are legal with this
     // property, we can bake in a call to the bottom half of the DOM
     // accessor
     DOMInstanceClassMatchesProto instanceChecker =
         compartment->runtime()->DOMcallbacks()->instanceClassMatchesProto;
 
     const JSJitInfo *jinfo = func->jitInfo();
-    if (jinfo->type != opType)
+    if (jinfo->type() != opType)
         return false;
 
     for (unsigned i = 0; i < inTypes->getObjectCount(); i++) {
         types::TypeObjectKey *curType = inTypes->getObject(i);
         if (!curType)
             continue;
 
         if (!curType->hasTenuredProto())
@@ -5238,26 +5238,26 @@ IonBuilder::makeCallHelper(JSFunction *t
     return call;
 }
 
 static bool
 DOMCallNeedsBarrier(const JSJitInfo* jitinfo, types::TemporaryTypeSet *types)
 {
     // If the return type of our DOM native is in "types" already, we don't
     // actually need a barrier.
-    if (jitinfo->returnType == JSVAL_TYPE_UNKNOWN)
+    if (jitinfo->returnType() == JSVAL_TYPE_UNKNOWN)
         return true;
 
     // JSVAL_TYPE_OBJECT doesn't tell us much; we still have to barrier on the
     // actual type of the object.
-    if (jitinfo->returnType == JSVAL_TYPE_OBJECT)
+    if (jitinfo->returnType() == JSVAL_TYPE_OBJECT)
         return true;
 
     // No need for a barrier if we're already expecting the type we'll produce.
-    return jitinfo->returnType != types->getKnownTypeTag();
+    return jitinfo->returnType() != types->getKnownTypeTag();
 }
 
 bool
 IonBuilder::makeCall(JSFunction *target, CallInfo &callInfo, bool cloneAtCallsite)
 {
     // Constructor calls to non-constructors should throw. We don't want to use
     // CallKnown in this case.
     JS_ASSERT_IF(callInfo.constructing() && target,
@@ -6220,22 +6220,22 @@ IonBuilder::pushDOMTypeBarrier(MInstruct
     // Need to be a bit careful: if jitinfo->returnType is JSVAL_TYPE_DOUBLE but
     // types->getKnownTypeTag() is JSVAL_TYPE_INT32, then don't unconditionally
     // unbox as a double.  Instead, go ahead and barrier on having an int type,
     // since we know we need a barrier anyway due to the type mismatch.  This is
     // the only situation in which TI actually has more information about the
     // JSValueType than codegen can, short of jitinfo->returnType just being
     // JSVAL_TYPE_UNKNOWN.
     MDefinition* replace = ins;
-    if (jitinfo->returnType != JSVAL_TYPE_DOUBLE ||
+    if (jitinfo->returnType() != JSVAL_TYPE_DOUBLE ||
         observed->getKnownTypeTag() != JSVAL_TYPE_INT32) {
-        JS_ASSERT(jitinfo->returnType == JSVAL_TYPE_UNKNOWN ||
+        JS_ASSERT(jitinfo->returnType() == JSVAL_TYPE_UNKNOWN ||
                   observed->getKnownTypeTag() == JSVAL_TYPE_UNKNOWN ||
-                  jitinfo->returnType == observed->getKnownTypeTag());
-        replace = ensureDefiniteType(ins, jitinfo->returnType);
+                  jitinfo->returnType() == observed->getKnownTypeTag());
+        replace = ensureDefiniteType(ins, jitinfo->returnType());
         if (replace != ins) {
             current->pop();
             current->push(replace);
         }
     } else {
         JS_ASSERT(barrier);
     }
 
@@ -8830,17 +8830,17 @@ IonBuilder::setPropTryCommonDOMSetter(bo
     if (!isDOM)
         return true;
 
     types::TemporaryTypeSet *objTypes = obj->resultTypeSet();
     if (!testShouldDOMCall(objTypes, setter, JSJitInfo::Setter))
         return true;
 
     // Emit SetDOMProperty.
-    JS_ASSERT(setter->jitInfo()->type == JSJitInfo::Setter);
+    JS_ASSERT(setter->jitInfo()->type() == JSJitInfo::Setter);
     MSetDOMProperty *set = MSetDOMProperty::New(alloc(), setter->jitInfo()->setter, obj, value);
 
     current->add(set);
     current->push(value);
 
     if (!resumeAfter(set))
         return false;
 
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -959,16 +959,17 @@ class CallInfo
         return fun_;
     }
 
     void setFun(MDefinition *fun) {
         fun_ = fun;
     }
 
     void setImplicitlyUsedUnchecked() {
+        fun_->setImplicitlyUsedUnchecked();
         thisArg_->setImplicitlyUsedUnchecked();
         for (uint32_t i = 0; i < argc(); i++)
             getArg(i)->setImplicitlyUsedUnchecked();
     }
 };
 
 bool TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *inputTypes);
 
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -191,16 +191,17 @@ IonBuilder::inlineMathFunction(CallInfo 
         return InliningStatus_NotInlined;
     if (!IsNumberType(callInfo.getArg(0)->type()))
         return InliningStatus_NotInlined;
 
     const MathCache *cache = compartment->runtime()->maybeGetMathCache();
     if (!cache)
         return InliningStatus_NotInlined;
 
+    callInfo.fun()->setImplicitlyUsedUnchecked();
     callInfo.thisArg()->setImplicitlyUsedUnchecked();
 
     MMathFunction *ins = MMathFunction::New(alloc(), callInfo.getArg(0), function, cache);
     current->add(ins);
     current->push(ins);
     return InliningStatus_Inlined;
 }
 
@@ -241,16 +242,19 @@ IonBuilder::inlineArray(CallInfo &callIn
         MDefinition *arg = callInfo.getArg(0);
         if (!arg->isConstant())
             return InliningStatus_NotInlined;
 
         // Negative lengths generate a RangeError, unhandled by the inline path.
         initLength = arg->toConstant()->value().toInt32();
         if (initLength >= JSObject::NELEMENTS_LIMIT)
             return InliningStatus_NotInlined;
+
+        if (initLength <= ArrayObject::EagerAllocationMaxLength)
+            allocating = MNewArray::NewArray_Allocating;
     }
 
     callInfo.setImplicitlyUsedUnchecked();
 
     types::TemporaryTypeSet::DoubleConversion conversion =
         getInlineReturnTypeSet()->convertDoubleElements(constraints());
     {
         AutoThreadSafeAccess ts(templateObject);
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -666,21 +666,21 @@ MCall::New(TempAllocator &alloc, JSFunct
 AliasSet
 MCallDOMNative::getAliasSet() const
 {
     JS_ASSERT(getSingleTarget() && getSingleTarget()->isNative());
 
     const JSJitInfo *jitInfo = getSingleTarget()->jitInfo();
     JS_ASSERT(jitInfo);
 
-    JS_ASSERT(jitInfo->aliasSet != JSJitInfo::AliasNone);
+    JS_ASSERT(jitInfo->aliasSet() != JSJitInfo::AliasNone);
     // If we don't know anything about the types of our arguments, we have to
     // assume that type-coercions can have side-effects, so we need to alias
     // everything.
-    if (jitInfo->aliasSet != JSJitInfo::AliasDOMSets || !jitInfo->isTypedMethodJitInfo())
+    if (jitInfo->aliasSet() != JSJitInfo::AliasDOMSets || !jitInfo->isTypedMethodJitInfo())
         return AliasSet::Store(AliasSet::Any);
 
     uint32_t argIndex = 0;
     const JSTypedMethodJitInfo *methodInfo =
         reinterpret_cast<const JSTypedMethodJitInfo*>(jitInfo);
     for (const JSJitInfo::ArgType *argType = methodInfo->argTypes;
          *argType != JSJitInfo::ArgTypeListEnd;
          ++argType, ++argIndex)
@@ -718,17 +718,17 @@ MCallDOMNative::computeMovable()
     // effectful.  The jitinfo can't check for the latter, since it depends on
     // the types of our arguments.
     JS_ASSERT(getSingleTarget() && getSingleTarget()->isNative());
 
     const JSJitInfo *jitInfo = getSingleTarget()->jitInfo();
     JS_ASSERT(jitInfo);
 
     JS_ASSERT_IF(jitInfo->isMovable,
-                 jitInfo->aliasSet != JSJitInfo::AliasEverything);
+                 jitInfo->aliasSet() != JSJitInfo::AliasEverything);
 
     if (jitInfo->isMovable && !isEffectful())
         setMovable();
 }
 
 bool
 MCallDOMNative::congruentTo(MDefinition *ins) const
 {
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -7913,26 +7913,26 @@ class MGetDOMProperty
 {
     const JSJitInfo *info_;
 
   protected:
     MGetDOMProperty(const JSJitInfo *jitinfo, MDefinition *obj, MDefinition *guard)
       : info_(jitinfo)
     {
         JS_ASSERT(jitinfo);
-        JS_ASSERT(jitinfo->type == JSJitInfo::Getter);
+        JS_ASSERT(jitinfo->type() == JSJitInfo::Getter);
 
         setOperand(0, obj);
 
         // Pin the guard as an operand if we want to hoist later
         setOperand(1, guard);
 
         // We are movable iff the jitinfo says we can be.
         if (isDomMovable()) {
-            JS_ASSERT(jitinfo->aliasSet != JSJitInfo::AliasEverything);
+            JS_ASSERT(jitinfo->aliasSet() != JSJitInfo::AliasEverything);
             setMovable();
         }
 
         setResultType(MIRType_Value);
     }
 
     const JSJitInfo *info() const {
         return info_;
@@ -7952,17 +7952,17 @@ class MGetDOMProperty
     }
     bool isInfallible() const {
         return info_->isInfallible;
     }
     bool isDomMovable() const {
         return info_->isMovable;
     }
     JSJitInfo::AliasSet domAliasSet() const {
-        return info_->aliasSet;
+        return info_->aliasSet();
     }
     size_t domMemberSlotIndex() const {
         MOZ_ASSERT(info_->isInSlot);
         return info_->slotIndex;
     }
     MDefinition *object() {
         return getOperand(0);
     }
--- a/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
+++ b/js/src/jsapi-tests/testDefineGetterSetterNonEnumerable.cpp
@@ -17,22 +17,22 @@ BEGIN_TEST(testDefineGetterSetterNonEnum
 {
     static const char PROPERTY_NAME[] = "foo";
 
     JS::RootedValue vobj(cx);
     JS::RootedObject obj(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
     CHECK(obj);
     vobj = OBJECT_TO_JSVAL(obj);
 
-    JSFunction *funGet = JS_NewFunction(cx, NativeGetterSetter, 0, 0, nullptr, "get");
+    JSFunction *funGet = JS_NewFunction(cx, NativeGetterSetter, 0, 0, JS::NullPtr(), "get");
     CHECK(funGet);
     JS::RootedObject funGetObj(cx, JS_GetFunctionObject(funGet));
     JS::RootedValue vget(cx, OBJECT_TO_JSVAL(funGetObj));
 
-    JSFunction *funSet = JS_NewFunction(cx, NativeGetterSetter, 1, 0, nullptr, "set");
+    JSFunction *funSet = JS_NewFunction(cx, NativeGetterSetter, 1, 0, JS::NullPtr(), "set");
     CHECK(funSet);
     JS::RootedObject funSetObj(cx, JS_GetFunctionObject(funSet));
     JS::RootedValue vset(cx, OBJECT_TO_JSVAL(funSetObj));
 
     JS::RootedObject vObject(cx, JSVAL_TO_OBJECT(vobj));
     CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
                             JSVAL_VOID,
                             JS_DATA_TO_FUNC_PTR(JSPropertyOp, (JSObject*) funGetObj),
--- a/js/src/jsapi-tests/testLookup.cpp
+++ b/js/src/jsapi-tests/testLookup.cpp
@@ -50,17 +50,17 @@ static const JSClass DocumentAllClass = 
 };
 
 bool
 document_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id, unsigned flags,
                  JS::MutableHandleObject objp)
 {
     // If id is "all", resolve document.all=true.
     JS::RootedValue v(cx);
-    if (!JS_IdToValue(cx, id, v.address()))
+    if (!JS_IdToValue(cx, id, &v))
         return false;
     if (JSVAL_IS_STRING(v)) {
         JSString *str = JSVAL_TO_STRING(v);
         JSFlatString *flatStr = JS_FlattenString(cx, str);
         if (!flatStr)
             return false;
         if (JS_FlatStringEqualsAscii(flatStr, "all")) {
             JS::Rooted<JSObject*> docAll(cx,
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2220,38 +2220,32 @@ JS_IdArrayGet(JSContext *cx, JSIdArray *
 
 JS_PUBLIC_API(void)
 JS_DestroyIdArray(JSContext *cx, JSIdArray *ida)
 {
     cx->runtime()->defaultFreeOp()->free_(ida);
 }
 
 JS_PUBLIC_API(bool)
-JS_ValueToId(JSContext *cx, jsval valueArg, jsid *idp)
+JS_ValueToId(JSContext *cx, jsval valueArg, MutableHandleId idp)
 {
     RootedValue value(cx, valueArg);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, value);
-
-    RootedId id(cx);
-    if (!ValueToId<CanGC>(cx, value, &id))
-        return false;
-
-    *idp = id;
-    return true;
+    return ValueToId<CanGC>(cx, value, idp);
 }
 
 JS_PUBLIC_API(bool)
-JS_IdToValue(JSContext *cx, jsid id, jsval *vp)
+JS_IdToValue(JSContext *cx, jsid id, MutableHandleValue vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    *vp = IdToJsval(id);
-    assertSameCompartment(cx, *vp);
+    vp.set(IdToJsval(id));
+    assertSameCompartment(cx, vp);
     return true;
 }
 
 JS_PUBLIC_API(bool)
 JS_DefaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
@@ -2656,30 +2650,27 @@ JS_IsNative(JSObject *obj)
 
 JS_PUBLIC_API(JSRuntime *)
 JS_GetObjectRuntime(JSObject *obj)
 {
     return obj->compartment()->runtimeFromMainThread();
 }
 
 JS_PUBLIC_API(bool)
-JS_FreezeObject(JSContext *cx, JSObject *objArg)
-{
-    RootedObject obj(cx, objArg);
+JS_FreezeObject(JSContext *cx, HandleObject obj)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
-
     return JSObject::freeze(cx, obj);
 }
 
 JS_PUBLIC_API(bool)
-JS_DeepFreezeObject(JSContext *cx, JSObject *objArg)
-{
-    RootedObject obj(cx, objArg);
+JS_DeepFreezeObject(JSContext *cx, HandleObject obj)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */
     bool extensible;
     if (!JSObject::isExtensible(cx, obj, &extensible))
         return false;
@@ -3680,20 +3671,18 @@ static const Class prop_iter_class = {
     nullptr,        /* checkAccess */
     nullptr,        /* call        */
     nullptr,        /* hasInstance */
     nullptr,        /* construct   */
     prop_iter_trace
 };
 
 JS_PUBLIC_API(JSObject *)
-JS_NewPropertyIterator(JSContext *cx, JSObject *objArg)
-{
-    RootedObject obj(cx, objArg);
-
+JS_NewPropertyIterator(JSContext *cx, HandleObject obj)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
 
     RootedObject iterobj(cx, NewObjectWithClassProto(cx, &prop_iter_class, nullptr, obj));
     if (!iterobj)
         return nullptr;
 
@@ -3712,20 +3701,18 @@ JS_NewPropertyIterator(JSContext *cx, JS
     }
 
     /* iterobj cannot escape to other threads here. */
     iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
     return iterobj;
 }
 
 JS_PUBLIC_API(bool)
-JS_NextProperty(JSContext *cx, JSObject *iterobjArg, jsid *idp)
-{
-    RootedObject iterobj(cx, iterobjArg);
-
+JS_NextProperty(JSContext *cx, HandleObject iterobj, jsid *idp)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, iterobj);
     int32_t i = iterobj->getSlot(JSSLOT_ITER_INDEX).toInt32();
     if (i < 0) {
         /* Native case: private data is a property tree node pointer. */
         JS_ASSERT(iterobj->getParent()->isNative());
         Shape *shape = static_cast<Shape *>(iterobj->getPrivate());
@@ -3784,49 +3771,41 @@ JS_PUBLIC_API(bool)
 JS_IsArrayObject(JSContext *cx, JSObject *objArg)
 {
     RootedObject obj(cx, objArg);
     assertSameCompartment(cx, obj);
     return ObjectClassIs(obj, ESClass_Array, cx);
 }
 
 JS_PUBLIC_API(bool)
-JS_GetArrayLength(JSContext *cx, JSObject *objArg, uint32_t *lengthp)
-{
-    RootedObject obj(cx, objArg);
+JS_GetArrayLength(JSContext *cx, HandleObject obj, uint32_t *lengthp)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return GetLengthProperty(cx, obj, lengthp);
 }
 
 JS_PUBLIC_API(bool)
-JS_SetArrayLength(JSContext *cx, JSObject *objArg, uint32_t length)
-{
-    RootedObject obj(cx, objArg);
+JS_SetArrayLength(JSContext *cx, HandleObject obj, uint32_t length)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     return SetLengthProperty(cx, obj, length);
 }
 
 JS_PUBLIC_API(bool)
-JS_CheckAccess(JSContext *cx, JSObject *objArg, jsid idArg, JSAccessMode mode,
-               jsval *vp, unsigned *attrsp)
-{
-    RootedObject obj(cx, objArg);
-    RootedId id(cx, idArg);
-    RootedValue value(cx, *vp);
-
+JS_CheckAccess(JSContext *cx, HandleObject obj, HandleId id, JSAccessMode mode,
+               MutableHandleValue vp, unsigned *attrsp)
+{
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, id);
-    bool status = CheckAccess(cx, obj, id, mode, &value, attrsp);
-    *vp = value;
-    return status;
+    return CheckAccess(cx, obj, id, mode, vp, attrsp);
 }
 
 JS_PUBLIC_API(void)
 JS_HoldPrincipals(JSPrincipals *principals)
 {
     ++principals->refcount;
 }
 
@@ -3862,19 +3841,18 @@ JS_InitDestroyPrincipalsCallback(JSRunti
 {
     JS_ASSERT(destroyPrincipals);
     JS_ASSERT(!rt->destroyPrincipals);
     rt->destroyPrincipals = destroyPrincipals;
 }
 
 JS_PUBLIC_API(JSFunction *)
 JS_NewFunction(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
-               JSObject *parentArg, const char *name)
-{
-    RootedObject parent(cx, parentArg);
+               HandleObject parent, const char *name)
+{
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     RootedAtom atom(cx);
     if (name) {
@@ -3883,34 +3861,33 @@ JS_NewFunction(JSContext *cx, JSNative n
             return nullptr;
     }
 
     JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
     return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, atom);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags, JSObject *parentArg,
-                   jsid id)
-{
-    RootedObject parent(cx, parentArg);
+JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flags,
+                   HandleObject parent, HandleId id)
+{
     JS_ASSERT(JSID_IS_STRING(id));
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     JS_ASSERT(native);
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
 
     RootedAtom name(cx, JSID_TO_ATOM(id));
     JSFunction::Flags funFlags = JSAPIToJSFunctionFlags(flags);
     return NewFunction(cx, NullPtr(), native, nargs, funFlags, parent, name);
 }
 
 JS_PUBLIC_API(JSFunction *)
-JS::GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, jsid id, unsigned nargs)
+JS::GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, HandleId id, unsigned nargs)
 {
     JS_ASSERT(JSID_IS_STRING(id));
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
 
     RootedAtom name(cx, JSID_TO_ATOM(id));
     RootedAtom shName(cx, Atomize(cx, selfHostedName, strlen(selfHostedName)));
@@ -3918,20 +3895,20 @@ JS::GetSelfHostedFunction(JSContext *cx,
         return nullptr;
     RootedValue funVal(cx);
     if (!cx->global()->getSelfHostedFunction(cx, shName, name, nargs, &funVal))
         return nullptr;
     return &funVal.toObject().as<JSFunction>();
 }
 
 JS_PUBLIC_API(JSObject *)
-JS_CloneFunctionObject(JSContext *cx, JSObject *funobjArg, JSObject *parentArg)
-{
-    RootedObject funobj(cx, funobjArg);
+JS_CloneFunctionObject(JSContext *cx, HandleObject funobj, HandleObject parentArg)
+{
     RootedObject parent(cx, parentArg);
+
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, parent);
     // Note that funobj can be in a different compartment.
 
     if (!parent)
         parent = cx->global();
 
@@ -4019,19 +3996,18 @@ JS_IsNativeFunction(JSObject *funobj, JS
 
 extern JS_PUBLIC_API(bool)
 JS_IsConstructor(JSFunction *fun)
 {
     return fun->isNativeConstructor() || fun->isInterpretedConstructor();
 }
 
 JS_PUBLIC_API(JSObject*)
-JS_BindCallable(JSContext *cx, JSObject *targetArg, JSObject *newThis)
-{
-    RootedObject target(cx, targetArg);
+JS_BindCallable(JSContext *cx, HandleObject target, HandleObject newThis)
+{
     RootedValue thisArg(cx, ObjectValue(*newThis));
     return js_fun_bind(cx, target, thisArg, nullptr, 0);
 }
 
 static bool
 js_generic_native_method_dispatcher(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -4055,24 +4031,23 @@ js_generic_native_method_dispatcher(JSCo
 
     /* Clear the last parameter in case too few arguments were passed. */
     vp[2 + --argc].setUndefined();
 
     return fs->call.op(cx, argc, vp);
 }
 
 JS_PUBLIC_API(bool)
-JS_DefineFunctions(JSContext *cx, JSObject *objArg, const JSFunctionSpec *fs)
+JS_DefineFunctions(JSContext *cx, HandleObject obj, const JSFunctionSpec *fs)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, objArg);
-
-    RootedObject obj(cx, objArg);
+    assertSameCompartment(cx, obj);
+
     RootedObject ctor(cx);
 
     for (; fs->name; fs++) {
         RootedAtom atom(cx);
         // If the name starts with "@@", it must be a well-known symbol.
         if (fs->name[0] != '@' || fs->name[1] != '@')
             atom = Atomize(cx, fs->name, strlen(fs->name));
         else if (strcmp(fs->name, "@@iterator") == 0)
@@ -4507,19 +4482,18 @@ JS_CompileScript(JSContext *cx, JS::Hand
 JS_PUBLIC_API(JSScript *)
 JS_CompileUCScript(JSContext *cx, JS::HandleObject obj, const jschar *chars,
                    size_t length, const JS::CompileOptions &options)
 {
     return Compile(cx, obj, options, chars, length);
 }
 
 JS_PUBLIC_API(bool)
-JS_BufferIsCompilableUnit(JSContext *cx, JSObject *objArg, const char *utf8, size_t length)
-{
-    RootedObject obj(cx, objArg);
+JS_BufferIsCompilableUnit(JSContext *cx, HandleObject obj, const char *utf8, size_t length)
+{
     bool result;
     JSExceptionState *exnState;
     JSErrorReporter older;
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     jschar *chars = JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get();
@@ -4637,52 +4611,49 @@ JS_CompileFunction(JSContext *cx, JS::Ha
                    unsigned nargs, const char *const *argnames,
                    const char *ascii, size_t length,
                    const JS::CompileOptions &options)
 {
     return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
 }
 
 JS_PUBLIC_API(JSString *)
-JS_DecompileScript(JSContext *cx, JSScript *scriptArg, const char *name, unsigned indent)
+JS_DecompileScript(JSContext *cx, HandleScript script, const char *name, unsigned indent)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
 
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    RootedScript script(cx, scriptArg);
     script->ensureNonLazyCanonicalFunction(cx);
     RootedFunction fun(cx, script->functionNonDelazifying());
     if (fun)
         return JS_DecompileFunction(cx, fun, indent);
     bool haveSource = script->scriptSource()->hasSourceData();
     if (!haveSource && !JSScript::loadSource(cx, script->scriptSource(), &haveSource))
         return nullptr;
     return haveSource ? script->sourceData(cx) : js_NewStringCopyZ<CanGC>(cx, "[no source]");
 }
 
 JS_PUBLIC_API(JSString *)
-JS_DecompileFunction(JSContext *cx, JSFunction *funArg, unsigned indent)
+JS_DecompileFunction(JSContext *cx, HandleFunction fun, unsigned indent)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, funArg);
-    RootedFunction fun(cx, funArg);
+    assertSameCompartment(cx, fun);
     return FunctionToString(cx, fun, false, !(indent & JS_DONT_PRETTY_PRINT));
 }
 
 JS_PUBLIC_API(JSString *)
-JS_DecompileFunctionBody(JSContext *cx, JSFunction *funArg, unsigned indent)
+JS_DecompileFunctionBody(JSContext *cx, HandleFunction fun, unsigned indent)
 {
     JS_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, funArg);
-    RootedFunction fun(cx, funArg);
+    assertSameCompartment(cx, fun);
     return FunctionToString(cx, fun, true, !(indent & JS_DONT_PRETTY_PRINT));
 }
 
 JS_NEVER_INLINE JS_PUBLIC_API(bool)
 JS_ExecuteScript(JSContext *cx, JSObject *objArg, JSScript *scriptArg, jsval *rval)
 {
     RootedObject obj(cx, objArg);
     RootedScript script(cx, scriptArg);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -2304,20 +2304,20 @@ class AutoIdArray : private AutoGCRooter
     /* No copy or assignment semantics. */
     AutoIdArray(AutoIdArray &ida) MOZ_DELETE;
     void operator=(AutoIdArray &ida) MOZ_DELETE;
 };
 
 } /* namespace JS */
 
 extern JS_PUBLIC_API(bool)
-JS_ValueToId(JSContext *cx, jsval v, jsid *idp);
+JS_ValueToId(JSContext *cx, jsval v, JS::MutableHandle<jsid> idp);
 
 extern JS_PUBLIC_API(bool)
-JS_IdToValue(JSContext *cx, jsid id, jsval *vp);
+JS_IdToValue(JSContext *cx, jsid id, JS::MutableHandle<JS::Value> vp);
 
 /*
  * JSNewResolveOp flag bits.
  */
 #define JSRESOLVE_ASSIGNING     0x01    /* resolve on the left of assignment */
 
 /*
  * Invoke the [[DefaultValue]] hook (see ES5 8.6.2) with the provided hint on
@@ -2740,23 +2740,23 @@ JS_NewObjectWithGivenProto(JSContext *cx
                            JS::Handle<JSObject*> parent);
 
 /*
  * Freeze obj, and all objects it refers to, recursively. This will not recurse
  * through non-extensible objects, on the assumption that those are already
  * deep-frozen.
  */
 extern JS_PUBLIC_API(bool)
-JS_DeepFreezeObject(JSContext *cx, JSObject *obj);
+JS_DeepFreezeObject(JSContext *cx, JS::Handle<JSObject*> obj);
 
 /*
  * Freezes an object; see ES5's Object.freeze(obj) method.
  */
 extern JS_PUBLIC_API(bool)
-JS_FreezeObject(JSContext *cx, JSObject *obj);
+JS_FreezeObject(JSContext *cx, JS::Handle<JSObject*> obj);
 
 extern JS_PUBLIC_API(bool)
 JS_PreventExtensions(JSContext *cx, JS::HandleObject obj);
 
 extern JS_PUBLIC_API(JSObject *)
 JS_New(JSContext *cx, JSObject *ctor, unsigned argc, jsval *argv);
 
 extern JS_PUBLIC_API(JSObject *)
@@ -3055,20 +3055,20 @@ JS_DeleteUCProperty2(JSContext *cx, JSOb
 
 extern JS_PUBLIC_API(JSObject *)
 JS_NewArrayObject(JSContext *cx, int length, jsval *vector);
 
 extern JS_PUBLIC_API(bool)
 JS_IsArrayObject(JSContext *cx, JSObject *obj);
 
 extern JS_PUBLIC_API(bool)
-JS_GetArrayLength(JSContext *cx, JSObject *obj, uint32_t *lengthp);
+JS_GetArrayLength(JSContext *cx, JS::Handle<JSObject*> obj, uint32_t *lengthp);
 
 extern JS_PUBLIC_API(bool)
-JS_SetArrayLength(JSContext *cx, JSObject *obj, uint32_t length);
+JS_SetArrayLength(JSContext *cx, JS::Handle<JSObject*> obj, uint32_t length);
 
 extern JS_PUBLIC_API(bool)
 JS_DefineElement(JSContext *cx, JSObject *obj, uint32_t index, jsval value,
                  JSPropertyOp getter, JSStrictPropertyOp setter, unsigned attrs);
 
 extern JS_PUBLIC_API(bool)
 JS_AlreadyHasOwnElement(JSContext *cx, JSObject *obj, uint32_t index, bool *foundp);
 
@@ -3153,29 +3153,29 @@ extern JS_PUBLIC_API(JSIdArray *)
 JS_Enumerate(JSContext *cx, JSObject *obj);
 
 /*
  * Create an object to iterate over enumerable properties of obj, in arbitrary
  * property definition order.  NB: This differs from longstanding for..in loop
  * order, which uses order of property definition in obj.
  */
 extern JS_PUBLIC_API(JSObject *)
-JS_NewPropertyIterator(JSContext *cx, JSObject *obj);
+JS_NewPropertyIterator(JSContext *cx, JS::Handle<JSObject*> obj);
 
 /*
  * Return true on success with *idp containing the id of the next enumerable
  * property to visit using iterobj, or JSID_IS_VOID if there is no such property
  * left to visit.  Return false on error.
  */
 extern JS_PUBLIC_API(bool)
-JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp);
+JS_NextProperty(JSContext *cx, JS::Handle<JSObject*> iterobj, jsid *idp);
 
 extern JS_PUBLIC_API(bool)
-JS_CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
-               jsval *vp, unsigned *attrsp);
+JS_CheckAccess(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JSAccessMode mode,
+               JS::MutableHandle<JS::Value> vp, unsigned *attrsp);
 
 extern JS_PUBLIC_API(jsval)
 JS_GetReservedSlot(JSObject *obj, uint32_t index);
 
 extern JS_PUBLIC_API(void)
 JS_SetReservedSlot(JSObject *obj, uint32_t index, jsval v);
 
 /************************************************************************/
@@ -3252,30 +3252,31 @@ JS_InitDestroyPrincipalsCallback(JSRunti
 
 /************************************************************************/
 
 /*
  * Functions and scripts.
  */
 extern JS_PUBLIC_API(JSFunction *)
 JS_NewFunction(JSContext *cx, JSNative call, unsigned nargs, unsigned flags,
-               JSObject *parent, const char *name);
+               JS::Handle<JSObject*> parent, const char *name);
 
 /*
  * Create the function with the name given by the id. JSID_IS_STRING(id) must
  * be true.
  */
 extern JS_PUBLIC_API(JSFunction *)
 JS_NewFunctionById(JSContext *cx, JSNative call, unsigned nargs, unsigned flags,
-                   JSObject *parent, jsid id);
+                   JS::Handle<JSObject*> parent, JS::Handle<jsid> id);
 
 namespace JS {
 
 extern JS_PUBLIC_API(JSFunction *)
-GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, jsid id, unsigned nargs);
+GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, JS::Handle<jsid> id,
+                      unsigned nargs);
 
 } /* namespace JS */
 
 extern JS_PUBLIC_API(JSObject *)
 JS_GetFunctionObject(JSFunction *fun);
 
 /*
  * Return the function's identifier as a JSString, or null if fun is unnamed.
@@ -3322,20 +3323,20 @@ extern JS_PUBLIC_API(bool)
 JS_IsConstructor(JSFunction *fun);
 
 /*
  * Bind the given callable to use the given object as "this".
  *
  * If |callable| is not callable, will throw and return nullptr.
  */
 extern JS_PUBLIC_API(JSObject*)
-JS_BindCallable(JSContext *cx, JSObject *callable, JSObject *newThis);
+JS_BindCallable(JSContext *cx, JS::Handle<JSObject*> callable, JS::Handle<JSObject*> newThis);
 
 extern JS_PUBLIC_API(bool)
-JS_DefineFunctions(JSContext *cx, JSObject *obj, const JSFunctionSpec *fs);
+JS_DefineFunctions(JSContext *cx, JS::Handle<JSObject*> obj, const JSFunctionSpec *fs);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_DefineFunction(JSContext *cx, JSObject *obj, const char *name, JSNative call,
                   unsigned nargs, unsigned attrs);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_DefineUCFunction(JSContext *cx, JSObject *obj,
                     const jschar *name, size_t namelen, JSNative call,
@@ -3345,27 +3346,28 @@ extern JS_PUBLIC_API(JSFunction *)
 JS_DefineFunctionById(JSContext *cx, JSObject *obj, jsid id, JSNative call,
                       unsigned nargs, unsigned attrs);
 
 /*
  * Clone a top-level function into a new scope. This function will dynamically
  * fail if funobj was lexically nested inside some other function.
  */
 extern JS_PUBLIC_API(JSObject *)
-JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent);
+JS_CloneFunctionObject(JSContext *cx, JS::Handle<JSObject*> funobj, JS::Handle<JSObject*> parent);
 
 /*
  * Given a buffer, return false if the buffer might become a valid
  * javascript statement with the addition of more lines.  Otherwise return
  * true.  The intent is to support interactive compilation - accumulate
  * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
  * the compiler.
  */
 extern JS_PUBLIC_API(bool)
-JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, const char *utf8, size_t length);
+JS_BufferIsCompilableUnit(JSContext *cx, JS::Handle<JSObject*> obj, const char *utf8,
+                          size_t length);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileScript(JSContext *cx, JS::HandleObject obj,
                  const char *ascii, size_t length,
                  const JS::CompileOptions &options);
 
 extern JS_PUBLIC_API(JSScript *)
 JS_CompileUCScript(JSContext *cx, JS::HandleObject obj,
@@ -3679,29 +3681,29 @@ CompileFunction(JSContext *cx, JS::Handl
 extern JS_PUBLIC_API(JSFunction *)
 CompileFunction(JSContext *cx, JS::HandleObject obj, const ReadOnlyCompileOptions &options,
                 const char *name, unsigned nargs, const char *const *argnames,
                 const jschar *chars, size_t length);
 
 } /* namespace JS */
 
 extern JS_PUBLIC_API(JSString *)
-JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent);
+JS_DecompileScript(JSContext *cx, JS::Handle<JSScript*> script, const char *name, unsigned indent);
 
 /*
  * API extension: OR this into indent to avoid pretty-printing the decompiled
  * source resulting from JS_DecompileFunction{,Body}.
  */
 #define JS_DONT_PRETTY_PRINT    ((unsigned)0x8000)
 
 extern JS_PUBLIC_API(JSString *)
-JS_DecompileFunction(JSContext *cx, JSFunction *fun, unsigned indent);
+JS_DecompileFunction(JSContext *cx, JS::Handle<JSFunction*> fun, unsigned indent);
 
 extern JS_PUBLIC_API(JSString *)
-JS_DecompileFunctionBody(JSContext *cx, JSFunction *fun, unsigned indent);
+JS_DecompileFunctionBody(JSContext *cx, JS::Handle<JSFunction*> fun, unsigned indent);
 
 /*
  * NB: JS_ExecuteScript and the JS_Evaluate*Script* quadruplets use the obj
  * parameter as the initial scope chain header, the 'this' keyword value, and
  * the variables object (ECMA parlance for where 'var' and 'function' bind
  * names) of the execution context for script.
  *
  * Using obj as the variables object is problematic if obj's parent (which is
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1999,18 +1999,18 @@ js::array_sort(JSContext *cx, unsigned a
     while (len > n) {
         if (!JS_CHECK_OPERATION_LIMIT(cx) || !DeletePropertyOrThrow(cx, obj, --len))
             return false;
     }
     args.rval().setObject(*obj);
     return true;
 }
 
-static JS_ALWAYS_INLINE bool
-NewbornArrayPushImpl(JSContext *cx, HandleObject obj, const Value &v)
+bool
+js::NewbornArrayPush(JSContext *cx, HandleObject obj, const Value &v)
 {
     Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
 
     JS_ASSERT(!v.isMagic());
     JS_ASSERT(arr->lengthIsWritable());
 
     uint32_t length = arr->length();
     JS_ASSERT(length <= arr->getDenseCapacity());
@@ -2019,22 +2019,16 @@ NewbornArrayPushImpl(JSContext *cx, Hand
         return false;
 
     arr->setDenseInitializedLength(length + 1);
     arr->setLengthInt32(length + 1);
     arr->initDenseElementWithType(cx, length, v);
     return true;
 }
 
-bool
-js_NewbornArrayPush(JSContext *cx, HandleObject obj, const Value &vp)
-{
-    return NewbornArrayPushImpl(cx, obj, vp);
-}
-
 /* ES5 15.4.4.7 */
 bool
 js::array_push(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     /* Step 1. */
     RootedObject obj(cx, ToObject(cx, args.thisv()));
@@ -3047,20 +3041,18 @@ js_Array(JSContext *cx, unsigned argc, V
             return false;
         }
     }
 
     /*
      * Allocate dense elements eagerly for small arrays, to avoid reallocating
      * elements when filling the array.
      */
-    static const uint32_t ArrayEagerAllocationMaxLength = 2048;
-
     RootedObject obj(cx);
-    obj = (length <= ArrayEagerAllocationMaxLength)
+    obj = (length <= ArrayObject::EagerAllocationMaxLength)
           ? NewDenseAllocatedArray(cx, length)
           : NewDenseUnallocatedArray(cx, length);
     if (!obj)
         return false;
     Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
 
     arr->setType(type);
 
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -135,30 +135,30 @@ array_concat_dense(JSContext *cx, Handle
                    Handle<ArrayObject*> result);
 
 extern void
 ArrayShiftMoveElements(JSObject *obj);
 
 extern bool
 array_shift(JSContext *cx, unsigned argc, js::Value *vp);
 
-} /* namespace js */
-
-#ifdef DEBUG
-extern bool
-js_ArrayInfo(JSContext *cx, unsigned argc, js::Value *vp);
-#endif
-
 /*
  * Append the given (non-hole) value to the end of an array.  The array must be
  * a newborn array -- that is, one which has not been exposed to script for
  * arbitrary manipulation.  (This method optimizes on the assumption that
  * extending the array to accommodate the element will never make the array
  * sparse, which requires that the array be completely filled.)
  */
 extern bool
-js_NewbornArrayPush(JSContext *cx, js::HandleObject obj, const js::Value &v);
+NewbornArrayPush(JSContext *cx, HandleObject obj, const Value &v);
+
+} /* namespace js */
+
+#ifdef DEBUG
+extern bool
+js_ArrayInfo(JSContext *cx, unsigned argc, js::Value *vp);
+#endif
 
 /* Array constructor native. Exposed only so the JIT can know its address. */
 bool
 js_Array(JSContext *cx, unsigned argc, js::Value *vp);
 
 #endif /* jsarray_h */
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1443,21 +1443,23 @@ typedef bool
 typedef bool
 (* JSJitSetterOp)(JSContext *cx, JS::HandleObject thisObj,
                   void *specializedThis, JSJitSetterCallArgs args);
 typedef bool
 (* JSJitMethodOp)(JSContext *cx, JS::HandleObject thisObj,
                   void *specializedThis, const JSJitMethodCallArgs& args);
 
 struct JSJitInfo {
-    enum OpType MOZ_ENUM_TYPE(uint8_t) {
+    enum OpType {
         Getter,
         Setter,
         Method,
-        ParallelNative
+        ParallelNative,
+        // Must be last
+        OpTypeCount
     };
 
     enum ArgType {
         // Basic types
         String = (1 << 0),
         Integer = (1 << 1), // Only 32-bit or less
         Double = (1 << 2), // Maybe we want to add Float sometime too
         Boolean = (1 << 3),
@@ -1471,95 +1473,142 @@ struct JSJitInfo {
         Primitive = Numeric | Boolean | Null | String,
         ObjectOrNull = Object | Null,
         Any = ObjectOrNull | Primitive,
 
         // Our sentinel value.
         ArgTypeListEnd = (1 << 31)
     };
 
-    enum AliasSet MOZ_ENUM_TYPE(uint8_t) {
+    enum AliasSet {
         // An enum that describes what this getter/setter/method aliases.  This
         // determines what things can be hoisted past this call, and if this
         // call is movable what it can be hoisted past.
 
         // Alias nothing: a constant value, getting it can't affect any other
         // values, nothing can affect it.
         AliasNone,
 
         // Alias things that can modify the DOM but nothing else.  Doing the
         // call can't affect the behavior of any other function.
         AliasDOMSets,
 
         // Alias the world.  Calling this can change arbitrary values anywhere
         // in the system.  Most things fall in this bucket.
-        AliasEverything
+        AliasEverything,
+
+        // Must be last.
+        AliasSetCount
     };
 
     bool hasParallelNative() const
     {
-        return type == ParallelNative;
+        return type() == ParallelNative;
     }
 
     bool isDOMJitInfo() const
     {
-        return type != ParallelNative;
+        return type() != ParallelNative;
     }
 
     bool isTypedMethodJitInfo() const
     {
         return isTypedMethod;
     }
 
+    OpType type() const
+    {
+        return OpType(type_);
+    }
+
+    AliasSet aliasSet() const
+    {
+        return AliasSet(aliasSet_);
+    }
+
+    JSValueType returnType() const
+    {
+        return JSValueType(returnType_);
+    }
+
     union {
         JSJitGetterOp getter;
         JSJitSetterOp setter;
         JSJitMethodOp method;
         /* An alternative native that's safe to call in parallel mode. */
         JSParallelNative parallelNative;
     };
 
     uint16_t protoID;
     uint16_t depth;
-    // type not being ParallelNative means this is a DOM method.  If you
-    // change that, come up with a different way of implementing
+
+    // These fields are carefully packed to take up 4 bytes.  If you need more
+    // bits for whatever reason, please see if you can steal bits from existing
+    // fields before adding more members to this structure.
+
+#define JITINFO_OP_TYPE_BITS 4
+#define JITINFO_ALIAS_SET_BITS 4
+#define JITINFO_RETURN_TYPE_BITS 8
+
+    // If this field is not ParallelNative, then this is a DOM method.
+    // If you change that, come up with a different way of implementing
     // isDOMJitInfo().
-    OpType type;
-    JSValueType returnType; /* The return type tag.  Might be JSVAL_TYPE_UNKNOWN */
-    uint16_t isInfallible : 1; /* Is op fallible? False in setters. */
-    uint16_t isMovable : 1;    /* Is op movable?  To be movable the op must
+    uint32_t type_ : JITINFO_OP_TYPE_BITS;
+
+    // The alias set for this op.  This is a _minimal_ alias set; in
+    // particular for a method it does not include whatever argument
+    // conversions might do.  That's covered by argTypes and runtime
+    // analysis of the actual argument types being passed in.
+    uint32_t aliasSet_ : JITINFO_ALIAS_SET_BITS;
+
+    // The return type tag.  Might be JSVAL_TYPE_UNKNOWN.
+    uint32_t returnType_ : JITINFO_RETURN_TYPE_BITS;
+
+    static_assert(OpTypeCount <= (1 << JITINFO_OP_TYPE_BITS),
+                  "Not enough space for OpType");
+    static_assert(AliasSetCount <= (1 << JITINFO_ALIAS_SET_BITS),
+                  "Not enough space for AliasSet");
+    static_assert((sizeof(JSValueType) * 8) <= JITINFO_RETURN_TYPE_BITS,
+                  "Not enough space for JSValueType");
+
+#undef JITINFO_RETURN_TYPE_BITS
+#undef JITINFO_ALIAS_SET_BITS
+#undef JITINFO_OP_TYPE_BITS
+
+    uint32_t isInfallible : 1; /* Is op fallible? False in setters. */
+    uint32_t isMovable : 1;    /* Is op movable?  To be movable the op must
                                   not AliasEverything, but even that might
                                   not be enough (e.g. in cases when it can
                                   throw). */
     // XXXbz should we have a JSValueType for the type of the member?
-    uint16_t isInSlot : 1;     /* True if this is a getter that can get a member
+    uint32_t isInSlot : 1;     /* True if this is a getter that can get a member
                                   from a slot of the "this" object directly. */
-    uint16_t isTypedMethod : 1; /* True if this is an instance of
+    uint32_t isTypedMethod : 1; /* True if this is an instance of
                                    JSTypedMethodJitInfo. */
-    uint16_t slotIndex : 12;   /* If isInSlot is true, the index of the slot to
+    uint32_t slotIndex : 12;   /* If isInSlot is true, the index of the slot to
                                   get the value from.  Otherwise 0. */
 
-    AliasSet aliasSet;      /* The alias set for this op.  This is a _minimal_
-                               alias set; in particular for a method it does not
-                               include whatever argument conversions might do.
-                               That's covered by argTypes and runtime analysis
-                               of the actual argument types being passed in. */
-
 private:
     static void staticAsserts()
     {
         JS_STATIC_ASSERT(Any & String);
         JS_STATIC_ASSERT(Any & Integer);
         JS_STATIC_ASSERT(Any & Double);
         JS_STATIC_ASSERT(Any & Boolean);
         JS_STATIC_ASSERT(Any & Object);
         JS_STATIC_ASSERT(Any & Null);
     }
 };
 
+static_assert(sizeof(JSJitInfo) == (sizeof(void*) + 2 * sizeof(uint32_t)),
+              "There are several thousand instances of JSJitInfo stored in "
+              "a binary. Please don't increase its space requirements without "
+              "verifying that there is no other way forward (better packing, "
+              "smaller datatypes for fields, subclassing, etc.).");
+
 struct JSTypedMethodJitInfo
 {
     // We use C-style inheritance here, rather than C++ style inheritance
     // because not all compilers support brace-initialization for non-aggregate
     // classes. Using C++ style inheritance and constructors instead of
     // brace-initialization would also force the creation of static
     // constructors (on some compilers) when JSJitInfo and JSTypedMethodJitInfo
     // structures are declared. Since there can be several thousand of these
@@ -1599,17 +1648,17 @@ inline int CheckIsParallelNative(JSParal
  * a datum of the type of the union's first member.)
  *
  * Presumably this has something to do with template instantiation.
  * Initializing with a normal function pointer seems to work fine. Hence
  * the ugliness that you see before you.
  */
 #define JS_JITINFO_NATIVE_PARALLEL(infoName, parallelOp)                \
     const JSJitInfo infoName =                                          \
-        {{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSVAL_TYPE_MISSING,false,false,false,false,0,JSJitInfo::AliasEverything}
+        {{JS_CAST_PARALLEL_NATIVE_TO(parallelOp, JSJitGetterOp)},0,0,JSJitInfo::ParallelNative,JSJitInfo::AliasEverything,JSVAL_TYPE_MISSING,false,false,false,false,0}
 
 #define JS_JITINFO_NATIVE_PARALLEL_THREADSAFE(infoName, wrapperName, serialOp) \
     bool wrapperName##_ParallelNativeThreadSafeWrapper(js::ForkJoinSlice *slice, unsigned argc, \
                                                        JS::Value *vp)   \
     {                                                                   \
         return JSParallelNativeThreadSafeWrapper<serialOp>(slice, argc, vp); \
     }                                                                   \
     JS_JITINFO_NATIVE_PARALLEL(infoName, wrapperName##_ParallelNativeThreadSafeWrapper)
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -870,17 +870,18 @@ ToDisassemblySource(JSContext *cx, Handl
             source = JS_sprintf_append(source, "}");
             if (!source)
                 return false;
             bytes->initBytes(source);
             return true;
         }
 
         if (obj->is<JSFunction>()) {
-            JSString *str = JS_DecompileFunction(cx, &obj->as<JSFunction>(), JS_DONT_PRETTY_PRINT);
+            RootedFunction fun(cx, &obj->as<JSFunction>());
+            JSString *str = JS_DecompileFunction(cx, fun, JS_DONT_PRETTY_PRINT);
             if (!str)
                 return false;
             return bytes->encodeLatin1(cx, str);
         }
 
         if (obj->is<RegExpObject>()) {
             JSString *source = obj->as<RegExpObject>().toString(cx);
             if (!source)
--- a/js/src/jsopcode.tbl
+++ b/js/src/jsopcode.tbl
@@ -434,17 +434,17 @@ OPDEF(JSOP_DEBUGLEAVEBLOCK, 200,"debugle
 
 OPDEF(JSOP_UNUSED201,     201,"unused201",  NULL,     1,  0,  0,  JOF_BYTE)
 
 /*
  * Generator and array comprehension support.
  */
 OPDEF(JSOP_GENERATOR,     202,"generator",   NULL,    1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_YIELD,         203,"yield",       NULL,    1,  1,  1,  JOF_BYTE)
-OPDEF(JSOP_ARRAYPUSH,     204,"arraypush",   NULL,    4,  1,  0,  JOF_LOCAL)
+OPDEF(JSOP_ARRAYPUSH,     204,"arraypush",   NULL,    1,  2,  0,  JOF_BYTE)
 
 OPDEF(JSOP_UNUSED205,     205, "unused205",    NULL,  1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED206,     206, "unused206",    NULL,  1,  0,  0,  JOF_BYTE)
 
 OPDEF(JSOP_UNUSED207,     207, "unused207",    NULL,  1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED208,     208, "unused208",    NULL,  1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED209,     209, "unused209",    NULL,  1,  0,  0,  JOF_BYTE)
 OPDEF(JSOP_UNUSED210,     210, "unused210",    NULL,  1,  0,  0,  JOF_BYTE)
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -28,16 +28,17 @@
 
 #include "frontend/BytecodeEmitter.h"
 #include "frontend/SharedContext.h"
 #include "gc/Marking.h"
 #include "jit/BaselineJIT.h"
 #include "jit/IonCode.h"
 #include "js/OldDebugAPI.h"
 #include "vm/ArgumentsObject.h"
+#include "vm/Compression.h"
 #include "vm/Debugger.h"
 #include "vm/Shape.h"
 #include "vm/Xdr.h"
 
 #include "jsfuninlines.h"
 #include "jsinferinlines.h"
 #include "jsobjinlines.h"
 
@@ -1234,17 +1235,17 @@ ScriptSource::setSource(const jschar *sr
 {
     JS_ASSERT(!hasSourceData());
     length_ = length;
     JS_ASSERT(!argumentsNotIncluded_);
     data.source = const_cast<jschar *>(src);
 }
 
 bool
-SourceCompressionTask::compress()
+SourceCompressionTask::work()
 {
     // A given compression token can be compressed on any thread, and the ss
     // not being ready indicates to other threads that its fields might change
     // with no lock held.
     JS_ASSERT(!ss->ready());
 
     size_t compressedLength = 0;
     size_t nbytes = sizeof(jschar) * ss->length_;
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -22,131 +22,16 @@
 
 #include "js/Utility.h"
 
 using namespace js;
 
 using mozilla::CeilingLog2Size;
 using mozilla::PodArrayZero;
 
-#if USE_ZLIB
-static void *
-zlib_alloc(void *cx, uInt items, uInt size)
-{
-    return js_calloc(items, size);
-}
-
-static void
-zlib_free(void *cx, void *addr)
-{
-    js_free(addr);
-}
-
-Compressor::Compressor(const unsigned char *inp, size_t inplen)
-    : inp(inp),
-      inplen(inplen),
-      outbytes(0)
-{
-    JS_ASSERT(inplen > 0);
-    zs.opaque = nullptr;
-    zs.next_in = (Bytef *)inp;
-    zs.avail_in = 0;
-    zs.next_out = nullptr;
-    zs.avail_out = 0;
-    zs.zalloc = zlib_alloc;
-    zs.zfree = zlib_free;
-}
-
-
-Compressor::~Compressor()
-{
-    int ret = deflateEnd(&zs);
-    if (ret != Z_OK) {
-        // If we finished early, we can get a Z_DATA_ERROR.
-        JS_ASSERT(ret == Z_DATA_ERROR);
-        JS_ASSERT(uInt(zs.next_in - inp) < inplen || !zs.avail_out);
-    }
-}
-
-bool
-Compressor::init()
-{
-    if (inplen >= UINT32_MAX)
-        return false;
-    // zlib is slow and we'd rather be done compression sooner
-    // even if it means decompression is slower which penalizes
-    // Function.toString()
-    int ret = deflateInit(&zs, Z_BEST_SPEED);
-    if (ret != Z_OK) {
-        JS_ASSERT(ret == Z_MEM_ERROR);
-        return false;
-    }
-    return true;
-}
-
-void
-Compressor::setOutput(unsigned char *out, size_t outlen)
-{
-    JS_ASSERT(outlen > outbytes);
-    zs.next_out = out + outbytes;
-    zs.avail_out = outlen - outbytes;
-}
-
-Compressor::Status
-Compressor::compressMore()
-{
-    JS_ASSERT(zs.next_out);
-    uInt left = inplen - (zs.next_in - inp);
-    bool done = left <= CHUNKSIZE;
-    if (done)
-        zs.avail_in = left;
-    else if (zs.avail_in == 0)
-        zs.avail_in = CHUNKSIZE;
-    Bytef *oldout = zs.next_out;
-    int ret = deflate(&zs, done ? Z_FINISH : Z_NO_FLUSH);
-    outbytes += zs.next_out - oldout;
-    if (ret == Z_MEM_ERROR) {
-        zs.avail_out = 0;
-        return OOM;
-    }
-    if (ret == Z_BUF_ERROR || (done && ret == Z_OK)) {
-        JS_ASSERT(zs.avail_out == 0);
-        return MOREOUTPUT;
-    }
-    JS_ASSERT_IF(!done, ret == Z_OK);
-    JS_ASSERT_IF(done, ret == Z_STREAM_END);
-    return done ? DONE : CONTINUE;
-}
-
-bool
-js::DecompressString(const unsigned char *inp, size_t inplen, unsigned char *out, size_t outlen)
-{
-    JS_ASSERT(inplen <= UINT32_MAX);
-    z_stream zs;
-    zs.zalloc = zlib_alloc;
-    zs.zfree = zlib_free;
-    zs.opaque = nullptr;
-    zs.next_in = (Bytef *)inp;
-    zs.avail_in = inplen;
-    zs.next_out = out;
-    JS_ASSERT(outlen);
-    zs.avail_out = outlen;
-    int ret = inflateInit(&zs);
-    if (ret != Z_OK) {
-        JS_ASSERT(ret == Z_MEM_ERROR);
-        return false;
-    }
-    ret = inflate(&zs, Z_FINISH);
-    JS_ASSERT(ret == Z_STREAM_END);
-    ret = inflateEnd(&zs);
-    JS_ASSERT(ret == Z_OK);
-    return true;
-}
-#endif
-
 #ifdef DEBUG
 /* For JS_OOM_POSSIBLY_FAIL in jsutil.h. */
 JS_PUBLIC_DATA(uint32_t) OOM_maxAllocations = UINT32_MAX;
 JS_PUBLIC_DATA(uint32_t) OOM_counter = 0;
 #endif
 
 /*
  * Checks the assumption that JS_FUNC_TO_DATA_PTR and JS_DATA_TO_FUNC_PTR
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -11,20 +11,16 @@
 #ifndef jsutil_h
 #define jsutil_h
 
 #include "mozilla/Compiler.h"
 #include "mozilla/GuardObjects.h"
 
 #include <limits.h>
 
-#ifdef USE_ZLIB
-#include <zlib.h>
-#endif
-
 #include "js/Utility.h"
 
 static JS_ALWAYS_INLINE void *
 js_memcpy(void *dst_, const void *src_, size_t len)
 {
     char *dst = (char *) dst_;
     const char *src = (const char *) src_;
     JS_ASSERT_IF(dst >= src, (size_t) (dst - src) >= len);
@@ -259,51 +255,16 @@ ClearBitArrayElement(size_t *array, size
 
 static inline void
 ClearAllBitArrayElements(size_t *array, size_t length)
 {
     for (unsigned i = 0; i < length; ++i)
         array[i] = 0;
 }
 
-#ifdef USE_ZLIB
-class Compressor
-{
-    /* Number of bytes we should hand to zlib each compressMore() call. */
-    static const size_t CHUNKSIZE = 2048;
-    z_stream zs;
-    const unsigned char *inp;
-    size_t inplen;
-    size_t outbytes;
-
-  public:
-    enum Status {
-        MOREOUTPUT,
-        DONE,
-        CONTINUE,
-        OOM
-    };
-
-    Compressor(const unsigned char *inp, size_t inplen);
-    ~Compressor();
-    bool init();
-    void setOutput(unsigned char *out, size_t outlen);
-    size_t outWritten() const { return outbytes; }
-    /* Compress some of the input. Return true if it should be called again. */
-    Status compressMore();
-};
-
-/*
- * Decompress a string. The caller must know the length of the output and
- * allocate |out| to a string of that length.
- */
-bool DecompressString(const unsigned char *inp, size_t inplen,
-                      unsigned char *out, size_t outlen);
-#endif
-
 }  /* namespace js */
 
 /* Crash diagnostics */
 #ifdef DEBUG
 # define JS_CRASH_DIAGNOSTICS 1
 #endif
 #ifdef JS_CRASH_DIAGNOSTICS
 # define JS_POISON(p, val, size) memset((p), (val), (size))
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -364,17 +364,17 @@ JS_NondeterministicGetWeakMapKeys(JSCont
     ObjectValueMap *map = obj->as<WeakMapObject>().getMap();
     if (map) {
         // Prevent GC from mutating the weakmap while iterating.
         gc::AutoSuppressGC suppress(cx);
         for (ObjectValueMap::Base::Range r = map->all(); !r.empty(); r.popFront()) {
             RootedObject key(cx, r.front().key());
             if (!cx->compartment()->wrap(cx, &key))
                 return false;
-            if (!js_NewbornArrayPush(cx, arr, ObjectValue(*key)))
+            if (!NewbornArrayPush(cx, arr, ObjectValue(*key)))
                 return false;
         }
     }
     *ret = arr;
     return true;
 }
 
 static void
--- a/js/src/jsworkers.cpp
+++ b/js/src/jsworkers.cpp
@@ -865,17 +865,17 @@ WorkerThread::handleCompressionWorkload(
     JS_ASSERT(state.canStartCompressionTask());
     JS_ASSERT(idle());
 
     compressionTask = state.compressionWorklist.popCopy();
     compressionTask->workerThread = this;
 
     {
         AutoUnlockWorkerThreadState unlock(runtime);
-        if (!compressionTask->compress())
+        if (!compressionTask->work())
             compressionTask->setOOM();
     }
 
     compressionTask->workerThread = nullptr;
     compressionTask = nullptr;
 
     // Notify the main thread in case it is waiting for the compression to finish.
     state.notifyAll(WorkerThreadState::CONSUMER);
--- a/js/src/jsworkers.h
+++ b/js/src/jsworkers.h
@@ -408,17 +408,17 @@ struct SourceCompressionTask
 #endif
     }
 
     ~SourceCompressionTask()
     {
         complete();
     }
 
-    bool compress();
+    bool work();
     bool complete();
     void abort() { abort_ = 1; }
     bool active() const { return !!ss; }
     ScriptSource *source() { return ss; }
     const jschar *uncompressedChars() { return chars; }
     void setOOM() { oom = true; }
 };
 
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -150,16 +150,17 @@ UNIFIED_SOURCES += [
     'jsweakmap.cpp',
     'jsworkers.cpp',
     'jswrapper.cpp',
     'perf/jsperf.cpp',
     'prmjtime.cpp',
     'vm/ArgumentsObject.cpp',
     'vm/CallNonGenericMethod.cpp',
     'vm/CharacterEncoding.cpp',
+    'vm/Compression.cpp',
     'vm/DateTime.cpp',
     'vm/Debugger.cpp',
     'vm/ErrorObject.cpp',
     'vm/ForkJoin.cpp',
     'vm/GlobalObject.cpp',
     'vm/Id.cpp',
     'vm/Interpreter.cpp',
     'vm/MemoryMetrics.cpp',
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3670,24 +3670,25 @@ NestedShell(JSContext *cx, unsigned argc
     }
 
     args.rval().setUndefined();
     return true;
 }
 
 static bool
 DecompileFunctionSomehow(JSContext *cx, unsigned argc, Value *vp,
-                         JSString *(*decompiler)(JSContext *, JSFunction *, unsigned))
+                         JSString *(*decompiler)(JSContext *, HandleFunction, unsigned))
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() < 1 || !args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
         args.rval().setUndefined();
         return true;
     }
-    JSString *result = decompiler(cx, &args[0].toObject().as<JSFunction>(), 0);
+    RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
+    JSString *result = decompiler(cx, fun, 0);
     if (!result)
         return false;
     args.rval().setString(result);
     return true;
 }
 
 static bool
 DecompileBody(JSContext *cx, unsigned argc, Value *vp)
@@ -4828,52 +4829,52 @@ dom_doFoo(JSContext* cx, HandleObject ob
     args.rval().setInt32(args.length());
     return true;
 }
 
 static const JSJitInfo dom_x_getterinfo = {
     { (JSJitGetterOp)dom_get_x },
     0,        /* protoID */
     0,        /* depth */
+    JSJitInfo::AliasNone, /* aliasSet */
     JSJitInfo::Getter,
     JSVAL_TYPE_UNKNOWN, /* returnType */
     true,     /* isInfallible. False in setters. */
     true,     /* isMovable */
     false,    /* isInSlot */
     false,    /* isTypedMethod */
-    0,        /* slotIndex */
-    JSJitInfo::AliasNone /* aliasSet */
+    0         /* slotIndex */
 };
 
 static const JSJitInfo dom_x_setterinfo = {
     { (JSJitGetterOp)dom_set_x },
     0,        /* protoID */
     0,        /* depth */
     JSJitInfo::Setter,
+    JSJitInfo::AliasEverything, /* aliasSet */
     JSVAL_TYPE_UNKNOWN, /* returnType */
     false,    /* isInfallible. False in setters. */
     false,    /* isMovable. */
     false,    /* isInSlot */
     false,    /* isTypedMethod */
-    0,        /* slotIndex */
-    JSJitInfo::AliasEverything /* aliasSet */
+    0         /* slotIndex */
 };
 
 static const JSJitInfo doFoo_methodinfo = {
     { (JSJitGetterOp)dom_doFoo },
     0,        /* protoID */
     0,        /* depth */
     JSJitInfo::Method,
+    JSJitInfo::AliasEverything, /* aliasSet */
     JSVAL_TYPE_UNKNOWN, /* returnType */
     false,    /* isInfallible. False in setters. */
     false,    /* isMovable */
     false,    /* isInSlot */
     false,    /* isTypedMethod */
-    0,        /* slotIndex */
-    JSJitInfo::AliasEverything /* aliasSet */
+    0         /* slotIndex */
 };
 
 static const JSPropertySpec dom_props[] = {
     {"x", 0,
      JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_NATIVE_ACCESSORS,
      { (JSPropertyOp)dom_genericGetter, &dom_x_getterinfo },
      { (JSStrictPropertyOp)dom_genericSetter, &dom_x_setterinfo }
     },
@@ -4920,17 +4921,17 @@ dom_genericGetter(JSContext *cx, unsigne
     if (JS_GetClass(obj) != &dom_class) {
         args.rval().set(UndefinedValue());
         return true;
     }
 
     JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
 
     const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
-    MOZ_ASSERT(info->type == JSJitInfo::Getter);
+    MOZ_ASSERT(info->type() == JSJitInfo::Getter);
     JSJitGetterOp getter = info->getter;
     return getter(cx, obj, val.toPrivate(), JSJitGetterCallArgs(args));
 }
 
 static bool
 dom_genericSetter(JSContext* cx, unsigned argc, JS::Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
@@ -4943,17 +4944,17 @@ dom_genericSetter(JSContext* cx, unsigne
     if (JS_GetClass(obj) != &dom_class) {
         args.rval().set(UndefinedValue());
         return true;
     }
 
     JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
 
     const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
-    MOZ_ASSERT(info->type == JSJitInfo::Setter);
+    MOZ_ASSERT(info->type() == JSJitInfo::Setter);
     JSJitSetterOp setter = info->setter;
     if (!setter(cx, obj, val.toPrivate(), JSJitSetterCallArgs(args)))
         return false;
     args.rval().set(UndefinedValue());
     return true;
 }
 
 static bool
@@ -4967,17 +4968,17 @@ dom_genericMethod(JSContext* cx, unsigne
     if (JS_GetClass(obj) != &dom_class) {
         args.rval().set(UndefinedValue());
         return true;
     }
 
     JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
 
     const JSJitInfo *info = FUNCTION_VALUE_TO_JITINFO(JS_CALLEE(cx, vp));
-    MOZ_ASSERT(info->type == JSJitInfo::Method);
+    MOZ_ASSERT(info->type() == JSJitInfo::Method);
     JSJitMethodOp method = info->method;
     return method(cx, obj, val.toPrivate(), JSJitMethodCallArgs(args));
 }
 
 static void
 InitDOMObject(HandleObject obj)
 {
     /* Fow now just initialize to a constant we can check. */
--- a/js/src/vm/ArrayObject.h
+++ b/js/src/vm/ArrayObject.h
@@ -9,16 +9,19 @@
 
 #include "jsobj.h"
 
 namespace js {
 
 class ArrayObject : public JSObject
 {
   public:
+    // Array(x) eagerly allocates dense elements if x <= this value.
+    static const uint32_t EagerAllocationMaxLength = 2048;
+
     static const Class class_;
 
     bool lengthIsWritable() const {
         return !getElementsHeader()->hasNonwritableArrayLength();
     }
 
     uint32_t length() const {
         return getElementsHeader()->length;
new file mode 100644
--- /dev/null
+++ b/js/src/vm/Compression.cpp
@@ -0,0 +1,127 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "vm/Compression.h"
+
+#include "js/Utility.h"
+
+using namespace js;
+
+#if USE_ZLIB
+static void *
+zlib_alloc(void *cx, uInt items, uInt size)
+{
+    return js_calloc(items, size);
+}
+
+static void
+zlib_free(void *cx, void *addr)
+{
+    js_free(addr);
+}
+
+Compressor::Compressor(const unsigned char *inp, size_t inplen)
+    : inp(inp),
+      inplen(inplen),
+      outbytes(0)
+{
+    JS_ASSERT(inplen > 0);
+    zs.opaque = nullptr;
+    zs.next_in = (Bytef *)inp;
+    zs.avail_in = 0;
+    zs.next_out = nullptr;
+    zs.avail_out = 0;
+    zs.zalloc = zlib_alloc;
+    zs.zfree = zlib_free;
+}
+
+
+Compressor::~Compressor()
+{
+    int ret = deflateEnd(&zs);
+    if (ret != Z_OK) {
+        // If we finished early, we can get a Z_DATA_ERROR.
+        JS_ASSERT(ret == Z_DATA_ERROR);
+        JS_ASSERT(uInt(zs.next_in - inp) < inplen || !zs.avail_out);
+    }
+}
+
+bool
+Compressor::init()
+{
+    if (inplen >= UINT32_MAX)
+        return false;
+    // zlib is slow and we'd rather be done compression sooner
+    // even if it means decompression is slower which penalizes
+    // Function.toString()
+    int ret = deflateInit(&zs, Z_BEST_SPEED);
+    if (ret != Z_OK) {
+        JS_ASSERT(ret == Z_MEM_ERROR);
+        return false;
+    }
+    return true;
+}
+
+void
+Compressor::setOutput(unsigned char *out, size_t outlen)
+{
+    JS_ASSERT(outlen > outbytes);
+    zs.next_out = out + outbytes;
+    zs.avail_out = outlen - outbytes;
+}
+
+Compressor::Status
+Compressor::compressMore()
+{
+    JS_ASSERT(zs.next_out);
+    uInt left = inplen - (zs.next_in - inp);
+    bool done = left <= CHUNKSIZE;
+    if (done)
+        zs.avail_in = left;
+    else if (zs.avail_in == 0)
+        zs.avail_in = CHUNKSIZE;
+    Bytef *oldout = zs.next_out;
+    int ret = deflate(&zs, done ? Z_FINISH : Z_NO_FLUSH);
+    outbytes += zs.next_out - oldout;
+    if (ret == Z_MEM_ERROR) {
+        zs.avail_out = 0;
+        return OOM;
+    }
+    if (ret == Z_BUF_ERROR || (done && ret == Z_OK)) {
+        JS_ASSERT(zs.avail_out == 0);
+        return MOREOUTPUT;
+    }
+    JS_ASSERT_IF(!done, ret == Z_OK);
+    JS_ASSERT_IF(done, ret == Z_STREAM_END);
+    return done ? DONE : CONTINUE;
+}
+
+bool
+js::DecompressString(const unsigned char *inp, size_t inplen, unsigned char *out, size_t outlen)
+{
+    JS_ASSERT(inplen <= UINT32_MAX);
+    z_stream zs;
+    zs.zalloc = zlib_alloc;
+    zs.zfree = zlib_free;
+    zs.opaque = nullptr;
+    zs.next_in = (Bytef *)inp;
+    zs.avail_in = inplen;
+    zs.next_out = out;
+    JS_ASSERT(outlen);
+    zs.avail_out = outlen;
+    int ret = inflateInit(&zs);
+    if (ret != Z_OK) {
+        JS_ASSERT(ret == Z_MEM_ERROR);
+        return false;
+    }
+    ret = inflate(&zs, Z_FINISH);
+    JS_ASSERT(ret == Z_STREAM_END);
+    ret = inflateEnd(&zs);
+    JS_ASSERT(ret == Z_OK);
+    return true;
+}
+#endif /* USE_ZLIB */
+
new file mode 100644
--- /dev/null
+++ b/js/src/vm/Compression.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef vm_Compression_h
+#define vm_Compression_h
+
+#ifdef USE_ZLIB
+
+#include <zlib.h>
+
+#include "jstypes.h"
+
+namespace js {
+
+class Compressor
+{
+    /* Number of bytes we should hand to zlib each compressMore() call. */
+    static const size_t CHUNKSIZE = 2048;
+    z_stream zs;
+    const unsigned char *inp;
+    size_t inplen;
+    size_t outbytes;
+
+  public:
+    enum Status {
+        MOREOUTPUT,
+        DONE,
+        CONTINUE,
+        OOM
+    };
+
+    Compressor(const unsigned char *inp, size_t inplen);
+    ~Compressor();
+    bool init();
+    void setOutput(unsigned char *out, size_t outlen);
+    size_t outWritten() const { return outbytes; }
+    /* Compress some of the input. Return true if it should be called again. */
+    Status compressMore();
+};
+
+/*
+ * Decompress a string. The caller must know the length of the output and
+ * allocate |out| to a string of that length.
+ */
+bool DecompressString(const unsigned char *inp, size_t inplen,
+                      unsigned char *out, size_t outlen);
+
+} /* namespace js */
+
+#endif /* USE_ZLIB */
+#endif /* vm_Compression_h */
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -2732,17 +2732,17 @@ Debugger::findAllGlobals(JSContext *cx, 
              * marked gray by XPConnect. Since we're now exposing it to JS code,
              * we need to mark it black.
              */
             JS::ExposeGCThingToActiveJS(global, JSTRACE_OBJECT);
 
             RootedValue globalValue(cx, ObjectValue(*global));
             if (!dbg->wrapDebuggeeValue(cx, &globalValue))
                 return false;
-            if (!js_NewbornArrayPush(cx, result, globalValue))
+            if (!NewbornArrayPush(cx, result, globalValue))
                 return false;
         }
     }
 
     args.rval().setObject(*result);
     return true;
 }
 
@@ -3023,17 +3023,17 @@ DebuggerScript_getChildScripts(JSContext
         for (uint32_t i = script->innerObjectsStart(); i < objects->length; i++) {
             obj = objects->vector[i];
             if (obj->is<JSFunction>()) {
                 fun = &obj->as<JSFunction>();
                 funScript = GetOrCreateFunctionScript(cx, fun);
                 if (!funScript)
                     return false;
                 s = dbg->wrapScript(cx, funScript);
-                if (!s || !js_NewbornArrayPush(cx, result, ObjectValue(*s)))
+                if (!s || !NewbornArrayPush(cx, result, ObjectValue(*s)))
                     return false;
             }
         }
     }
     args.rval().setObject(*result);
     return true;
 }
 
@@ -3355,17 +3355,17 @@ DebuggerScript_getAllOffsets(JSContext *
                 }
 
                 RootedValue value(cx, ObjectValue(*offsets));
                 if (!JSObject::defineGeneric(cx, result, id, value))
                     return false;
             }
 
             /* Append the current offset to the offsets array. */
-            if (!js_NewbornArrayPush(cx, offsets, NumberValue(offset)))
+            if (!NewbornArrayPush(cx, offsets, NumberValue(offset)))
                 return false;
         }
     }
 
     args.rval().setObject(*result);
     return true;
 }
 
@@ -3408,17 +3408,17 @@ DebuggerScript_getAllColumnOffsets(JSCon
             if (!JSObject::defineProperty(cx, entry, cx->names().columnNumber, value))
                 return false;
 
             id = NameToId(cx->names().offset);
             value = NumberValue(offset);
             if (!JSObject::defineGeneric(cx, entry, id, value))
                 return false;
 
-            if (!js_NewbornArrayPush(cx, result, ObjectValue(*entry)))
+            if (!NewbornArrayPush(cx, result, ObjectValue(*entry)))
                 return false;
         }
     }
 
     args.rval().setObject(*result);
     return true;
 }
 
@@ -3457,17 +3457,17 @@ DebuggerScript_getLineOffsets(JSContext 
     for (BytecodeRangeWithPosition r(cx, script); !r.empty(); r.popFront()) {
         size_t offset = r.frontOffset();
 
         /* If the op at offset is an entry point, append offset to result. */
         if (r.frontLineNumber() == lineno &&
             !flowData[offset].hasNoEdges() &&
             flowData[offset].lineno() != lineno)
         {
-            if (!js_NewbornArrayPush(cx, result, NumberValue(offset)))
+            if (!NewbornArrayPush(cx, result, NumberValue(offset)))
                 return false;
         }
     }
 
     args.rval().setObject(*result);
     return true;
 }
 
@@ -3570,17 +3570,17 @@ DebuggerScript_getBreakpoints(JSContext 
     if (!arr)
         return false;
 
     for (unsigned i = 0; i < script->length(); i++) {
         BreakpointSite *site = script->getBreakpointSite(script->offsetToPC(i));
         if (site && (!pc || site->pc == pc)) {
             for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = bp->nextInSite()) {
                 if (bp->debugger == dbg &&
-                    !js_NewbornArrayPush(cx, arr, ObjectValue(*bp->getHandler())))
+                    !NewbornArrayPush(cx, arr, ObjectValue(*bp->getHandler())))
                 {
                     return false;
                 }
             }
         }
     }
     args.rval().setObject(*arr);
     return true;
@@ -5644,17 +5644,17 @@ DebuggerEnv_names(JSContext *cx, unsigne
     if (!arr)
         return false;
     RootedId id(cx);
     for (size_t i = 0, len = keys.length(); i < len; i++) {
         id = keys[i];
         if (JSID_IS_ATOM(id) && IsIdentifier(JSID_TO_ATOM(id))) {
             if (!cx->compartment()->wrapId(cx, id.address()))
                 return false;
-            if (!js_NewbornArrayPush(cx, arr, StringValue(JSID_TO_STRING(id))))
+            if (!NewbornArrayPush(cx, arr, StringValue(JSID_TO_STRING(id))))
                 return false;
         }
     }
     args.rval().setObject(*arr);
     return true;
 }
 
 static bool
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -3390,24 +3390,21 @@ CASE(JSOP_YIELD)
     REGS.fp()->setReturnValue(REGS.sp[-1]);
     REGS.fp()->setYielding();
     REGS.pc += JSOP_YIELD_LENGTH;
     interpReturnOK = true;
     goto exit;
 
 CASE(JSOP_ARRAYPUSH)
 {
-    uint32_t slot = GET_LOCALNO(REGS.pc);
-    JS_ASSERT(script->nfixed() <= slot);
-    JS_ASSERT(slot < script->nslots());
     RootedObject &obj = rootObject0;
-    obj = &REGS.fp()->unaliasedLocal(slot).toObject();
-    if (!js_NewbornArrayPush(cx, obj, REGS.sp[-1]))
+    obj = &REGS.sp[-1].toObject();
+    if (!NewbornArrayPush(cx, obj, REGS.sp[-2]))
         goto error;
-    REGS.sp--;
+    REGS.sp -= 2;
 }
 END_CASE(JSOP_ARRAYPUSH)
 
 DEFAULT()
 {
     char numBuf[12];
     JS_snprintf(numBuf, sizeof numBuf, "%d", *REGS.pc);
     JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -12,16 +12,17 @@
 #include "jshashutil.h"
 #include "jsobj.h"
 #include "jswrapper.h"
 #include "selfhosted.out.h"
 
 #include "builtin/Intl.h"
 #include "builtin/TypedObject.h"
 #include "gc/Marking.h"
+#include "vm/Compression.h"
 #include "vm/ForkJoin.h"
 #include "vm/Interpreter.h"
 
 #include "jsfuninlines.h"
 #include "jsscriptinlines.h"
 
 #include "vm/BooleanObject-inl.h"
 #include "vm/NumberObject-inl.h"
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -17,17 +17,17 @@ namespace js {
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number is XDR'd near the front of xdr bytecode and
  * aborts deserialization if there is a mismatch between the current
  * and saved versions. If deserialization fails, the data should be
  * invalidated if possible.
  */
-static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 162);
+static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 163);
 
 class XDRBuffer {
   public:
     XDRBuffer(JSContext *cx)
       : context(cx), base(nullptr), cursor(nullptr), limit(nullptr) { }
 
     JSContext *cx() const {
         return context;
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -1290,17 +1290,17 @@ mozJSComponentLoader::ImportInto(const n
         nsAutoCString logBuffer;
 #endif
 
         RootedValue value(mContext);
         RootedId symbolId(mContext);
         for (uint32_t i = 0; i < symbolCount; ++i) {
             if (!JS_GetElement(mContext, symbolsObj, i, &value) ||
                 !value.isString() ||
-                !JS_ValueToId(mContext, value, symbolId.address())) {
+                !JS_ValueToId(mContext, value, &symbolId)) {
                 return ReportOnCaller(cxhelper, ERROR_ARRAY_ELEMENT,
                                       PromiseFlatCString(aLocation).get(), i);
             }
 
             if (!JS_GetPropertyById(mContext, mod->obj, symbolId, &value)) {
                 JSAutoByteString bytes(mContext, JSID_TO_STRING(symbolId));
                 if (!bytes)
                     return NS_ERROR_FAILURE;
--- a/js/xpconnect/src/Sandbox.cpp
+++ b/js/xpconnect/src/Sandbox.cpp
@@ -165,17 +165,17 @@ SandboxImport(JSContext *cx, unsigned ar
         funname = JS_GetFunctionId(fun);
         if (!funname) {
             XPCThrower::Throw(NS_ERROR_INVALID_ARG, cx);
             return false;
         }
     }
 
     RootedId id(cx);
-    if (!JS_ValueToId(cx, StringValue(funname), id.address()))
+    if (!JS_ValueToId(cx, StringValue(funname), &id))
         return false;
 
     // We need to resolve the this object, because this function is used
     // unbound and should still work and act on the original sandbox.
     RootedObject thisObject(cx, JS_THIS_OBJECT(cx, vp));
     if (!thisObject) {
         XPCThrower::Throw(NS_ERROR_UNEXPECTED, cx);
         return false;
@@ -289,17 +289,17 @@ ExportFunction(JSContext *cx, HandleValu
             // copy the name from the function being imported.
             JSFunction *fun = JS_GetObjectFunction(funObj);
             RootedString funName(cx, JS_GetFunctionId(fun));
             if (!funName)
                 funName = JS_InternString(cx, "");
 
             RootedValue vname(cx);
             vname.setString(funName);
-            if (!JS_ValueToId(cx, vname, id.address()))
+            if (!JS_ValueToId(cx, vname, &id))
                 return false;
         }
         MOZ_ASSERT(JSID_IS_STRING(id));
 
         // The function forwarder will live in the target compartment. Since
         // this function will be referenced from its private slot, to avoid a
         // GC hazard, we must wrap it to the same compartment.
         if (!JS_WrapObject(cx, &funObj))
@@ -1442,17 +1442,17 @@ OptionsBase::ParseId(const char *name, M
     RootedValue value(mCx);
     bool found;
     bool ok = ParseValue(name, &value, &found);
     NS_ENSURE_TRUE(ok, false);
 
     if (!found)
         return true;
 
-    return JS_ValueToId(mCx, value, prop.address());
+    return JS_ValueToId(mCx, value, prop);
 }
 
 /*
  * Helper that tries to get a list of DOM constructors and other helpers from the options object.
  */
 bool
 SandboxOptions::ParseGlobalProperties()
 {
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -258,19 +258,21 @@ nsXPCComponents_Interfaces::NewEnumerate
             uint32_t idx = JSVAL_TO_INT(*statep);
             nsIInterfaceInfo* interface = mInterfaces.SafeElementAt(idx);
             *statep = UINT_TO_JSVAL(idx + 1);
 
             if (interface) {
                 JSString* idstr;
                 const char* name;
 
+                JS::Rooted<jsid> id(cx);
                 if (NS_SUCCEEDED(interface->GetNameShared(&name)) && name &&
                         nullptr != (idstr = JS_NewStringCopyZ(cx, name)) &&
-                        JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp)) {
+                        JS_ValueToId(cx, StringValue(idstr), &id)) {
+                    *idp = id;
                     return NS_OK;
                 }
             }
             // fall through
         }
 
         case JSENUMERATE_DESTROY:
         default:
@@ -507,17 +509,19 @@ nsXPCComponents_InterfacesByID::NewEnume
             if (interface) {
                 nsIID const *iid;
                 char idstr[NSID_LENGTH];
                 JSString* jsstr;
 
                 if (NS_SUCCEEDED(interface->GetIIDShared(&iid))) {
                     iid->ToProvidedString(idstr);
                     jsstr = JS_NewStringCopyZ(cx, idstr);
-                    if (jsstr && JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp)) {
+                    JS::Rooted<jsid> id(cx);
+                    if (jsstr && JS_ValueToId(cx, StringValue(jsstr), &id)) {
+                        *idp = id;
                         return NS_OK;
                     }
                 }
             }
             // FALL THROUGH
         }
 
         case JSENUMERATE_DESTROY:
@@ -761,18 +765,20 @@ nsXPCComponents_Classes::NewEnumerate(ns
 
             if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
                 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
                 nsCOMPtr<nsISupportsCString> holder(do_QueryInterface(isup));
                 if (holder) {
                     nsAutoCString name;
                     if (NS_SUCCEEDED(holder->GetData(name))) {
                         JSString* idstr = JS_NewStringCopyN(cx, name.get(), name.Length());
+                        JS::Rooted<jsid> id(cx);
                         if (idstr &&
-                            JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp)) {
+                            JS_ValueToId(cx, StringValue(idstr), &id)) {
+                            *idp = id;
                             return NS_OK;
                         }
                     }
                 }
             }
             // else... FALL THROUGH
         }
 
@@ -1001,18 +1007,20 @@ nsXPCComponents_ClassesByID::NewEnumerat
             if (NS_SUCCEEDED(e->HasMoreElements(&hasMore)) && hasMore &&
                 NS_SUCCEEDED(e->GetNext(getter_AddRefs(isup))) && isup) {
                 nsCOMPtr<nsISupportsID> holder(do_QueryInterface(isup));
                 if (holder) {
                     char* name;
                     if (NS_SUCCEEDED(holder->ToString(&name)) && name) {
                         JSString* idstr = JS_NewStringCopyZ(cx, name);
                         nsMemory::Free(name);
+                        JS::Rooted<jsid> id(cx);
                         if (idstr &&
-                            JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp)) {
+                            JS_ValueToId(cx, StringValue(idstr), &id)) {
+                            *idp = id;
                             return NS_OK;
                         }
                     }
                 }
             }
             // else... FALL THROUGH
         }
 
@@ -1253,18 +1261,21 @@ nsXPCComponents_Results::NewEnumerate(ns
             return NS_OK;
         }
         case JSENUMERATE_NEXT:
         {
             const char* name;
             iter = (const void**) JSVAL_TO_PRIVATE(*statep);
             if (nsXPCException::IterateNSResults(nullptr, &name, nullptr, iter)) {
                 JSString* idstr = JS_NewStringCopyZ(cx, name);
-                if (idstr && JS_ValueToId(cx, STRING_TO_JSVAL(idstr), idp))
+                JS::Rooted<jsid> id(cx);
+                if (idstr && JS_ValueToId(cx, StringValue(idstr), &id)) {
+                    *idp = id;
                     return NS_OK;
+                }
             }
             // else... FALL THROUGH
         }
 
         case JSENUMERATE_DESTROY:
         default:
             iter = (const void**) JSVAL_TO_PRIVATE(*statep);
             delete [] (char*) iter;
@@ -2394,17 +2405,17 @@ nsXPCComponents_Constructor::CallOrConst
                                       getter_AddRefs(holder))) || !holder ||
             // Assign, not compare
             !(ifacesObj = holder->GetJSObject())) {
             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
         }
 
         RootedString str(cx, ToString(cx, args[1]));
         RootedId id(cx);
-        if (!str || !JS_ValueToId(cx, StringValue(str), id.address()))
+        if (!str || !JS_ValueToId(cx, StringValue(str), &id))
             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
         RootedValue val(cx);
         if (!JS_GetPropertyById(cx, ifacesObj, id, &val) || val.isPrimitive())
             return ThrowAndFail(NS_ERROR_XPC_BAD_IID, cx, _retval);
 
         nsCOMPtr<nsIXPConnectWrappedNative> wn;
         if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, &val.toObject(),
@@ -2442,17 +2453,17 @@ nsXPCComponents_Constructor::CallOrConst
                                       getter_AddRefs(holder))) || !holder ||
             // Assign, not compare
             !(classesObj = holder->GetJSObject())) {
             return ThrowAndFail(NS_ERROR_XPC_UNEXPECTED, cx, _retval);
         }
 
         RootedString str(cx, ToString(cx, args[0]));
         RootedId id(cx);
-        if (!str || !JS_ValueToId(cx, StringValue(str), id.address()))
+        if (!str || !JS_ValueToId(cx, StringValue(str), &id))
             return ThrowAndFail(NS_ERROR_XPC_BAD_CONVERT_JS, cx, _retval);
 
         RootedValue val(cx);
         if (!JS_GetPropertyById(cx, classesObj, id, &val) || val.isPrimitive())
             return ThrowAndFail(NS_ERROR_XPC_BAD_CID, cx, _retval);
 
         nsCOMPtr<nsIXPConnectWrappedNative> wn;
         if (NS_FAILED(xpc->GetWrappedNativeOfJSObject(cx, JSVAL_TO_OBJECT(val),
--- a/js/xpconnect/src/XPCQuickStubs.h
+++ b/js/xpconnect/src/XPCQuickStubs.h
@@ -605,17 +605,17 @@ PropertyOpForwarder(JSContext *cx, unsig
 
     JSObject *ptrobj = JSVAL_TO_OBJECT(v);
     Op *popp = static_cast<Op *>(JS_GetPrivate(ptrobj));
 
     v = js::GetFunctionNativeReserved(callee, 1);
 
     JS::RootedValue argval(cx, (argc > 0) ? args.get(0) : JSVAL_VOID);
     JS::RootedId id(cx);
-    if (!JS_ValueToId(cx, v, id.address()))
+    if (!JS_ValueToId(cx, v, &id))
         return false;
     args.rval().set(argval);
     return ApplyPropertyOp<Op>(cx, *popp, obj, id, args.rval());
 }
 
 extern const JSClass PointerHolderClass;
 
 template<typename Op>
--- a/js/xpconnect/src/XPCShellImpl.cpp
+++ b/js/xpconnect/src/XPCShellImpl.cpp
@@ -726,17 +726,17 @@ env_setProperty(JSContext *cx, HandleObj
 {
 /* XXX porting may be easy, but these don't seem to supply setenv by default */
 #if !defined XP_OS2 && !defined SOLARIS
     JSString *valstr;
     JS::Rooted<JSString*> idstr(cx);
     int rv;
 
     RootedValue idval(cx);
-    if (!JS_IdToValue(cx, id, idval.address()))
+    if (!JS_IdToValue(cx, id, &idval))
         return false;
 
     idstr = ToString(cx, idval);
     valstr = ToString(cx, vp);
     if (!idstr || !valstr)
         return false;
     JSAutoByteString name(cx, idstr);
     if (!name)
@@ -809,17 +809,17 @@ env_enumerate(JSContext *cx, HandleObjec
 
 static bool
 env_resolve(JSContext *cx, HandleObject obj, HandleId id, unsigned flags,
             JS::MutableHandleObject objp)
 {
     JSString *idstr, *valstr;
 
     RootedValue idval(cx);
-    if (!JS_IdToValue(cx, id, idval.address()))
+    if (!JS_IdToValue(cx, id, &idval))
         return false;
 
     idstr = ToString(cx, idval);
     if (!idstr)
         return false;
     JSAutoByteString name(cx, idstr);
     if (!name)
         return false;
--- a/js/xpconnect/src/XPCWrappedJSClass.cpp
+++ b/js/xpconnect/src/XPCWrappedJSClass.cpp
@@ -330,17 +330,17 @@ nsXPCWrappedJSClass::GetNamedPropertyAsV
     RootedValue value(cx);
     if (!XPCStringConvert::ReadableToJSVal(ccx, aName, &buf, &value))
         return NS_ERROR_OUT_OF_MEMORY;
     if (buf)
         buf->AddRef();
 
     RootedId id(cx);
     nsresult rv = NS_OK;
-    if (!JS_ValueToId(cx, value, id.address()) ||
+    if (!JS_ValueToId(cx, value, &id) ||
         !GetNamedPropertyAsVariantRaw(ccx, aJSObj, id, aResult, &rv)) {
         if (NS_FAILED(rv))
             return rv;
         return NS_ERROR_FAILURE;
     }
     return NS_OK;
 }
 
@@ -373,17 +373,17 @@ nsXPCWrappedJSClass::BuildPropertyEnumer
         if (!GetNamedPropertyAsVariantRaw(ccx, aJSObj, idName,
                                           getter_AddRefs(value), &rv)) {
             if (NS_FAILED(rv))
                 return rv;
             return NS_ERROR_FAILURE;
         }
 
         RootedValue jsvalName(cx);
-        if (!JS_IdToValue(cx, idName, jsvalName.address()))
+        if (!JS_IdToValue(cx, idName, &jsvalName))
             return NS_ERROR_FAILURE;
 
         JSString* name = ToString(cx, jsvalName);
         if (!name)
             return NS_ERROR_FAILURE;
 
         size_t length;
         const jschar *chars = JS_GetStringCharsAndLength(cx, name, &length);
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3813,18 +3813,19 @@ ContainerState::SetupMaskLayer(Layer *aL
 
     // build the image and container
     container = aLayer->Manager()->CreateImageContainer();
     NS_ASSERTION(container, "Could not create image container for mask layer.");
     static const ImageFormat format = CAIRO_SURFACE;
     nsRefPtr<Image> image = container->CreateImage(&format, 1);
     NS_ASSERTION(image, "Could not create image container for mask layer.");
     CairoImage::Data data;
-    data.mSurface = surface;
+    data.mDeprecatedSurface = surface;
     data.mSize = surfaceSizeInt;
+    data.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface);
     static_cast<CairoImage*>(image.get())->SetData(data);
     container->SetCurrentImageInTransaction(image);
 
     GetMaskLayerImageCache()->PutImage(newKey.forget(), container);
   }
 
   maskLayer->SetContainer(container);
 
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -618,17 +618,21 @@ RestyleManager::ProcessRestyledFrames(ns
       frame = nullptr;
       if (!(hint & nsChangeHint_ReconstructFrame)) {
         continue;
       }
     }
 
     if ((hint & nsChangeHint_AddOrRemoveTransform) && frame &&
         !(hint & nsChangeHint_ReconstructFrame)) {
-      if (NeedToReframeForAddingOrRemovingTransform(frame)) {
+      if (NeedToReframeForAddingOrRemovingTransform(frame) ||
+          frame->GetType() == nsGkAtoms::fieldSetFrame ||
+          frame->GetContentInsertionFrame() != frame) {
+        // The frame has positioned children that need to be reparented, or
+        // it can't easily be converted to/from being an abs-pos container correctly.
         NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
       } else {
         for (nsIFrame *cont = frame; cont;
              cont = nsLayoutUtils::GetNextContinuationOrSpecialSibling(cont)) {
           // Normally frame construction would set state bits as needed,
           // but we're not going to reconstruct the frame so we need to set them.
           // It's because we need to set this state on each affected frame
           // that we can't coalesce nsChangeHint_AddOrRemoveTransform hints up
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -63,16 +63,17 @@
 #include "nsTArray.h"
 #include "nsGenericDOMDataNode.h"
 #include "mozilla/dom/Element.h"
 #include "nsAutoLayoutPhase.h"
 #include "nsStyleStructInlines.h"
 #include "nsPageContentFrame.h"
 #include "RestyleManager.h"
 #include "StickyScrollContainer.h"
+#include "nsFieldSetFrame.h"
 
 #ifdef MOZ_XUL
 #include "nsIRootBox.h"
 #endif
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
@@ -5645,31 +5646,42 @@ nsCSSFrameConstructor::GetAbsoluteContai
     // scrolledframe might be.  So, we need to check this special case to return
     // the correct containing block (the scrolledframe) in that case.
     // If we're looking for a fixed-pos containing block and the frame is
     // not transformed, skip it.
     if (!frame->IsPositioned() ||
         (aType == FIXED_POS && !frame->StyleDisplay()->HasTransform(frame))) {
       continue;
     }
-    nsIFrame* absPosCBCandidate = nullptr;
-    if (frame->GetType() == nsGkAtoms::scrollFrame) {
-      nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
+    nsIFrame* absPosCBCandidate = frame;
+    nsIAtom* type = absPosCBCandidate->GetType();
+    if (type == nsGkAtoms::fieldSetFrame) {
+      absPosCBCandidate = static_cast<nsFieldSetFrame*>(absPosCBCandidate)->GetInner();
+      if (!absPosCBCandidate) {
+        continue;
+      }
+      type = absPosCBCandidate->GetType();
+    }
+    if (type == nsGkAtoms::scrollFrame) {
+      nsIScrollableFrame* scrollFrame = do_QueryFrame(absPosCBCandidate);
       absPosCBCandidate = scrollFrame->GetScrolledFrame();
-    } else {
-      // Only first continuations can be containing blocks.
-      absPosCBCandidate = frame->FirstContinuation();
-    }
+      if (!absPosCBCandidate) {
+        continue;
+      }
+      type = absPosCBCandidate->GetType();
+    }
+    // Only first continuations can be containing blocks.
+    absPosCBCandidate = absPosCBCandidate->FirstContinuation();
     // Is the frame really an absolute container?
-    if (!absPosCBCandidate || !absPosCBCandidate->IsAbsoluteContainer()) {
+    if (!absPosCBCandidate->IsAbsoluteContainer()) {
       continue;
     }
 
     // For tables, skip the inner frame and consider the outer table frame.
-    if (absPosCBCandidate->GetType() == nsGkAtoms::tableFrame) {
+    if (type == nsGkAtoms::tableFrame) {
       continue;
     }
     // For outer table frames, we can just return absPosCBCandidate.
     return absPosCBCandidate;
   }
 
   // It is possible for the search for the containing block to fail, because
   // no absolute container can be found in the parent chain.  In those cases,
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -1730,16 +1730,22 @@ DrawBackgroundColor(BackgroundClipState&
 
 nscolor
 nsCSSRendering::DetermineBackgroundColor(nsPresContext* aPresContext,
                                          nsStyleContext* aStyleContext,
                                          nsIFrame* aFrame,
                                          bool& aDrawBackgroundImage,
                                          bool& aDrawBackgroundColor)
 {
+  if (aFrame->IsThemed()) {
+    aDrawBackgroundColor = false;
+    aDrawBackgroundImage = false;
+    return NS_RGBA(0,0,0,0);
+  }
+
   aDrawBackgroundImage = true;
   aDrawBackgroundColor = true;
 
   if (aFrame->HonorPrintBackgroundSettings()) {
     aDrawBackgroundImage = aPresContext->GetBackgroundImageDraw();
     aDrawBackgroundColor = aPresContext->GetBackgroundColorDraw();
   }
 
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1050,17 +1050,18 @@ nsPresContext::Init(nsDeviceContext* aDe
 
     if (!mRefreshDriver) {
       mRefreshDriver = new nsRefreshDriver(this);
     }
   }
 
   // Initialise refresh tick counters for OMTA
   mLastStyleUpdateForAllAnimations =
-    mLastUpdateThrottledStyle = mRefreshDriver->MostRecentRefresh();
+    mLastUpdateThrottledAnimationStyle =
+    mLastUpdateThrottledTransitionStyle = mRefreshDriver->MostRecentRefresh();
 
   mLangService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
 
   // Register callbacks so we're notified when the preferences change
   Preferences::RegisterCallback(nsPresContext::PrefChangedCallback,
                                 "font.",
                                 this);
   Preferences::RegisterCallback(nsPresContext::PrefChangedCallback,
@@ -1574,25 +1575,39 @@ nsPresContext::GetContainerWeakExternal(
 
 nsIDocShell*
 nsPresContext::GetDocShell() const
 {
   return mContainer;
 }
 
 bool
-nsPresContext::ThrottledStyleIsUpToDate() const
+nsPresContext::ThrottledTransitionStyleIsUpToDate() const
 {
-  return mLastUpdateThrottledStyle == mRefreshDriver->MostRecentRefresh();
+  return
+    mLastUpdateThrottledTransitionStyle == mRefreshDriver->MostRecentRefresh();
 }
 
 void
-nsPresContext::TickLastUpdateThrottledStyle()
+nsPresContext::TickLastUpdateThrottledTransitionStyle()
+{
+  mLastUpdateThrottledTransitionStyle = mRefreshDriver->MostRecentRefresh();
+}
+
+bool
+nsPresContext::ThrottledAnimationStyleIsUpToDate() const
 {
-  mLastUpdateThrottledStyle = mRefreshDriver->MostRecentRefresh();
+  return
+    mLastUpdateThrottledAnimationStyle == mRefreshDriver->MostRecentRefresh();
+}
+
+void
+nsPresContext::TickLastUpdateThrottledAnimationStyle()
+{
+  mLastUpdateThrottledAnimationStyle = mRefreshDriver->MostRecentRefresh();
 }
 
 bool
 nsPresContext::StyleUpdateForAllAnimationsIsUpToDate()
 {
   return mLastStyleUpdateForAllAnimations == mRefreshDriver->MostRecentRefresh();
 }
 
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -659,18 +659,20 @@ public:
   void   SetBackgroundColorDraw(bool aCanDraw)
   {
     mDrawColorBackground = aCanDraw;
   }
   
   /**
    * Getter and setter for OMTA time counters
    */
-  bool ThrottledStyleIsUpToDate() const;
-  void TickLastUpdateThrottledStyle();
+  bool ThrottledTransitionStyleIsUpToDate() const;
+  void TickLastUpdateThrottledTransitionStyle();
+  bool ThrottledAnimationStyleIsUpToDate() const;
+  void TickLastUpdateThrottledAnimationStyle();
   bool StyleUpdateForAllAnimationsIsUpToDate();
   void TickLastStyleUpdateForAllAnimations();
 
 #ifdef IBMBIDI
   /**
    *  Check if bidi enabled (set depending on the presence of RTL
    *  characters or when default directionality is RTL).
    *  If enabled, we should apply the Unicode Bidi Algorithm
@@ -1235,18 +1237,20 @@ protected:
   LangGroupFontPrefs    mLangGroupFontPrefs;
 
   nscoord               mBorderWidthTable[3];
 
   uint32_t              mInterruptChecksToSkip;
 
   mozilla::TimeStamp    mReflowStartTime;
 
-  // last time animations/transition styles were flushed to their primary frames
-  mozilla::TimeStamp    mLastUpdateThrottledStyle;
+  // last time animations styles were flushed to their primary frames
+  mozilla::TimeStamp    mLastUpdateThrottledAnimationStyle;
+  // last time transition styles were flushed to their primary frames
+  mozilla::TimeStamp    mLastUpdateThrottledTransitionStyle;
   // last time we did a full style flush
   mozilla::TimeStamp    mLastStyleUpdateForAllAnimations;
 
   unsigned              mHasPendingInterrupt : 1;
   unsigned              mInterruptsEnabled : 1;
   unsigned              mUseDocumentFonts : 1;
   unsigned              mUseDocumentColors : 1;
   unsigned              mUnderlineLinks : 1;
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -6198,16 +6198,31 @@ nsIFrame* GetNearestFrameContainingPresS
   nsIFrame* frame = nullptr;
   if (view) {
     frame = view->GetFrame();
   }
 
   return frame;
 }
 
+static bool
+FlushThrottledStyles(nsIDocument *aDocument, void *aData)
+{
+  nsIPresShell* shell = aDocument->GetShell();
+  if (shell && shell->IsVisible()) {
+    nsPresContext* presContext = shell->GetPresContext();
+    if (presContext) {
+      presContext->TransitionManager()->UpdateAllThrottledStyles();
+      presContext->AnimationManager()->UpdateAllThrottledStyles();
+    }
+  }
+
+  return true;
+}
+
 nsresult
 PresShell::HandleEvent(nsIFrame* aFrame,
                        WidgetGUIEvent* aEvent,
                        bool aDontRetargetEvents,
                        nsEventStatus* aEventStatus)
 {
   NS_ASSERTION(aFrame, "null frame");
 
@@ -6294,24 +6309,31 @@ PresShell::HandleEvent(nsIFrame* aFrame,
         delete event;
       }
     }
     return NS_OK;
   }
 
   nsIFrame* frame = aFrame;
 
-  if (aEvent->eventStructType == NS_TOUCH_EVENT) {
-    nsIDocument::UnlockPointer();
-    FlushPendingNotifications(Flush_Layout);
-    frame = GetNearestFrameContainingPresShell(this);
-  }
-
   bool dispatchUsingCoordinates = aEvent->IsUsingCoordinates();
   if (dispatchUsingCoordinates) {
+    if (nsLayoutUtils::AreAsyncAnimationsEnabled() && mDocument) {
+      if (aEvent->eventStructType == NS_TOUCH_EVENT) {
+        nsIDocument::UnlockPointer();
+      }
+
+      {  // scope for scriptBlocker.
+        nsAutoScriptBlocker scriptBlocker;
+        GetRootPresShell()->GetDocument()->
+          EnumerateSubDocuments(FlushThrottledStyles, nullptr);
+      }
+      frame = GetNearestFrameContainingPresShell(this);
+    }
+
     NS_WARN_IF_FALSE(frame, "Nothing to handle this event!");
     if (!frame)
       return NS_OK;
 
     nsPresContext* framePresContext = frame->PresContext();
     nsPresContext* rootPresContext = framePresContext->GetRootPresContext();
     NS_ASSERTION(rootPresContext == mPresContext->GetRootPresContext(),
                  "How did we end up outside the connected prescontext/viewmanager hierarchy?"); 
new file mode 100644
--- /dev/null
+++ b/layout/forms/crashtests/960277-2.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<style>
+#d { overflow:scroll; width:200px; height:200px; background:yellow; }
+#d2 { right:0; width:100px; height:100px; background:purple; }
+</style>
+<fieldset id="d">
+  <div id="d2"></div>
+</fieldset>
+<script>
+d.getBoundingClientRect();
+d.style.transform = "translateX(100px)";
+d.getBoundingClientRect();
+d2.style.position = "absolute";
+</script>
--- a/layout/forms/crashtests/crashtests.list
+++ b/layout/forms/crashtests/crashtests.list
@@ -48,8 +48,9 @@ skip-if(B2G) load 498698-1.html # bug 83
 asserts(1) load 578604-1.html # bug 584564
 asserts(4-7) load 590302-1.xhtml # bug 584564
 load 626014.xhtml
 load 639733.xhtml
 asserts(0-1) load 669767.html
 load 682684.xhtml
 load 865602.html
 load 944198.html
+load 960277-2.html
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsFieldSetFrame.h"
+
 #include "nsCSSAnonBoxes.h"
-#include "nsContainerFrame.h"
 #include "nsLegendFrame.h"
 #include "nsCSSRendering.h"
 #include <algorithm>
 #include "nsIFrame.h"
 #include "nsPresContext.h"
 #include "RestyleManager.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
@@ -17,134 +18,16 @@
 #include "nsRenderingContext.h"
 #include "nsIScrollableFrame.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Maybe.h"
 
 using namespace mozilla;
 using namespace mozilla::layout;
 
-class nsFieldSetFrame MOZ_FINAL : public nsContainerFrame {
-public:
-  NS_DECL_FRAMEARENA_HELPERS
-
-  nsFieldSetFrame(nsStyleContext* aContext);
-
-  NS_HIDDEN_(nscoord)
-    GetIntrinsicWidth(nsRenderingContext* aRenderingContext,
-                      nsLayoutUtils::IntrinsicWidthType);
-  virtual nscoord GetMinWidth(nsRenderingContext* aRenderingContext);
-  virtual nscoord GetPrefWidth(nsRenderingContext* aRenderingContext);
-  virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
-                             nsSize aCBSize, nscoord aAvailableWidth,
-                             nsSize aMargin, nsSize aBorder, nsSize aPadding,
-                             uint32_t aFlags) MOZ_OVERRIDE;
-  virtual nscoord GetBaseline() const;
-
-  /**
-   * The area to paint box-shadows around.  It's the border rect except
-   * when there's a <legend> we offset the y-position to the center of it.
-   */
-  virtual nsRect VisualBorderRectRelativeToSelf() const MOZ_OVERRIDE {
-    nscoord topBorder = StyleBorder()->GetComputedBorderWidth(NS_SIDE_TOP);
-    nsRect r(nsPoint(0,0), GetSize());
-    if (topBorder < mLegendRect.height) {
-      nscoord yoff = (mLegendRect.height - topBorder) / 2;
-      r.y += yoff;
-      r.height -= yoff;
-    }
-    return r;
-  }
-
-  NS_IMETHOD Reflow(nsPresContext*           aPresContext,
-                    nsHTMLReflowMetrics&     aDesiredSize,
-                    const nsHTMLReflowState& aReflowState,
-                    nsReflowStatus&          aStatus);
-                               
-  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
-                                const nsRect&           aDirtyRect,
-                                const nsDisplayListSet& aLists) MOZ_OVERRIDE;
-
-  void PaintBorderBackground(nsRenderingContext& aRenderingContext,
-    nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags);
-
-  NS_IMETHOD AppendFrames(ChildListID    aListID,
-                          nsFrameList&   aFrameList);
-  NS_IMETHOD InsertFrames(ChildListID    aListID,
-                          nsIFrame*      aPrevFrame,
-                          nsFrameList&   aFrameList);
-  NS_IMETHOD RemoveFrame(ChildListID    aListID,
-                         nsIFrame*      aOldFrame);
-
-  virtual nsIAtom* GetType() const;
-  virtual bool IsFrameOfType(uint32_t aFlags) const
-  {
-    return nsContainerFrame::IsFrameOfType(aFlags &
-             ~nsIFrame::eCanContainOverflowContainers);
-  }
-  virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE
-  {
-    return do_QueryFrame(GetInner());
-  }
-
-#ifdef ACCESSIBILITY  
-  virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
-#endif
-
-#ifdef DEBUG
-  NS_IMETHOD SetInitialChildList(ChildListID    aListID,
-                                 nsFrameList&   aChildList);
-#endif
-
-#ifdef DEBUG_FRAME_DUMP
-  NS_IMETHOD GetFrameName(nsAString& aResult) const {
-    return MakeFrameName(NS_LITERAL_STRING("FieldSet"), aResult);
-  }
-#endif
-
-protected:
-
-  /**
-   * Return the anonymous frame that contains all descendants except
-   * the legend frame.  This is currently always a block frame with
-   * pseudo nsCSSAnonBoxes::fieldsetContent -- this may change in the
-   * future when we add support for CSS overflow for <fieldset>.
-   */
-  nsIFrame* GetInner() const
-  {
-    nsIFrame* last = mFrames.LastChild();
-    if (last &&
-        last->StyleContext()->GetPseudo() == nsCSSAnonBoxes::fieldsetContent) {
-      return last;
-    }
-    MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
-    return nullptr;
-  }
-
-  /**
-   * Return the frame that represents the legend if any.  This may be
-   * a nsLegendFrame or a nsHTMLScrollFrame with the nsLegendFrame as the
-   * scrolled frame (aka content insertion frame).
-   */
-  nsIFrame* GetLegend() const
-  {
-    if (mFrames.FirstChild() == GetInner()) {
-      MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
-      return nullptr;
-    }
-    MOZ_ASSERT(mFrames.FirstChild() &&
-               mFrames.FirstChild()->GetContentInsertionFrame()->GetType() ==
-                 nsGkAtoms::legendFrame);
-    return mFrames.FirstChild();
-  }
-
-  nsRect    mLegendRect;
-  nscoord   mLegendSpace;
-};
-
 nsIFrame*
 NS_NewFieldSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsFieldSetFrame(aContext);
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsFieldSetFrame)
 
@@ -166,16 +49,54 @@ nsFieldSetFrame::SetInitialChildList(Chi
                                      nsFrameList&   aChildList)
 {
   nsresult rv = nsContainerFrame::SetInitialChildList(kPrincipalList, aChildList);
   MOZ_ASSERT(GetInner());
   return rv;
 }
 #endif
 
+nsRect
+nsFieldSetFrame::VisualBorderRectRelativeToSelf() const
+{
+  nscoord topBorder = StyleBorder()->GetComputedBorderWidth(NS_SIDE_TOP);
+  nsRect r(nsPoint(0,0), GetSize());
+  if (topBorder < mLegendRect.height) {
+    nscoord yoff = (mLegendRect.height - topBorder) / 2;
+    r.y += yoff;
+    r.height -= yoff;
+  }
+  return r;
+}
+
+nsIFrame*
+nsFieldSetFrame::GetInner() const
+{
+  nsIFrame* last = mFrames.LastChild();
+  if (last &&
+      last->StyleContext()->GetPseudo() == nsCSSAnonBoxes::fieldsetContent) {
+    return last;
+  }
+  MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
+  return nullptr;
+}
+
+nsIFrame*
+nsFieldSetFrame::GetLegend() const
+{
+  if (mFrames.FirstChild() == GetInner()) {
+    MOZ_ASSERT(mFrames.LastChild() == mFrames.FirstChild());
+    return nullptr;
+  }
+  MOZ_ASSERT(mFrames.FirstChild() &&
+             mFrames.FirstChild()->GetContentInsertionFrame()->GetType() ==
+               nsGkAtoms::legendFrame);
+  return mFrames.FirstChild();
+}
+
 class nsDisplayFieldSetBorderBackground : public nsDisplayItem {
 public:
   nsDisplayFieldSetBorderBackground(nsDisplayListBuilder* aBuilder,
                                     nsFieldSetFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame) {
     MOZ_COUNT_CTOR(nsDisplayFieldSetBorderBackground);
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
new file mode 100644
--- /dev/null
+++ b/layout/forms/nsFieldSetFrame.h
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsFieldSetFrame_h___
+#define nsFieldSetFrame_h___
+
+#include "nsContainerFrame.h"
+
+class nsFieldSetFrame MOZ_FINAL : public nsContainerFrame
+{
+public:
+  NS_DECL_FRAMEARENA_HELPERS
+
+  nsFieldSetFrame(nsStyleContext* aContext);
+
+  NS_HIDDEN_(nscoord)
+    GetIntrinsicWidth(nsRenderingContext* aRenderingContext,
+                      nsLayoutUtils::IntrinsicWidthType);
+  virtual nscoord GetMinWidth(nsRenderingContext* aRenderingContext);
+  virtual nscoord GetPrefWidth(nsRenderingContext* aRenderingContext);
+  virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext,
+                             nsSize aCBSize, nscoord aAvailableWidth,
+                             nsSize aMargin, nsSize aBorder, nsSize aPadding,
+                             uint32_t aFlags) MOZ_OVERRIDE;
+  virtual nscoord GetBaseline() const;
+
+  /**
+   * The area to paint box-shadows around.  It's the border rect except
+   * when there's a <legend> we offset the y-position to the center of it.
+   */
+  virtual nsRect VisualBorderRectRelativeToSelf() const MOZ_OVERRIDE;
+
+  NS_IMETHOD Reflow(nsPresContext*           aPresContext,
+                    nsHTMLReflowMetrics&     aDesiredSize,
+                    const nsHTMLReflowState& aReflowState,
+                    nsReflowStatus&          aStatus);
+                               
+  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
+                                const nsRect&           aDirtyRect,
+                                const nsDisplayListSet& aLists) MOZ_OVERRIDE;
+
+  void PaintBorderBackground(nsRenderingContext& aRenderingContext,
+    nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags);
+
+  NS_IMETHOD AppendFrames(ChildListID    aListID,
+                          nsFrameList&   aFrameList);
+  NS_IMETHOD InsertFrames(ChildListID    aListID,
+                          nsIFrame*      aPrevFrame,
+                          nsFrameList&   aFrameList);
+  NS_IMETHOD RemoveFrame(ChildListID    aListID,
+                         nsIFrame*      aOldFrame);
+
+  virtual nsIAtom* GetType() const;
+  virtual bool IsFrameOfType(uint32_t aFlags) const
+  {
+    return nsContainerFrame::IsFrameOfType(aFlags &
+             ~nsIFrame::eCanContainOverflowContainers);
+  }
+  virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE
+  {
+    return do_QueryFrame(GetInner());
+  }
+
+#ifdef ACCESSIBILITY  
+  virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE;
+#endif
+
+#ifdef DEBUG
+  NS_IMETHOD SetInitialChildList(ChildListID    aListID,
+                                 nsFrameList&   aChildList);
+#endif
+
+#ifdef DEBUG_FRAME_DUMP
+  NS_IMETHOD GetFrameName(nsAString& aResult) const {
+    return MakeFrameName(NS_LITERAL_STRING("FieldSet"), aResult);
+  }
+#endif
+
+  /**
+   * Return the anonymous frame that contains all descendants except
+   * the legend frame.  This is currently always a block frame with
+   * pseudo nsCSSAnonBoxes::fieldsetContent -- this may change in the
+   * future when we add support for CSS overflow for <fieldset>.
+   */
+  nsIFrame* GetInner() const;
+
+  /**
+   * Return the frame that represents the legend if any.  This may be
+   * a nsLegendFrame or a nsHTMLScrollFrame with the nsLegendFrame as the
+   * scrolled frame (aka content insertion frame).
+   */
+  nsIFrame* GetLegend() const;
+
+protected:
+  nsRect    mLegendRect;
+  nscoord   mLegendSpace;
+};
+
+#endif // nsFieldSetFrame_h___
--- a/layout/forms/test/mochitest.ini
+++ b/layout/forms/test/mochitest.ini
@@ -31,11 +31,12 @@ support-files =
 [test_bug620936.html]
 [test_bug644542.html]
 [test_bug672810.html]
 [test_bug704049.html]
 [test_bug717878_input_scroll.html]
 [test_bug869314.html]
 [test_bug903715.html]
 [test_bug957562.html]
+[test_bug960277.html]
 [test_listcontrol_search.html]
 [test_select_prevent_default.html]
 [test_textarea_resize.html]
new file mode 100644
--- /dev/null
+++ b/layout/forms/test/test_bug960277.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=960277
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 903715</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=960277">Mozilla Bug 960277</a>
+<p id="display"></p>
+<fieldset style="position:relative; height:100px; margin:50px; background:blue;">
+<legend style="background:purple">
+  <div id="d" style="position:absolute; background:yellow; top:0; left:0; width:50px; height:50px;"></div>
+</legend>
+</fieldset>
+<pre id="test">
+</pre>
+<script type="application/javascript">
+var rect = d.getBoundingClientRect();
+is(document.elementFromPoint(rect.left + 10, rect.top + 10), d,
+   "Hit testing yellow div");
+</script>
+</body>
+</html>
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -605,30 +605,33 @@ public:
     }
   }
 
   virtual void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE
   {
     MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
   }
 
-  void SaveZoomConstraints(const ZoomConstraints& aConstraints)
-  {
-    mHaveZoomConstraints = true;
-    mZoomConstraints = aConstraints;
-  }
-
   virtual bool GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
   {
     if (mHaveZoomConstraints && aOutConstraints) {
       *aOutConstraints = mZoomConstraints;
     }
     return mHaveZoomConstraints;
   }
 
+  virtual bool GetTouchSensitiveRegion(CSSRect* aOutRegion)
+  {
+    if (mTouchSensitiveRegion.IsEmpty())
+      return false;
+
+    *aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
+    return true;
+  }
+
   virtual void NotifyTransformBegin(const ScrollableLayerGuid& aGuid)
   {
     if (MessageLoop::current() != mUILoop) {
       mUILoop->PostTask(
         FROM_HERE,
         NewRunnableMethod(this, &RemoteContentController::NotifyTransformBegin,
                           aGuid));
       return;
@@ -649,30 +652,43 @@ public:
       return;
     }
     if (mRenderFrame) {
       TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
       browser->NotifyTransformEnd(aGuid.mScrollId);
     }
   }
 
+  // Methods used by RenderFrameParent to set fields stored here.
+
+  void SaveZoomConstraints(const ZoomConstraints& aConstraints)
+  {
+    mHaveZoomConstraints = true;
+    mZoomConstraints = aConstraints;
+  }
+
+  void SetTouchSensitiveRegion(const nsRegion& aRegion)
+  {
+    mTouchSensitiveRegion = aRegion;
+  }
 private:
   void DoRequestContentRepaint(const FrameMetrics& aFrameMetrics)
   {
     if (mRenderFrame) {
       TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
       browser->UpdateFrame(aFrameMetrics);
     }
   }
 
   MessageLoop* mUILoop;
   RenderFrameParent* mRenderFrame;
 
   bool mHaveZoomConstraints;
   ZoomConstraints mZoomConstraints;
+  nsRegion mTouchSensitiveRegion;
 };
 
 RenderFrameParent::RenderFrameParent()
   : mLayersId(0)
   , mFrameLoaderDestroyed(false)
   , mBackgroundColor(gfxRGBA(1, 1, 1))
 {
 }
@@ -936,16 +952,23 @@ RenderFrameParent::RecvNotifyCompositorT
   TriggerRepaint();
   return true;
 }
 
 bool
 RenderFrameParent::RecvUpdateHitRegion(const nsRegion& aRegion)
 {
   mTouchRegion = aRegion;
+  if (mContentController) {
+    // Tell the content controller about the touch-sensitive region, so
+    // that it can provide it to APZ. This is required for APZ to do
+    // correct hit testing for a remote 'mozpasspointerevents' iframe
+    // until bug 928833 is fixed.
+    mContentController->SetTouchSensitiveRegion(aRegion);
+  }
   return true;
 }
 
 PLayerTransactionParent*
 RenderFrameParent::AllocPLayerTransactionParent()
 {
   if (!mFrameLoader || mFrameLoaderDestroyed) {
     return nullptr;
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/960277-1-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<style>
+#d { overflow:scroll; width:200px; height:200px; background:yellow; transform:translateX(100px); }
+#d2 { right:0; width:100px; height:100px; background:purple; position:absolute; }
+</style>
+<div id="d">
+  <div id="d2"></div>
+</div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/960277-1.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<style>
+#d { overflow:scroll; width:200px; height:200px; background:yellow; }
+#d2 { right:0; width:100px; height:100px; background:purple; }
+</style>
+<div id="d">
+  <div id="d2"></div>
+</div>
+<script>
+d.getBoundingClientRect();
+d.style.transform = "translateX(100px)";
+d.getBoundingClientRect();
+d2.style.position = "absolute";
+</script>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1790,8 +1790,9 @@ fuzzy-if(OSX==10.6,2,30) == 933264-1.htm
 == 936670-1.svg 936670-1-ref.svg
 == 941940-1.html 941940-1-ref.html
 == 942017.html 942017-ref.html
 == 942672-1.html 942672-1-ref.html
 == 953334-win32-clipping.html 953334-win32-clipping-ref.html
 == 956513-1.svg 956513-1-ref.svg
 == 944291-1.html 944291-1-ref.html
 == 957770-1.svg 957770-1-ref.svg
+== 960277-1.html 960277-1-ref.html
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -1,26 +1,32 @@
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* 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 "AnimationCommon.h"
+#include "nsTransitionManager.h"
+#include "nsAnimationManager.h"
+
 #include "gfxPlatform.h"
-#include "AnimationCommon.h"
 #include "nsRuleData.h"
 #include "nsCSSValue.h"
 #include "nsStyleContext.h"
 #include "nsIFrame.h"
 #include "nsLayoutUtils.h"
 #include "mozilla/LookAndFeel.h"
 #include "Layers.h"
 #include "FrameLayerBuilder.h"
 #include "nsDisplayList.h"
 #include "mozilla/MemoryReporting.h"
 #include "RestyleManager.h"
+#include "nsStyleSet.h"
+#include "nsStyleChangeList.h"
+
 
 using namespace mozilla::layers;
 
 namespace mozilla {
 namespace css {
 
 /* static */ bool
 IsGeometricProperty(nsCSSProperty aProperty)
@@ -137,16 +143,167 @@ CommonAnimationManager::ExtractComputedV
                         nsStyleAnimation::eUnit_Enumerated,
                       "unexpected unit");
     aComputedValue.SetIntValue(aComputedValue.GetIntValue(),
                                nsStyleAnimation::eUnit_Visibility);
   }
   return result;
 }
 
+already_AddRefed<nsStyleContext>
+CommonAnimationManager::ReparentContent(nsIContent* aContent,
+                                        nsStyleContext* aParentStyle)
+{
+  nsStyleSet* styleSet = mPresContext->PresShell()->StyleSet();
+  nsIFrame* primaryFrame = nsLayoutUtils::GetStyleFrame(aContent);
+  if (!primaryFrame) {
+    return nullptr;
+  }
+
+  dom::Element* element = aContent->IsElement()
+                          ? aContent->AsElement()
+                          : nullptr;
+
+  nsRefPtr<nsStyleContext> newStyle =
+    styleSet->ReparentStyleContext(primaryFrame->StyleContext(),
+                                   aParentStyle, element);
+  primaryFrame->SetStyleContext(newStyle);
+  ReparentBeforeAndAfter(element, primaryFrame, newStyle, styleSet);
+
+  return newStyle.forget();
+}
+
+/* static */ void
+CommonAnimationManager::ReparentBeforeAndAfter(dom::Element* aElement,
+                                               nsIFrame* aPrimaryFrame,
+                                               nsStyleContext* aNewStyle,
+                                               nsStyleSet* aStyleSet)
+{
+  if (nsIFrame* before = nsLayoutUtils::GetBeforeFrame(aPrimaryFrame)) {
+    nsRefPtr<nsStyleContext> beforeStyle =
+      aStyleSet->ReparentStyleContext(before->StyleContext(),
+                                     aNewStyle, aElement);
+    before->SetStyleContext(beforeStyle);
+  }
+  if (nsIFrame* after = nsLayoutUtils::GetBeforeFrame(aPrimaryFrame)) {
+    nsRefPtr<nsStyleContext> afterStyle =
+      aStyleSet->ReparentStyleContext(after->StyleContext(),
+                                     aNewStyle, aElement);
+    after->SetStyleContext(afterStyle);
+  }
+}
+
+// Ensure that the next repaint rebuilds the layer tree for aFrame. That
+// means that changes to animations on aFrame's layer are propagated to
+// the compositor, which is needed for correct behaviour of new
+// transitions.
+static void
+ForceLayerRerendering(nsIFrame* aFrame, CommonElementAnimationData* aData)
+{
+  if (aData->HasAnimationOfProperty(eCSSProperty_opacity)) {
+    if (Layer* layer = FrameLayerBuilder::GetDedicatedLayer(
+          aFrame, nsDisplayItem::TYPE_OPACITY)) {
+      layer->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey());
+    }
+  }
+
+  if (aData->HasAnimationOfProperty(eCSSProperty_transform)) {
+    if (Layer* layer = FrameLayerBuilder::GetDedicatedLayer(
+          aFrame, nsDisplayItem::TYPE_TRANSFORM)) {
+      layer->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey());
+    }
+  }
+}
+
+nsStyleContext*
+CommonAnimationManager::UpdateThrottledStyle(dom::Element* aElement,
+                                             nsStyleContext* aParentStyle,
+                                             nsStyleChangeList& aChangeList)
+{
+  NS_ASSERTION(mPresContext->TransitionManager()->GetElementTransitions(
+                 aElement,
+                 nsCSSPseudoElements::ePseudo_NotPseudoElement,
+                 false) ||
+               mPresContext->AnimationManager()->GetElementAnimations(
+                 aElement,
+                 nsCSSPseudoElements::ePseudo_NotPseudoElement,
+                 false), "element not animated");
+
+  nsIFrame* primaryFrame = nsLayoutUtils::GetStyleFrame(aElement);
+  if (!primaryFrame) {
+    return nullptr;
+  }
+
+  nsStyleContext* oldStyle = primaryFrame->StyleContext();
+  nsRuleNode* ruleNode = oldStyle->RuleNode();
+  nsTArray<nsStyleSet::RuleAndLevel> rules;
+  do {
+    if (ruleNode->IsRoot()) {
+      break;
+    }
+
+    nsStyleSet::RuleAndLevel curRule;
+    curRule.mLevel = ruleNode->GetLevel();
+
+    if (curRule.mLevel == nsStyleSet::eAnimationSheet) {
+      ElementAnimations* ea =
+        mPresContext->AnimationManager()->GetElementAnimations(
+          aElement,
+          oldStyle->GetPseudoType(),
+          false);
+      NS_ASSERTION(ea,
+        "Rule has level eAnimationSheet without animation on manager");
+
+      mPresContext->AnimationManager()->EnsureStyleRuleFor(ea);
+      curRule.mRule = ea->mStyleRule;
+
+      // FIXME: maybe not needed anymore:
+      ForceLayerRerendering(primaryFrame, ea);
+    } else if (curRule.mLevel == nsStyleSet::eTransitionSheet) {
+      ElementTransitions *et =
+        mPresContext->TransitionManager()->GetElementTransitions(
+          aElement,
+          oldStyle->GetPseudoType(),
+          false);
+      NS_ASSERTION(et,
+        "Rule has level eTransitionSheet without transition on manager");
+
+      et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh());
+      curRule.mRule = et->mStyleRule;
+
+      // FIXME: maybe not needed anymore:
+      ForceLayerRerendering(primaryFrame, et);
+    } else {
+      curRule.mRule = ruleNode->GetRule();
+    }
+
+    if (curRule.mRule) {
+      rules.AppendElement(curRule);
+    }
+  } while ((ruleNode = ruleNode->GetParent()));
+
+  nsRefPtr<nsStyleContext> newStyle = mPresContext->PresShell()->StyleSet()->
+    ResolveStyleForRules(aParentStyle, oldStyle, rules);
+
+  // We absolutely must call CalcStyleDifference in order to ensure the
+  // new context has all the structs cached that the old context had.
+  // We also need it for processing of the changes.
+  nsChangeHint styleChange =
+    oldStyle->CalcStyleDifference(newStyle, nsChangeHint(0));
+  aChangeList.AppendChange(primaryFrame, primaryFrame->GetContent(),
+                           styleChange);
+
+  primaryFrame->SetStyleContext(newStyle);
+
+  ReparentBeforeAndAfter(aElement, primaryFrame, newStyle,
+                         mPresContext->PresShell()->StyleSet());
+
+  return newStyle;
+}
+
 NS_IMPL_ISUPPORTS1(AnimValuesStyleRule, nsIStyleRule)
 
 /* virtual */ void
 AnimValuesStyleRule::MapRuleInfoInto(nsRuleData* aRuleData)
 {
   nsStyleContext *contextParent = aRuleData->mStyleContext->GetParent();
   if (contextParent && contextParent->HasPseudoElementData()) {
     // Don't apply transitions or animations to things inside of
--- a/layout/style/AnimationCommon.h
+++ b/layout/style/AnimationCommon.h
@@ -12,16 +12,17 @@
 #include "prclist.h"
 #include "nsStyleAnimation.h"
 #include "nsCSSProperty.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/Element.h"
 #include "nsSMILKeySpline.h"
 #include "nsStyleStruct.h"
 #include "mozilla/Attributes.h"
+#include "nsCSSPseudoElements.h"
 
 class nsPresContext;
 class nsIFrame;
 
 
 namespace mozilla {
 namespace css {
 
@@ -66,20 +67,92 @@ public:
                   nsStyleAnimation::Value& aComputedValue);
 protected:
   friend struct CommonElementAnimationData; // for ElementDataRemoved
 
   virtual void AddElementData(CommonElementAnimationData* aData) = 0;
   virtual void ElementDataRemoved() = 0;
   void RemoveAllElementData();
 
+  // Update the style on aElement from the transition stored in this manager and
+  // the new parent style - aParentStyle. aElement must be transitioning or
+  // animated. Returns the updated style.
+  nsStyleContext* UpdateThrottledStyle(mozilla::dom::Element* aElement,
+                                       nsStyleContext* aParentStyle,
+                                       nsStyleChangeList &aChangeList);
+  // Reparent the style of aContent and any :before and :after pseudo-elements.
+  already_AddRefed<nsStyleContext> ReparentContent(nsIContent* aContent,
+                                                  nsStyleContext* aParentStyle);
+  // reparent :before and :after pseudo elements of aElement
+  static void ReparentBeforeAndAfter(dom::Element* aElement,
+                                     nsIFrame* aPrimaryFrame,
+                                     nsStyleContext* aNewStyle,
+                                     nsStyleSet* aStyleSet);
+
   PRCList mElementData;
   nsPresContext *mPresContext; // weak (non-null from ctor to Disconnect)
 };
 
+// The internals of UpdateAllThrottledStyles, used by nsAnimationManager and
+// nsTransitionManager, see the comments in the declaration of the latter.
+#define IMPL_UPDATE_ALL_THROTTLED_STYLES_INTERNAL(class_, animations_getter_)  \
+void                                                                           \
+class_::UpdateAllThrottledStylesInternal()                                     \
+{                                                                              \
+  TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();          \
+                                                                               \
+  nsStyleChangeList changeList;                                                \
+                                                                               \
+  /* update each transitioning element by finding its root-most ancestor
+     with a transition, and flushing the style on that ancestor and all
+     its descendants*/                                                         \
+  PRCList *next = PR_LIST_HEAD(&mElementData);                                 \
+  while (next != &mElementData) {                                              \
+    CommonElementAnimationData* ea =                                           \
+      static_cast<CommonElementAnimationData*>(next);                          \
+    next = PR_NEXT_LINK(next);                                                 \
+                                                                               \
+    if (ea->mFlushGeneration == now) {                                         \
+      /* this element has been ticked already */                               \
+      continue;                                                                \
+    }                                                                          \
+                                                                               \
+    /* element is initialised to the starting element (i.e., one we know has
+       an animation) and ends up with the root-most animated ancestor,
+       that is, the element where we begin updates. */                         \
+    dom::Element* element = ea->mElement;                                      \
+    /* make a list of ancestors */                                             \
+    nsTArray<dom::Element*> ancestors;                                         \
+    do {                                                                       \
+      ancestors.AppendElement(element);                                        \
+    } while ((element = element->GetParentElement()));                         \
+                                                                               \
+    /* walk down the ancestors until we find one with a throttled transition */\
+    for (int32_t i = ancestors.Length() - 1; i >= 0; --i) {                    \
+      if (animations_getter_(ancestors[i],                                     \
+                            nsCSSPseudoElements::ePseudo_NotPseudoElement,     \
+                            false)) {                                          \
+        element = ancestors[i];                                                \
+        break;                                                                 \
+      }                                                                        \
+    }                                                                          \
+                                                                               \
+    nsIFrame* primaryFrame;                                                    \
+    if (element &&                                                             \
+        (primaryFrame = nsLayoutUtils::GetStyleFrame(element))) {              \
+      UpdateThrottledStylesForSubtree(element,                                 \
+        primaryFrame->StyleContext()->GetParent(), changeList);                \
+    }                                                                          \
+  }                                                                            \
+                                                                               \
+  RestyleManager* restyleManager = mPresContext->RestyleManager();             \
+  restyleManager->ProcessRestyledFrames(changeList);                           \
+  restyleManager->FlushOverflowChangedTracker();                               \
+}
+
 /**
  * A style rule that maps property-nsStyleAnimation::Value pairs.
  */
 class AnimValuesStyleRule MOZ_FINAL : public nsIStyleRule
 {
 public:
   // nsISupports implementation
   NS_DECL_ISUPPORTS
@@ -128,21 +201,22 @@ private:
   Type mType;
   nsSMILKeySpline mTimingFunction;
   uint32_t mSteps;
 };
 
 struct CommonElementAnimationData : public PRCList
 {
   CommonElementAnimationData(dom::Element *aElement, nsIAtom *aElementProperty,
-                             CommonAnimationManager *aManager)
+                             CommonAnimationManager *aManager, TimeStamp aNow)
     : mElement(aElement)
     , mElementProperty(aElementProperty)
     , mManager(aManager)
     , mAnimationGeneration(0)
+    , mFlushGeneration(aNow)
 #ifdef DEBUG
     , mCalledPropertyDtor(false)
 #endif
   {
     MOZ_COUNT_CTOR(CommonElementAnimationData);
     PR_INIT_CLIST(this);
   }
   ~CommonElementAnimationData()
@@ -212,16 +286,21 @@ struct CommonElementAnimationData : publ
   // date with the animation manager.
   uint64_t mAnimationGeneration;
   // Update mFlushCount to nsCSSFrameConstructor's count
   void UpdateAnimationGeneration(nsPresContext* aPresContext);
 
   // The refresh time associated with mStyleRule.
   TimeStamp mStyleRuleRefreshTime;
 
+  // Generation counter for flushes of throttled animations.
+  // Used to prevent updating the styles twice for a given element during
+  // UpdateAllThrottledStyles.
+  TimeStamp mFlushGeneration;
+
 #ifdef DEBUG
   bool mCalledPropertyDtor;
 #endif
 };
 
 }
 }
 
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -11,17 +11,16 @@
 @namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);
 
 *|*::-moz-fieldset-content {
   display: block;
   unicode-bidi: inherit;
   text-overflow: inherit;
   overflow: inherit;
   padding: inherit;
-  position: inherit;
   height: 100%;   /* Need this so percentage heights of kids work right */
 }
 
 /* miscellaneous form elements */
 
 fieldset > legend {
   padding-left: 2px;
   padding-right: 2px;
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -1,36 +1,41 @@
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* 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 "nsAnimationManager.h"
+#include "nsTransitionManager.h"
 
 #include "mozilla/MemoryReporting.h"
 
 #include "nsPresContext.h"
 #include "nsRuleProcessorData.h"
 #include "nsStyleSet.h"
+#include "nsStyleChangeList.h"
 #include "nsCSSRules.h"
+#include "RestyleManager.h"
 #include "nsStyleAnimation.h"
 #include "nsEventDispatcher.h"
 #include "nsLayoutUtils.h"
 #include "nsIFrame.h"
 #include "nsIDocument.h"
 #include "ActiveLayerTracker.h"
 #include <math.h>
 
 using namespace mozilla;
 using namespace mozilla::css;
 
-ElementAnimations::ElementAnimations(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
-                                     nsAnimationManager *aAnimationManager)
+ElementAnimations::ElementAnimations(mozilla::dom::Element *aElement,
+                                     nsIAtom *aElementProperty,
+                                     nsAnimationManager *aAnimationManager,
+                                     TimeStamp aNow)
   : CommonElementAnimationData(aElement, aElementProperty,
-                               aAnimationManager),
+                               aAnimationManager, aNow),
     mNeedsRefreshes(true)
 {
 }
 
 static void
 ElementAnimationsPropertyDtor(void           *aObject,
                               nsIAtom        *aPropertyName,
                               void           *aPropertyValue,
@@ -447,17 +452,18 @@ nsAnimationManager::GetElementAnimations
                  "should never try to create transitions for pseudo "
                  "other than :before or :after");
     return nullptr;
   }
   ElementAnimations *ea = static_cast<ElementAnimations*>(
                              aElement->GetProperty(propName));
   if (!ea && aCreateIfNeeded) {
     // FIXME: Consider arena-allocating?
-    ea = new ElementAnimations(aElement, propName, this);
+    ea = new ElementAnimations(aElement, propName, this,
+           mPresContext->RefreshDriver()->MostRecentRefresh());
     nsresult rv = aElement->SetProperty(propName, ea,
                                         ElementAnimationsPropertyDtor, false);
     if (NS_FAILED(rv)) {
       NS_WARNING("SetProperty failed");
       delete ea;
       return nullptr;
     }
     if (propName == nsGkAtoms::animationsProperty) {
@@ -1088,8 +1094,67 @@ nsAnimationManager::DoDispatchEvents()
     AnimationEventInfo &info = events[i];
     nsEventDispatcher::Dispatch(info.mElement, mPresContext, &info.mEvent);
 
     if (!mPresContext) {
       break;
     }
   }
 }
+
+void
+nsAnimationManager::UpdateThrottledStylesForSubtree(nsIContent* aContent,
+                                                nsStyleContext* aParentStyle,
+                                                nsStyleChangeList& aChangeList)
+{
+  dom::Element* element;
+  if (aContent->IsElement()) {
+    element = aContent->AsElement();
+  } else {
+    element = nullptr;
+  }
+
+  nsRefPtr<nsStyleContext> newStyle;
+
+  ElementAnimations* ea;
+  if (element &&
+      (ea = GetElementAnimations(element,
+                                 nsCSSPseudoElements::ePseudo_NotPseudoElement,
+                                 false))) {
+    // re-resolve our style
+    newStyle = UpdateThrottledStyle(element, aParentStyle, aChangeList);
+    // remove the current transition from the working set
+    ea->mFlushGeneration = mPresContext->RefreshDriver()->MostRecentRefresh();
+  } else {
+    newStyle = ReparentContent(aContent, aParentStyle);
+  }
+
+  // walk the children
+  if (newStyle) {
+    for (nsIContent *child = aContent->GetFirstChild(); child;
+         child = child->GetNextSibling()) {
+      UpdateThrottledStylesForSubtree(child, newStyle, aChangeList);
+    }
+  }
+}
+
+IMPL_UPDATE_ALL_THROTTLED_STYLES_INTERNAL(nsAnimationManager,
+                                          GetElementAnimations)
+
+void
+nsAnimationManager::UpdateAllThrottledStyles()
+{
+  if (PR_CLIST_IS_EMPTY(&mElementData)) {
+    // no throttled animations, leave early
+    mPresContext->TickLastUpdateThrottledAnimationStyle();
+    return;
+  }
+
+  if (mPresContext->ThrottledAnimationStyleIsUpToDate()) {
+    // throttled transitions are up to date, leave early
+    return;
+  }
+
+  mPresContext->TickLastUpdateThrottledAnimationStyle();
+
+  UpdateAllThrottledStylesInternal();
+}
+
--- a/layout/style/nsAnimationManager.h
+++ b/layout/style/nsAnimationManager.h
@@ -123,17 +123,17 @@ struct ElementAnimation
  */
 struct ElementAnimations MOZ_FINAL
   : public mozilla::css::CommonElementAnimationData
 {
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
   ElementAnimations(mozilla::dom::Element *aElement, nsIAtom *aElementProperty,
-                    nsAnimationManager *aAnimationManager);
+                    nsAnimationManager *aAnimationManager, TimeStamp aNow);
 
   // This function takes as input the start time, duration, and direction of an
   // animation and returns the position in the current iteration.  Note that
   // this only works when we know that the animation is currently running.
   // This way of calling the function can be used from the compositor.  Note
   // that if the animation has not started yet, has already ended, or is paused,
   // it should not be run from the compositor.  When this function is called 
   // from the main thread, we need the actual ElementAnimation* in order to 
@@ -270,16 +270,19 @@ public:
       DoDispatchEvents();
     }
   }
 
   ElementAnimations* GetElementAnimations(mozilla::dom::Element *aElement,
                                           nsCSSPseudoElements::Type aPseudoType,
                                           bool aCreateIfNeeded);
 
+  // Updates styles on throttled animations. See note on nsTransitionManager
+  void UpdateAllThrottledStyles();
+
 protected:
   virtual void ElementDataRemoved() MOZ_OVERRIDE
   {
     CheckNeedsRefresh();
   }
   virtual void AddElementData(mozilla::css::CommonElementAnimationData* aData) MOZ_OVERRIDE;
 
   /**
@@ -293,16 +296,24 @@ private:
   bool BuildSegment(InfallibleTArray<AnimationPropertySegment>& aSegments,
                     nsCSSProperty aProperty, const nsAnimation& aAnimation,
                     float aFromKey, nsStyleContext* aFromContext,
                     mozilla::css::Declaration* aFromDeclaration,
                     float aToKey, nsStyleContext* aToContext);
   nsIStyleRule* GetAnimationRule(mozilla::dom::Element* aElement,
                                  nsCSSPseudoElements::Type aPseudoType);
 
+  // Update the animated styles of an element and its descendants.
+  // If the element has an animation, it is flushed back to its primary frame.
+  // If the element does not have an animation, then its style is reparented.
+  void UpdateThrottledStylesForSubtree(nsIContent* aContent,
+                                       nsStyleContext* aParentStyle,
+                                       nsStyleChangeList &aChangeList);
+  void UpdateAllThrottledStylesInternal();
+
   // The guts of DispatchEvents
   void DoDispatchEvents();
 
   EventArray mPendingEvents;
 
   bool mObservingRefreshDriver;
 };
 
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -36,18 +36,18 @@ using mozilla::TimeDuration;
 using namespace mozilla;
 using namespace mozilla::layers;
 using namespace mozilla::css;
 
 ElementTransitions::ElementTransitions(mozilla::dom::Element *aElement,
                                        nsIAtom *aElementProperty,
                                        nsTransitionManager *aTransitionManager,
                                        TimeStamp aNow)
-  : CommonElementAnimationData(aElement, aElementProperty, aTransitionManager)
-  , mFlushGeneration(aNow)
+  : CommonElementAnimationData(aElement, aElementProperty,
+                               aTransitionManager, aNow)
 {
 }
 
 double
 ElementPropertyTransition::ValuePortionFor(TimeStamp aRefreshTime) const
 {
   // Set |timePortion| to the portion of the way we are through the time
   // input to the transition's timing function (always within the range
@@ -205,132 +205,16 @@ ElementTransitions::CanPerformOnComposit
   }
   return true;
 }
 
 /*****************************************************************************
  * nsTransitionManager                                                       *
  *****************************************************************************/
 
-// reparent :before and :after pseudo elements of aElement
-static void ReparentBeforeAndAfter(dom::Element* aElement,
-                                   nsIFrame* aPrimaryFrame,
-                                   nsStyleContext* aNewStyle,
-                                   nsStyleSet* aStyleSet)
-{
-  if (nsIFrame* before = nsLayoutUtils::GetBeforeFrame(aPrimaryFrame)) {
-    nsRefPtr<nsStyleContext> beforeStyle =
-      aStyleSet->ReparentStyleContext(before->StyleContext(),
-                                     aNewStyle, aElement);
-    before->SetStyleContext(beforeStyle);
-  }
-  if (nsIFrame* after = nsLayoutUtils::GetBeforeFrame(aPrimaryFrame)) {
-    nsRefPtr<nsStyleContext> afterStyle =
-      aStyleSet->ReparentStyleContext(after->StyleContext(),
-                                     aNewStyle, aElement);
-    after->SetStyleContext(afterStyle);
-  }
-}
-
-// Ensure that the next repaint rebuilds the layer tree for aFrame. That
-// means that changes to animations on aFrame's layer are propagated to
-// the compositor, which is needed for correct behaviour of new
-// transitions.
-static void
-ForceLayerRerendering(nsIFrame* aFrame, CommonElementAnimationData* aData)
-{
-  if (aData->HasAnimationOfProperty(eCSSProperty_opacity)) {
-    if (Layer* layer = FrameLayerBuilder::GetDedicatedLayer(
-          aFrame, nsDisplayItem::TYPE_OPACITY)) {
-      layer->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey());
-    }
-  } 
-  
-  if (aData->HasAnimationOfProperty(eCSSProperty_transform)) {
-    if (Layer* layer = FrameLayerBuilder::GetDedicatedLayer(
-          aFrame, nsDisplayItem::TYPE_TRANSFORM)) {
-      layer->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey());
-    }
-  }
-}
-
-nsStyleContext*
-nsTransitionManager::UpdateThrottledStyle(dom::Element* aElement,
-                                          nsStyleContext* aParentStyle,
-                                          nsStyleChangeList& aChangeList)
-{
-  NS_ASSERTION(GetElementTransitions(aElement,
-                                     nsCSSPseudoElements::ePseudo_NotPseudoElement,
-                                     false), "element not transitioning");
-
-  nsIFrame* primaryFrame = nsLayoutUtils::GetStyleFrame(aElement);
-  if (!primaryFrame) {
-    return nullptr;
-  }
-
-  nsStyleContext* oldStyle = primaryFrame->StyleContext();
-  nsRuleNode* ruleNode = oldStyle->RuleNode();
-  nsTArray<nsStyleSet::RuleAndLevel> rules;
-  do {
-    if (ruleNode->IsRoot()) {
-      break;
-    }
-
-    nsStyleSet::RuleAndLevel curRule;
-    curRule.mLevel = ruleNode->GetLevel();
-
-    if (curRule.mLevel == nsStyleSet::eAnimationSheet) {
-      ElementAnimations* ea = 
-        mPresContext->AnimationManager()->GetElementAnimations(aElement,
-                                                               oldStyle->GetPseudoType(),
-                                                               false);
-      NS_ASSERTION(ea, "Rule has level eAnimationSheet without animation on manager");
-
-      mPresContext->AnimationManager()->EnsureStyleRuleFor(ea);
-      curRule.mRule = ea->mStyleRule;
-
-      // FIXME: maybe not needed anymore:
-      ForceLayerRerendering(primaryFrame, ea);
-    } else if (curRule.mLevel == nsStyleSet::eTransitionSheet) {
-      ElementTransitions *et =
-        GetElementTransitions(aElement, oldStyle->GetPseudoType(), false);
-      NS_ASSERTION(et, "Rule has level eTransitionSheet without transition on manager");
-      
-      et->EnsureStyleRuleFor(mPresContext->RefreshDriver()->MostRecentRefresh());
-      curRule.mRule = et->mStyleRule;
-
-      // FIXME: maybe not needed anymore:
-      ForceLayerRerendering(primaryFrame, et);
-    } else {
-      curRule.mRule = ruleNode->GetRule();
-    }
-
-    if (curRule.mRule) {
-      rules.AppendElement(curRule);
-    }
-  } while ((ruleNode = ruleNode->GetParent()));
-
-  nsRefPtr<nsStyleContext> newStyle = mPresContext->PresShell()->StyleSet()->
-    ResolveStyleForRules(aParentStyle, oldStyle, rules);
-
-  // We absolutely must call CalcStyleDifference in order to ensure the
-  // new context has all the structs cached that the old context had.
-  // We also need it for processing of the changes.
-  nsChangeHint styleChange =
-    oldStyle->CalcStyleDifference(newStyle, nsChangeHint(0));
-  aChangeList.AppendChange(primaryFrame, primaryFrame->GetContent(),
-                           styleChange);
-
-  primaryFrame->SetStyleContext(newStyle);
-
-  ReparentBeforeAndAfter(aElement, primaryFrame, newStyle, mPresContext->PresShell()->StyleSet());
-
-  return newStyle;
-}
-
 void
 nsTransitionManager::UpdateThrottledStylesForSubtree(nsIContent* aContent,
                                                      nsStyleContext* aParentStyle,
                                                      nsStyleChangeList& aChangeList)
 {
   dom::Element* element;
   if (aContent->IsElement()) {
     element = aContent->AsElement();
@@ -345,100 +229,47 @@ nsTransitionManager::UpdateThrottledStyl
       (et = GetElementTransitions(element,
                                   nsCSSPseudoElements::ePseudo_NotPseudoElement,
                                   false))) {
     // re-resolve our style
     newStyle = UpdateThrottledStyle(element, aParentStyle, aChangeList);
     // remove the current transition from the working set
     et->mFlushGeneration = mPresContext->RefreshDriver()->MostRecentRefresh();
   } else {
-    // reparent the element's style
-    nsStyleSet* styleSet = mPresContext->PresShell()->StyleSet();
-    nsIFrame* primaryFrame = nsLayoutUtils::GetStyleFrame(aContent);
-    if (!primaryFrame) {
-      return;
-    }
-
-    newStyle = styleSet->ReparentStyleContext(primaryFrame->StyleContext(),
-                                              aParentStyle, element);
-    primaryFrame->SetStyleContext(newStyle);
-    ReparentBeforeAndAfter(element, primaryFrame, newStyle, styleSet);
+    newStyle = ReparentContent(aContent, aParentStyle);
   }
 
   // walk the children
   if (newStyle) {
     for (nsIContent *child = aContent->GetFirstChild(); child;
          child = child->GetNextSibling()) {
       UpdateThrottledStylesForSubtree(child, newStyle, aChangeList);
     }
   }
 }
 
+IMPL_UPDATE_ALL_THROTTLED_STYLES_INTERNAL(nsTransitionManager,
+                                          GetElementTransitions)
+
 void
 nsTransitionManager::UpdateAllThrottledStyles()
 {
   if (PR_CLIST_IS_EMPTY(&mElementData)) {
     // no throttled transitions, leave early
-    mPresContext->TickLastUpdateThrottledStyle();
+    mPresContext->TickLastUpdateThrottledTransitionStyle();
     return;
   }
 
-  if (mPresContext->ThrottledStyleIsUpToDate()) {
+  if (mPresContext->ThrottledTransitionStyleIsUpToDate()) {
     // throttled transitions are up to date, leave early
     return;
   }
 
-  mPresContext->TickLastUpdateThrottledStyle();
-  TimeStamp now = mPresContext->RefreshDriver()->MostRecentRefresh();
-
-  nsStyleChangeList changeList;
-
-  // update each transitioning element by finding its root-most ancestor with a
-  // transition, and flushing the style on that ancestor and all its descendants
-  PRCList *next = PR_LIST_HEAD(&mElementData);
-  while (next != &mElementData) {
-    ElementTransitions* et = static_cast<ElementTransitions*>(next);
-    next = PR_NEXT_LINK(next);
-
-    if (et->mFlushGeneration == now) {
-      // this element has been ticked already
-      continue;
-    }
-
-    // element is initialised to the starting element (i.e., one we know has
-    // a transition) and ends up with the root-most transitioning ancestor,
-    // that is, the element where we begin updates.
-    dom::Element* element = et->mElement;
-    // make a list of ancestors
-    nsTArray<dom::Element*> ancestors;
-    do {
-      ancestors.AppendElement(element);
-    } while ((element = element->GetParentElement()));
-
-    // walk down the ancestors until we find one with a throttled transition
-    for (int32_t i = ancestors.Length() - 1; i >= 0; --i) {
-      if (GetElementTransitions(ancestors[i],
-                                nsCSSPseudoElements::ePseudo_NotPseudoElement,
-                                false)) {
-        element = ancestors[i];
-        break;
-      }
-    }
-
-    nsIFrame* primaryFrame;
-    if (element &&
-        (primaryFrame = nsLayoutUtils::GetStyleFrame(element))) {
-      UpdateThrottledStylesForSubtree(element,
-        primaryFrame->StyleContext()->GetParent(), changeList);
-    }
-  }
-
-  RestyleManager* restyleManager = mPresContext->RestyleManager();
-  restyleManager->ProcessRestyledFrames(changeList);
-  restyleManager->FlushOverflowChangedTracker();
+  mPresContext->TickLastUpdateThrottledTransitionStyle();
+  UpdateAllThrottledStylesInternal();
 }
 
 void
 nsTransitionManager::ElementDataRemoved()
 {
   // If we have no transitions or animations left, remove ourselves from
   // the refresh driver.
   if (PR_CLIST_IS_EMPTY(&mElementData)) {
@@ -522,17 +353,17 @@ nsTransitionManager::StyleContextChanged
       aNewStyleContext->GetParent()->HasPseudoElementData()) {
     // Ignore transitions on things that inherit properties from
     // pseudo-elements.
     // FIXME (Bug 522599): Add tests for this.
     return nullptr;
   }
 
   NS_WARN_IF_FALSE(!nsLayoutUtils::AreAsyncAnimationsEnabled() ||
-                     mPresContext->ThrottledStyleIsUpToDate(),
+                     mPresContext->ThrottledTransitionStyleIsUpToDate(),
                    "throttled animations not up to date");
 
   // Per http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html
   // I'll consider only the transitions from the number of items in
   // 'transition-property' on down, and later ones will override earlier
   // ones (tracked using |whichStarted|).
   bool startedAny = false;
   nsCSSPropertySet whichStarted;
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -86,21 +86,16 @@ struct ElementTransitions MOZ_FINAL
 
   void EnsureStyleRuleFor(mozilla::TimeStamp aRefreshTime);
 
   virtual bool HasAnimationOfProperty(nsCSSProperty aProperty) const MOZ_OVERRIDE;
   virtual bool CanPerformOnCompositorThread(CanAnimateFlags aFlags) const MOZ_OVERRIDE;
 
   // Either zero or one for each CSS property:
   nsTArray<ElementPropertyTransition> mPropertyTransitions;
-
-  // Generation counter for flushes of throttled transitions.
-  // Used to prevent updating the styles twice for a given element during
-  // UpdateAllThrottledStyles.
-  mozilla::TimeStamp mFlushGeneration;
 };
 
 
 
 class nsTransitionManager MOZ_FINAL
   : public mozilla::css::CommonAnimationManager
 {
 public:
@@ -198,42 +193,37 @@ public:
   // primary frame.  So the purpose of the mini-flush is to update the
   // style for all throttled transitions and animations to the current
   // animation state without making any other updates, so that when we
   // process the queued style updates we'll have correct old data to
   // compare against.  When we do this, we don't bother touching frames
   // other than primary frames.
   void UpdateAllThrottledStyles();
 
+  ElementTransitions* GetElementTransitions(mozilla::dom::Element *aElement,
+                                          nsCSSPseudoElements::Type aPseudoType,
+                                          bool aCreateIfNeeded);
+
 protected:
   virtual void ElementDataRemoved() MOZ_OVERRIDE;
   virtual void AddElementData(mozilla::css::CommonElementAnimationData* aData) MOZ_OVERRIDE;
 
 private:
   void ConsiderStartingTransition(nsCSSProperty aProperty,
                                   const nsTransition& aTransition,
                                   mozilla::dom::Element *aElement,
                                   ElementTransitions *&aElementTransitions,
                                   nsStyleContext *aOldStyleContext,
                                   nsStyleContext *aNewStyleContext,
                                   bool *aStartedAny,
                                   nsCSSPropertySet *aWhichStarted);
-  ElementTransitions* GetElementTransitions(mozilla::dom::Element *aElement,
-                                            nsCSSPseudoElements::Type aPseudoType,
-                                            bool aCreateIfNeeded);
   void WalkTransitionRule(ElementDependentRuleProcessorData* aData,
                           nsCSSPseudoElements::Type aPseudoType);
-
   // Update the animated styles of an element and its descendants.
   // If the element has a transition, it is flushed back to its primary frame.
   // If the element does not have a transition, then its style is reparented.
   void UpdateThrottledStylesForSubtree(nsIContent* aContent,
                                        nsStyleContext* aParentStyle,
                                        nsStyleChangeList &aChangeList);
-  // Update the style on aElement from the transition stored in this manager and
-  // the new parent style - aParentStyle. aElement must be transitioning or
-  // animated. Returns the updated style.
-  nsStyleContext* UpdateThrottledStyle(mozilla::dom::Element* aElement,
-                                       nsStyleContext* aParentStyle,
-                                       nsStyleChangeList &aChangeList);
+  void UpdateAllThrottledStylesInternal();
 };
 
 #endif /* !defined(nsTransitionManager_h_) */
--- a/layout/xul/nsMenuFrame.cpp
+++ b/layout/xul/nsMenuFrame.cpp
@@ -693,27 +693,20 @@ nsMenuFrame::CloseMenu(bool aDeselectMen
   nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
   if (pm && HasPopup())
     pm->HidePopup(GetPopup()->GetContent(), false, aDeselectMenu, true);
 }
 
 bool
 nsMenuFrame::IsSizedToPopup(nsIContent* aContent, bool aRequireAlways)
 {
-  bool sizeToPopup;
-  if (aContent->Tag() == nsGkAtoms::select)
-    sizeToPopup = true;
-  else {
-    nsAutoString sizedToPopup;
-    aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::sizetopopup, sizedToPopup);
-    sizeToPopup = sizedToPopup.EqualsLiteral("always") ||
-                  (!aRequireAlways && sizedToPopup.EqualsLiteral("pref"));
-  }
-  
-  return sizeToPopup;
+  nsAutoString sizedToPopup;
+  aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::sizetopopup, sizedToPopup);
+  return sizedToPopup.EqualsLiteral("always") ||
+         (!aRequireAlways && sizedToPopup.EqualsLiteral("pref"));
 }
 
 nsSize
 nsMenuFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
 {
   nsSize size = nsBoxFrame::GetMinSize(aBoxLayoutState);
   DISPLAY_MIN_SIZE(this, size);
 
--- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
+++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp
@@ -35,16 +35,17 @@
 #include "transportflow.h"
 #include "transportlayer.h"
 #include "transportlayerdtls.h"
 #include "transportlayerice.h"
 #include "runnable_utils.h"
 #include "gfxImageSurface.h"
 #include "libyuv/convert.h"
 #include "mozilla/gfx/Point.h"
+#include "mozilla/gfx/Types.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 // Logging context
 MOZ_MTLOG_MODULE("mediapipeline")
 
 namespace mozilla {
@@ -956,37 +957,35 @@ void MediaPipelineTransmit::PipelineList
     int c_size = half_width * half_height;
     int buffer_size = size.width * size.height + 2 * c_size;
     uint8* yuv = (uint8*) malloc(buffer_size);
     if (!yuv)
       return;
 
     int cb_offset = size.width * size.height;
     int cr_offset = cb_offset + c_size;
-    nsRefPtr<gfxImageSurface> surf = rgb->mSurface->GetAsImageSurface();
+    RefPtr<gfx::SourceSurface> tempSurf = rgb->GetAsSourceSurface();
+    RefPtr<gfx::DataSourceSurface> surf = tempSurf->GetDataSurface();
 
-    switch (surf->Format()) {
-      case gfxImageFormatARGB32:
-      case gfxImageFormatRGB24:
-        libyuv::ARGBToI420(static_cast<uint8*>(surf->Data()), surf->Stride(),
+    switch (surf->GetFormat()) {
+      case gfx::SurfaceFormat::B8G8R8A8:
+      case gfx::SurfaceFormat::B8G8R8X8:
+        libyuv::ARGBToI420(static_cast<uint8*>(surf->GetData()), surf->Stride(),
                            yuv, size.width,
                            yuv + cb_offset, half_width,
                            yuv + cr_offset, half_width,
                            size.width, size.height);
         break;
-      case gfxImageFormatRGB16_565:
-        libyuv::RGB565ToI420(static_cast<uint8*>(surf->Data()), surf->Stride(),
+      case gfx::SurfaceFormat::R5G6B5:
+        libyuv::RGB565ToI420(static_cast<uint8*>(surf->GetData()), surf->Stride(),
                              yuv, size.width,
                              yuv + cb_offset, half_width,
                              yuv + cr_offset, half_width,
                              size.width, size.height);
         break;
-      case gfxImageFormatA1:
-      case gfxImageFormatA8:
-      case gfxImageFormatUnknown:
       default:
         MOZ_MTLOG(ML_ERROR, "Unsupported RGB video format");
         MOZ_ASSERT(PR_FALSE);
     }
     conduit->SendVideoFrame(yuv, buffer_size, size.width, size.height, mozilla::kVideoI420, 0);
   } else {
     MOZ_MTLOG(ML_ERROR, "Unsupported video format");
     MOZ_ASSERT(PR_FALSE);
--- a/memory/build/mozmemory_wrap.c
+++ b/memory/build/mozmemory_wrap.c
@@ -83,16 +83,65 @@ strndup_impl(const char *src, size_t len
 MOZ_MEMORY_API char *
 strdup_impl(const char *src)
 {
   size_t len = strlen(src);
   return strndup_impl(src, len);
 }
 #endif /* XP_DARWIN */
 
+#ifdef ANDROID
+#include <stdarg.h>
+
+MOZ_MEMORY_API int
+vasprintf_impl(char **str, const char *fmt, va_list ap)
+{
+  if (str == NULL || fmt == NULL) {
+    return -1;
+  }
+
+  char* ptr = (char*)malloc_impl(128);
+  if (ptr == NULL) {
+    *str = NULL;
+    return -1;
+  }
+
+  int ret = vsnprintf(ptr, 128, fmt, ap);
+  if (ret < 0) {
+    free_impl(ptr);
+    *str = NULL;
+    return -1;
+  }
+
+  char* _ptr = realloc_impl(ptr, ret + 1);
+  if (_ptr == NULL) {
+    free_impl(ptr);
+    *str = NULL;
+    return -1;
+  }
+
+  *str = _ptr;
+
+  return ret;
+}
+
+MOZ_MEMORY_API int
+asprintf_impl(char **str, const char *fmt, ...)
+ {
+   va_list ap;
+   va_start(ap, fmt);
+
+   int ret = vasprintf_impl(str, fmt, ap);
+
+   va_end(ap);
+
+   return ret;
+}
+#endif
+
 #ifdef XP_WIN
 /*
  *  There's a fun allocator mismatch in (at least) the VS 2010 CRT
  *  (see the giant comment in $(topsrcdir)/mozglue/build/Makefile.in)
  *  that gets redirected here to avoid a crash on shutdown.
  */
 void
 dumb_free_thunk(void *ptr)
--- a/memory/build/mozmemory_wrap.h
+++ b/memory/build/mozmemory_wrap.h
@@ -207,14 +207,23 @@
 
 /* Duplication functions */
 #define strndup_impl   mozmem_dup_impl(strndup)
 #define strdup_impl    mozmem_dup_impl(strdup)
 #ifdef XP_WIN
 #  define wcsdup_impl  mozmem_dup_impl(wcsdup)
 #endif
 
+/* String functions */
+#ifdef ANDROID
+/* Bug 801571 and Bug 879668, libstagefright uses vasprintf, causing malloc()/
+ * free() to be mismatched between bionic and mozglue implementation.
+ */
+#define vasprintf_impl  mozmem_dup_impl(vasprintf)
+#define asprintf_impl   mozmem_dup_impl(asprintf)
+#endif
+
 /* Jemalloc specific function */
 #define jemalloc_stats_impl              mozmem_jemalloc_impl(jemalloc_stats)
 #define jemalloc_purge_freed_pages_impl  mozmem_jemalloc_impl(jemalloc_purge_freed_pages)
 #define jemalloc_free_dirty_pages_impl   mozmem_jemalloc_impl(jemalloc_free_dirty_pages)
 
 #endif /* mozmemory_wrap_h */
--- a/mfbt/Compression.h
+++ b/mfbt/Compression.h
@@ -29,17 +29,17 @@ class LZ4
 {
 
 public:
 
   /**
    * Compresses 'inputSize' bytes from 'source' into 'dest'.
    * Destination buffer must be already allocated,
    * and must be sized to handle worst cases situations (input data not compressible)
-   * Worst case size evaluation is provided by function LZ4_compressBound()
+   * Worst case size evaluation is provided by function maxCompressedSize()
    *
    * @param inputSize is the input size. Max supported value is ~1.9GB
    * @param return the number of bytes written in buffer dest
    */
   static MFBT_API size_t compress(const char* source, size_t inputSize, char* dest);
 
   /**
    * Compress 'inputSize' bytes from 'source' into an output buffer
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -97,16 +97,20 @@ pref("network.http.max-persistent-connec
 
 // spdy
 pref("network.http.spdy.push-allowance", 32768);
 
 // See bug 545869 for details on why these are set the way they are
 pref("network.buffer.cache.count", 24);
 pref("network.buffer.cache.size",  16384);
 
+// predictive actions
+pref("network.seer.max-db-size", 2097152); // bytes
+pref("network.seer.preserve", 50); // percentage of seer data to keep when cleaning up
+
 /* history max results display */
 pref("browser.display.history.maxresults", 100);
 
 /* How many times should have passed before the remote tabs list is refreshed */
 pref("browser.display.remotetabs.timeout", 10);
 
 /* session history */
 pref("browser.sessionhistory.max_total_viewers", 1);
@@ -810,11 +814,11 @@ pref("browser.snippets.geoUrl", "https:/
 // URL used to ping metrics with stats about which snippets have been shown
 pref("browser.snippets.statsUrl", "https://snippets-stats.mozilla.org/mobile");
 
 // This pref requires a restart to take effect.
 pref("browser.snippets.enabled", false);
 
 #ifdef MOZ_ANDROID_SYNTHAPKS
 // The URL of the APK factory from which we obtain APKs for webapps.
-// XXX This currently points to jhugman's prototype server.
-pref("browser.webapps.apkFactoryUrl", "http://107.22.148.17:8080/application.apk");
+// This currently points to the development server.
+pref("browser.webapps.apkFactoryUrl", "http://dapk.net/application.apk");
 #endif
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -214,44 +214,17 @@ public class GeckoAppShell
     public static native Message getNextMessageFromQueue(MessageQueue queue);
     public static native void onSurfaceTextureFrameAvailable(Object surfaceTexture, int id);
     public static native void dispatchMemoryPressure();
 
     public static void registerGlobalExceptionHandler() {
         Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
             @Override
             public void uncaughtException(Thread thread, Throwable e) {
-                // If the uncaught exception was rethrown, walk the exception `cause` chain to find
-                // the original exception so Socorro can correctly collate related crash reports.
-                Throwable cause;
-                while ((cause = e.getCause()) != null) {
-                    e = cause;
-                }
-
-                try {
-                    Log.e(LOGTAG, ">>> REPORTING UNCAUGHT EXCEPTION FROM THREAD "
-                                  + thread.getId() + " (\"" + thread.getName() + "\")", e);
-
-                    Thread mainThread = ThreadUtils.getUiThread();
-                    if (mainThread != null && thread != mainThread) {
-                        Log.e(LOGTAG, "Main thread stack:");
-                        for (StackTraceElement ste : mainThread.getStackTrace()) {
-                            Log.e(LOGTAG, ste.toString());
-                        }
-                    }
-
-                    if (e instanceof OutOfMemoryError) {
-                        SharedPreferences prefs = getSharedPreferences();
-                        SharedPreferences.Editor editor = prefs.edit();
-                        editor.putBoolean(GeckoApp.PREFS_OOM_EXCEPTION, true);
-                        editor.commit();
-                    }
-                } finally {
-                    reportJavaCrash(getStackTraceString(e));
-                }
+                handleUncaughtException(thread, e);
             }
         });
     }
 
     private static String getStackTraceString(Throwable e) {
         StringWriter sw = new StringWriter();
         PrintWriter pw = new PrintWriter(sw);
         e.printStackTrace(pw);
@@ -413,16 +386,52 @@ public class GeckoAppShell
     }
 
     // Tell the Gecko event loop that an event is available.
     public static native void notifyGeckoOfEvent(GeckoEvent event);
 
     /*
      *  The Gecko-side API: API methods that Gecko calls
      */
+
+    @WrapElementForJNI(generateStatic = true, noThrow = true)
+    public static void handleUncaughtException(Thread thread, Throwable e) {
+        if (thread == null) {
+            thread = Thread.currentThread();
+        }
+        // If the uncaught exception was rethrown, walk the exception `cause` chain to find
+        // the original exception so Socorro can correctly collate related crash reports.
+        Throwable cause;
+        while ((cause = e.getCause()) != null) {
+            e = cause;
+        }
+
+        try {
+            Log.e(LOGTAG, ">>> REPORTING UNCAUGHT EXCEPTION FROM THREAD "
+                          + thread.getId() + " (\"" + thread.getName() + "\")", e);
+
+            Thread mainThread = ThreadUtils.getUiThread();
+            if (mainThread != null && thread != mainThread) {
+                Log.e(LOGTAG, "Main thread stack:");
+                for (StackTraceElement ste : mainThread.getStackTrace()) {
+                    Log.e(LOGTAG, ste.toString());
+                }
+            }
+
+            if (e instanceof OutOfMemoryError) {
+                SharedPreferences prefs = getSharedPreferences();
+                SharedPreferences.Editor editor = prefs.edit();
+                editor.putBoolean(GeckoApp.PREFS_OOM_EXCEPTION, true);
+                editor.commit();
+            }
+        } finally {
+            reportJavaCrash(getStackTraceString(e));
+        }
+    }
+
     @WrapElementForJNI(generateStatic = true)
     public static void notifyIME(int type) {
         if (mEditableListener != null) {
             mEditableListener.notifyIME(type);
         }
     }
 
     @WrapElementForJNI(generateStatic = true)
--- a/mobile/android/base/mozglue/generatorannotations/WrapElementForJNI.java
+++ b/mobile/android/base/mozglue/generatorannotations/WrapElementForJNI.java
@@ -33,9 +33,15 @@ public @interface WrapElementForJNI {
     /**
      * If set, the generated method stub will support being called from any thread via the use of
      * GetJNIForThread. This is rarely useful, at time of writing, as well as possibly risky.
      * See information in AndroidBridge.cpp regarding GetJNIForThread.
      *
      * Did I mention use of this function is discouraged?
      */
     boolean allowMultithread() default false;
+
+    /**
+     * If set, the generated stub will not handle uncaught exceptions.
+     * Any exception must be handled or cleared by the code calling the stub.
+     */
+    boolean noThrow() default false;
 }
--- a/mobile/android/components/build/nsAndroidHistory.cpp
+++ b/mobile/android/components/build/nsAndroidHistory.cpp
@@ -57,17 +57,19 @@ nsAndroidHistory::RegisterVisitedCallbac
 
   nsTArray<Link*>* list = mListeners.Get(uriString);
   if (! list) {
     list = new nsTArray<Link*>();
     mListeners.Put(uriString, list);
   }
   list->AppendElement(aContent);
 
- GeckoAppShell::CheckURIVisited(uriString);
+  if (AndroidBridge::HasEnv()) {
+    GeckoAppShell::CheckURIVisited(uriString);
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidHistory::UnregisterVisitedCallback(nsIURI *aURI, Link *aContent)
 {
   if (!aContent || !aURI)
@@ -168,21 +170,23 @@ nsAndroidHistory::VisitURI(nsIURI *aURI,
   }
 
   if (aFlags & VisitFlags::REDIRECT_SOURCE)
     return NS_OK;
 
   if (aFlags & VisitFlags::UNRECOVERABLE_ERROR)
     return NS_OK;
 
-  nsAutoCString uri;
-  rv = aURI->GetSpec(uri);
-  if (NS_FAILED(rv)) return rv;
-  NS_ConvertUTF8toUTF16 uriString(uri);
-  GeckoAppShell::MarkURIVisited(uriString);
+  if (AndroidBridge::HasEnv()) {
+    nsAutoCString uri;
+    rv = aURI->GetSpec(uri);
+    if (NS_FAILED(rv)) return rv;
+    NS_ConvertUTF8toUTF16 uriString(uri);
+    GeckoAppShell::MarkURIVisited(uriString);
+  }
 
   AppendToRecentlyVisitedURIs(aURI);
 
   // Finally, notify that we've been visited.
   nsCOMPtr<nsIObserverService> obsService =
     mozilla::services::GetObserverService();
   if (obsService) {
     obsService->NotifyObservers(aURI, NS_LINK_VISITED_EVENT_TOPIC, nullptr);
@@ -201,17 +205,17 @@ nsAndroidHistory::SetURITitle(nsIURI *aU
   if (!canAdd) {
     return NS_OK;
   }
 
   if (IsEmbedURI(aURI)) {
     return NS_OK;
   }
 
-  if (AndroidBridge::Bridge()) {
+  if (AndroidBridge::HasEnv()) {
     nsAutoCString uri;
     nsresult rv = aURI->GetSpec(uri);
     if (NS_FAILED(rv)) return rv;
     NS_ConvertUTF8toUTF16 uriString(uri);
     GeckoAppShell::SetURITitle(uriString, aTitle);
   }
   return NS_OK;
 }
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -224,18 +224,18 @@ pref("media.apple.mp3.enabled", true);
 pref("media.navigator.enabled", true);
 pref("media.navigator.video.enabled", true);
 pref("media.navigator.load_adapt", false);
 pref("media.navigator.video.default_width",640);
 pref("media.navigator.video.default_height",480);
 pref("media.navigator.video.default_fps",30);
 pref("media.navigator.video.default_minfps",10);
 #ifdef MOZ_WIDGET_GONK
-pref("media.peerconnection.enabled", false);
-pref("media.peerconnection.video.enabled", false);
+pref("media.peerconnection.enabled", true);
+pref("media.peerconnection.video.enabled", true);
 pref("media.navigator.video.max_fs", 1200); // 640x480 == 1200mb
 pref("media.navigator.video.max_fr", 30);
 #else
 pref("media.peerconnection.enabled", true);
 pref("media.peerconnection.video.enabled", true);
 pref("media.navigator.video.max_fs", 0); // unrestricted
 pref("media.navigator.video.max_fr", 0); // unrestricted
 #endif
@@ -1268,16 +1268,18 @@ pref("network.seer.subresource-degradati
 pref("network.seer.subresource-degradation.week", 10);
 pref("network.seer.subresource-degradation.month", 25);
 pref("network.seer.subresource-degradation.year", 50);
 pref("network.seer.subresource-degradation.max", 100);
 pref("network.seer.preconnect-min-confidence", 90);
 pref("network.seer.preresolve-min-confidence", 60);
 pref("network.seer.redirect-likely-confidence", 75);
 pref("network.seer.max-queue-size", 50);
+pref("network.seer.max-db-size", 157286400); // bytes
+pref("network.seer.preserve", 80); // percentage of seer data to keep when cleaning up
 
 
 // The following prefs pertain to the negotiate-auth extension (see bug 17578),
 // which provides transparent Kerberos or NTLM authentication using the SPNEGO
 // protocol.  Each pref is a comma-separated list of keys, where each key has
 // the format:
 //   [scheme "://"] [host [":" port]]
 // For example, "foo.com" would match "http://www.foo.com/bar", etc.
--- a/netwerk/base/public/nsINetworkSeer.idl
+++ b/netwerk/base/public/nsINetworkSeer.idl
@@ -12,17 +12,17 @@ interface nsINetworkSeerVerifier;
 typedef unsigned long SeerPredictReason;
 typedef unsigned long SeerLearnReason;
 
 /**
  * nsINetworkSeer - learn about pages users visit, and allow us to take
  *                  predictive actions upon future visits.
  *                  NOTE: nsINetworkSeer should only be used on the main thread
  */
-[scriptable, uuid(884a39a0-a3ed-4855-826a-fabb73ae878d)]
+[scriptable, uuid(25e323b6-99e0-4274-b5b3-1a9eb56e28ac)]
 interface nsINetworkSeer : nsISupports
 {
   /**
    * Prediction reasons
    *
    * PREDICT_LINK - we are being asked to take predictive action because
    * the user is hovering over a link.
    *
@@ -116,16 +116,22 @@ interface nsINetworkSeer : nsISupports
 
   /**
    * Clear out all our learned knowledge
    *
    * This removes everything from our database so that any predictions begun
    * after this completes will start from a blank slate.
    */
   void reset();
+
+  /**
+   * @deprecated THIS API IS FOR TESTING ONLY. IF YOU DON'T KNOW WHAT IT DOES,
+   * DON'T USE IT
+   */
+  void prepareForDnsTest(in long long timestamp, in string uri);
 };
 
 %{C++
 // Wrapper functions to make use of the seer easier and less invasive
 class nsIChannel;
 class nsIDocument;
 class nsILoadContext;
 class nsILoadGroup;
--- a/netwerk/base/src/Seer.cpp
+++ b/netwerk/base/src/Seer.cpp
@@ -16,16 +16,17 @@
 #include "nsIFile.h"
 #include "nsILoadContext.h"
 #include "nsILoadGroup.h"
 #include "nsINetworkSeerVerifier.h"
 #include "nsIObserverService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsISpeculativeConnect.h"
+#include "nsITimer.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
@@ -94,16 +95,21 @@ const char SEER_PRERESOLVE_MIN_PREF[] =
 const int PRERESOLVE_MIN_DEFAULT = 60;
 const char SEER_REDIRECT_LIKELY_PREF[] =
   "network.seer.redirect-likely-confidence";
 const int REDIRECT_LIKELY_DEFAULT = 75;
 
 const char SEER_MAX_QUEUE_SIZE_PREF[] = "network.seer.max-queue-size";
 const uint32_t SEER_MAX_QUEUE_SIZE_DEFAULT = 50;
 
+const char SEER_MAX_DB_SIZE_PREF[] = "network.seer.max-db-size";
+const int32_t SEER_MAX_DB_SIZE_DEFAULT_BYTES = 150 * 1024 * 1024;
+const char SEER_PRESERVE_PERCENTAGE_PREF[] = "network.seer.preserve";
+const int32_t SEER_PRESERVE_PERCENTAGE_DEFAULT = 80;
+
 // All these time values are in usec
 const long long ONE_DAY = 86400LL * 1000000LL;
 const long long ONE_WEEK = 7LL * ONE_DAY;
 const long long ONE_MONTH = 30LL * ONE_DAY;
 const long long ONE_YEAR = 365LL * ONE_DAY;
 
 const long STARTUP_WINDOW = 5L * 60L * 1000000L; // 5min
 
@@ -186,16 +192,20 @@ Seer::Seer()
   ,mPreresolveMinConfidence(PRERESOLVE_MIN_DEFAULT)
   ,mRedirectLikelyConfidence(REDIRECT_LIKELY_DEFAULT)
   ,mMaxQueueSize(SEER_MAX_QUEUE_SIZE_DEFAULT)
   ,mStatements(mDB)
   ,mLastStartupTime(0)
   ,mStartupCount(0)
   ,mQueueSize(0)
   ,mQueueSizeLock("Seer.mQueueSizeLock")
+  ,mCleanupScheduled(false)
+  ,mMaxDBSize(SEER_MAX_DB_SIZE_DEFAULT_BYTES)
+  ,mPreservePercentage(SEER_PRESERVE_PERCENTAGE_DEFAULT)
+  ,mLastCleanupTime(0)
 {
 #if defined(PR_LOGGING)
   gSeerLog = PR_NewLogModule("NetworkSeer");
 #endif
 
   MOZ_ASSERT(!gSeer, "multiple Seer instances!");
   gSeer = this;
 }
@@ -270,39 +280,84 @@ Seer::InstallObserver()
                               PRERESOLVE_MIN_DEFAULT);
   Preferences::AddIntVarCache(&mRedirectLikelyConfidence,
                               SEER_REDIRECT_LIKELY_PREF,
                               REDIRECT_LIKELY_DEFAULT);
 
   Preferences::AddIntVarCache(&mMaxQueueSize, SEER_MAX_QUEUE_SIZE_PREF,
                               SEER_MAX_QUEUE_SIZE_DEFAULT);
 
+  Preferences::AddIntVarCache(&mMaxDBSize, SEER_MAX_DB_SIZE_PREF,
+                              SEER_MAX_DB_SIZE_DEFAULT_BYTES);
+  Preferences::AddIntVarCache(&mPreservePercentage,
+                              SEER_PRESERVE_PERCENTAGE_PREF,
+                              SEER_PRESERVE_PERCENTAGE_DEFAULT);
+
   return rv;
 }
 
 void
 Seer::RemoveObserver()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Removing observer off main thread");
 
   nsCOMPtr<nsIObserverService> obs =
     mozilla::services::GetObserverService();
   if (obs) {
     obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
   }
 }
 
+static const uint32_t COMMIT_TIMER_DELTA_MS = 5 * 1000;
+
+class SeerCommitTimerInitEvent : public nsRunnable
+{
+public:
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    nsresult rv = NS_OK;
+
+    if (!gSeer->mCommitTimer) {
+      gSeer->mCommitTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
+    } else {
+      gSeer->mCommitTimer->Cancel();
+    }
+    if (NS_SUCCEEDED(rv)) {
+      gSeer->mCommitTimer->Init(gSeer, COMMIT_TIMER_DELTA_MS,
+                                nsITimer::TYPE_ONE_SHOT);
+    }
+
+    return NS_OK;
+  }
+};
+
+class SeerNewTransactionEvent : public nsRunnable
+{
+  NS_IMETHODIMP Run() MOZ_OVERRIDE
+  {
+    gSeer->CommitTransaction();
+    gSeer->BeginTransaction();
+    gSeer->MaybeScheduleCleanup();
+    nsRefPtr<SeerCommitTimerInitEvent> event = new SeerCommitTimerInitEvent();
+    NS_DispatchToMainThread(event);
+    return NS_OK;
+  }
+};
+
 NS_IMETHODIMP
 Seer::Observe(nsISupports *subject, const char *topic,
               const char16_t *data_unicode)
 {
   nsresult rv = NS_OK;
 
   if (!strcmp(NS_XPCOM_SHUTDOWN_OBSERVER_ID, topic)) {
     gSeer->Shutdown();
+  } else if (!strcmp(NS_TIMER_CALLBACK_TOPIC, topic)) {
+    nsRefPtr<SeerNewTransactionEvent> event = new SeerNewTransactionEvent();
+    gSeer->mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
   }
 
   return rv;
 }
 
 // Seer::nsISpeculativeConnectionOverrider
 
 NS_IMETHODIMP
@@ -462,16 +517,18 @@ Seer::EnsureInitStorage()
 
     rv = mStorageService->OpenDatabase(mDBFile, getter_AddRefs(mDB));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA synchronous = OFF;"));
   mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA foreign_keys = ON;"));
 
+  BeginTransaction();
+
   // A table to make sure we're working with the database layout we expect
   rv = mDB->ExecuteSimpleSQL(
       NS_LITERAL_CSTRING("CREATE TABLE IF NOT EXISTS moz_seer_version (\n"
                          "  version INTEGER NOT NULL\n"
                          ");\n"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<mozIStorageStatement> stmt;
@@ -528,16 +585,21 @@ Seer::EnsureInitStorage()
                          "ON moz_hosts (id, origin);"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mDB->ExecuteSimpleSQL(
       NS_LITERAL_CSTRING("CREATE INDEX IF NOT EXISTS host_origin_index "
                          "ON moz_hosts (origin);"));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  rv = mDB->ExecuteSimpleSQL(
+      NS_LITERAL_CSTRING("CREATE INDEX IF NOT EXISTS host_load_index "
+                         "ON moz_hosts (last_load);"));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // And this is the table that keeps track of the hosts for subresources of a
   // pageload.
   rv = mDB->ExecuteSimpleSQL(
       NS_LITERAL_CSTRING("CREATE TABLE IF NOT EXISTS moz_subhosts (\n"
                          "  id INTEGER PRIMARY KEY AUTOINCREMENT,\n"
                          "  hid INTEGER NOT NULL,\n"
                          "  origin TEXT NOT NULL,\n"
                          "  hits INTEGER DEFAULT 0,\n"
@@ -629,16 +691,21 @@ Seer::EnsureInitStorage()
                          ");\n"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mDB->ExecuteSimpleSQL(
       NS_LITERAL_CSTRING("CREATE INDEX IF NOT EXISTS startup_page_uri_index "
                          "ON moz_startup_pages (uri);"));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  rv = mDB->ExecuteSimpleSQL(
+      NS_LITERAL_CSTRING("CREATE INDEX IF NOT EXISTS startup_page_hit_index "
+                         "ON moz_startup_pages (last_hit);"));
+  NS_ENSURE_SUCCESS(rv, rv);
+
   // This table is similar to moz_hosts above, but uses full URIs instead of
   // hosts so that we can get more specific predictions for URIs that people
   // visit often (such as their email or social network home pages).
   rv = mDB->ExecuteSimpleSQL(
       NS_LITERAL_CSTRING("CREATE TABLE IF NOT EXISTS moz_pages (\n"
                          "  id integer PRIMARY KEY AUTOINCREMENT,\n"
                          "  uri TEXT NOT NULL,\n"
                          "  loads INTEGER DEFAULT 0,\n"
@@ -698,16 +765,22 @@ Seer::EnsureInitStorage()
                          "ON moz_redirects (pid, uri);"));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mDB->ExecuteSimpleSQL(
       NS_LITERAL_CSTRING("CREATE INDEX IF NOT EXISTS redirect_id_index "
                          "ON moz_redirects (id);"));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  CommitTransaction();
+  BeginTransaction();
+
+  nsRefPtr<SeerCommitTimerInitEvent> event = new SeerCommitTimerInitEvent();
+  NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
+
   return NS_OK;
 }
 
 class SeerThreadShutdownRunner : public nsRunnable
 {
 public:
   SeerThreadShutdownRunner(nsIThread *ioThread)
     :mIOThread(ioThread)
@@ -732,16 +805,19 @@ public:
   {
     mSeer = new nsMainThreadPtrHolder<nsINetworkSeer>(seer);
   }
 
   NS_IMETHODIMP Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(!NS_IsMainThread(), "Shutting down DB on main thread");
 
+    // Ensure everything is written to disk before we shut down the db
+    gSeer->CommitTransaction();
+
     gSeer->mStatements.FinalizeStatements();
     gSeer->mDB->Close();
     gSeer->mDB = nullptr;
 
     nsRefPtr<SeerThreadShutdownRunner> runner =
       new SeerThreadShutdownRunner(mIOThread);
     NS_DispatchToMainThread(runner);
 
@@ -760,16 +836,20 @@ Seer::Shutdown()
 {
   if (!NS_IsMainThread()) {
     MOZ_ASSERT(false, "Seer::Shutdown called off the main thread!");
     return;
   }
 
   mInitialized = false;
 
+  if (mCommitTimer) {
+    mCommitTimer->Cancel();
+  }
+
   if (mIOThread) {
     nsCOMPtr<nsIThread> ioThread;
     mIOThread.swap(ioThread);
 
     if (mDB) {
       nsRefPtr<SeerDBShutdownRunner> runner =
         new SeerDBShutdownRunner(ioThread, this);
       ioThread->Dispatch(runner, NS_DISPATCH_NORMAL);
@@ -885,16 +965,18 @@ public:
         rv = NS_ERROR_UNEXPECTED;
     }
 
     gSeer->FreeSpaceInQueue();
 
     Telemetry::AccumulateTimeDelta(Telemetry::SEER_PREDICT_WORK_TIME,
                                    startTime);
 
+    gSeer->MaybeScheduleCleanup();
+
     return rv;
   }
 
 private:
   Seer::UriInfo mTargetURI;
   Seer::UriInfo mSourceURI;
   SeerPredictReason mReason;
   SeerVerifierHandle mVerifier;
@@ -1666,16 +1748,18 @@ public:
       MOZ_ASSERT(false, "Got unexpected value for learn reason");
       rv = NS_ERROR_UNEXPECTED;
     }
 
     gSeer->FreeSpaceInQueue();
 
     Telemetry::AccumulateTimeDelta(Telemetry::SEER_LEARN_WORK_TIME, startTime);
 
+    gSeer->MaybeScheduleCleanup();
+
     return rv;
   }
 private:
   Seer::UriInfo mTargetURI;
   Seer::UriInfo mSourceURI;
   SeerLearnReason mReason;
   TimeStamp mEnqueueTime;
 };
@@ -2147,23 +2231,29 @@ public:
 void
 Seer::ResetInternal()
 {
   MOZ_ASSERT(!NS_IsMainThread(), "Resetting db on main thread");
 
   nsresult rv = EnsureInitStorage();
   RETURN_IF_FAILED(rv);
 
-  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_redirects"));
-  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_startup_pages"));
-  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_startups"));
+  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_redirects;"));
+  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_startup_pages;"));
+  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_startups;"));
 
   // These cascade to moz_subresources and moz_subhosts, respectively.
-  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_pages"));
-  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_hosts"));
+  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_pages;"));
+  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_hosts;"));
+
+  VacuumDatabase();
+
+  // Go ahead and ensure this is flushed to disk
+  CommitTransaction();
+  BeginTransaction();
 }
 
 // Called on the main thread to clear out all our knowledge. Tabula Rasa FTW!
 NS_IMETHODIMP
 Seer::Reset()
 {
   MOZ_ASSERT(NS_IsMainThread(),
              "Seer interface methods must be called on the main thread");
@@ -2171,16 +2261,419 @@ Seer::Reset()
   if (!mInitialized) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsRefPtr<SeerResetEvent> event = new SeerResetEvent();
   return mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
 }
 
+class SeerCleanupEvent : public nsRunnable
+{
+public:
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    gSeer->Cleanup();
+    gSeer->mCleanupScheduled = false;
+    return NS_OK;
+  }
+};
+
+// Returns the current size (in bytes) of the db file on disk
+int64_t
+Seer::GetDBFileSize()
+{
+  MOZ_ASSERT(!NS_IsMainThread(), "GetDBFileSize called on main thread!");
+
+  CommitTransaction();
+
+  nsCOMPtr<mozIStorageStatement> countStmt = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("PRAGMA page_count;"));
+  if (!countStmt) {
+    return 0;
+  }
+  mozStorageStatementScoper scopedCount(countStmt);
+  bool hasRows;
+  nsresult rv = countStmt->ExecuteStep(&hasRows);
+  if (NS_FAILED(rv) || !hasRows) {
+    return 0;
+  }
+  int64_t pageCount;
+  rv = countStmt->GetInt64(0, &pageCount);
+  if (NS_FAILED(rv)) {
+    return 0;
+  }
+
+  nsCOMPtr<mozIStorageStatement> sizeStmt = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("PRAGMA page_size;"));
+  if (!sizeStmt) {
+    return 0;
+  }
+  mozStorageStatementScoper scopedSize(sizeStmt);
+  rv = sizeStmt->ExecuteStep(&hasRows);
+  if (NS_FAILED(rv) || !hasRows) {
+    return 0;
+  }
+  int64_t pageSize;
+  rv = sizeStmt->GetInt64(0, &pageSize);
+  if (NS_FAILED(rv)) {
+    return 0;
+  }
+
+  BeginTransaction();
+
+  return pageCount * pageSize;
+}
+
+// Returns the size (in bytes) that the db file will consume on disk AFTER we
+// vacuum the db.
+int64_t
+Seer::GetDBFileSizeAfterVacuum()
+{
+  MOZ_ASSERT(!NS_IsMainThread(), "GetDBFileSizeAfterVacuum called on main thread!");
+
+  CommitTransaction();
+
+  nsCOMPtr<mozIStorageStatement> countStmt = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("PRAGMA page_count;"));
+  if (!countStmt) {
+    return 0;
+  }
+  mozStorageStatementScoper scopedCount(countStmt);
+  bool hasRows;
+  nsresult rv = countStmt->ExecuteStep(&hasRows);
+  if (NS_FAILED(rv) || !hasRows) {
+    return 0;
+  }
+  int64_t pageCount;
+  rv = countStmt->GetInt64(0, &pageCount);
+  if (NS_FAILED(rv)) {
+    return 0;
+  }
+
+  nsCOMPtr<mozIStorageStatement> sizeStmt = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("PRAGMA page_size;"));
+  if (!sizeStmt) {
+    return 0;
+  }
+  mozStorageStatementScoper scopedSize(sizeStmt);
+  rv = sizeStmt->ExecuteStep(&hasRows);
+  if (NS_FAILED(rv) || !hasRows) {
+    return 0;
+  }
+  int64_t pageSize;
+  rv = sizeStmt->GetInt64(0, &pageSize);
+  if (NS_FAILED(rv)) {
+    return 0;
+  }
+
+  nsCOMPtr<mozIStorageStatement> freeStmt = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("PRAGMA freelist_count;"));
+  if (!freeStmt) {
+    return 0;
+  }
+  mozStorageStatementScoper scopedFree(freeStmt);
+  rv = freeStmt->ExecuteStep(&hasRows);
+  if (NS_FAILED(rv) || !hasRows) {
+    return 0;
+  }
+  int64_t freelistCount;
+  rv = freeStmt->GetInt64(0, &freelistCount);
+  if (NS_FAILED(rv)) {
+    return 0;
+  }
+
+  BeginTransaction();
+
+  return (pageCount - freelistCount) * pageSize;
+}
+
+void
+Seer::MaybeScheduleCleanup()
+{
+  MOZ_ASSERT(!NS_IsMainThread(), "MaybeScheduleCleanup called on main thread!");
+
+  if (mCleanupScheduled) {
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_SCHEDULED, false);
+    return;
+  }
+
+  int64_t dbFileSize = GetDBFileSize();
+  if (dbFileSize < mMaxDBSize) {
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_SCHEDULED, false);
+    return;
+  }
+
+  mCleanupScheduled = true;
+
+  nsRefPtr<SeerCleanupEvent> event = new SeerCleanupEvent();
+  nsresult rv = mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
+  if (NS_FAILED(rv)) {
+    mCleanupScheduled = false;
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_SCHEDULED, false);
+  } else {
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_SCHEDULED, true);
+  }
+}
+
+#ifndef ANDROID
+static const long long CLEANUP_CUTOFF = ONE_MONTH;
+#else
+static const long long CLEANUP_CUTOFF = ONE_WEEK;
+#endif
+
+void
+Seer::CleanupOrigins(PRTime now)
+{
+  PRTime cutoff = now - CLEANUP_CUTOFF;
+
+  nsCOMPtr<mozIStorageStatement> deleteOrigins = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("DELETE FROM moz_hosts WHERE last_load <= :cutoff"));
+  if (!deleteOrigins) {
+    return;
+  }
+  mozStorageStatementScoper scopedOrigins(deleteOrigins);
+
+  nsresult rv = deleteOrigins->BindInt32ByName(NS_LITERAL_CSTRING("cutoff"),
+                                               cutoff);
+  RETURN_IF_FAILED(rv);
+
+  deleteOrigins->Execute();
+}
+
+void
+Seer::CleanupStartupPages(PRTime now)
+{
+  PRTime cutoff = now - ONE_WEEK;
+
+  nsCOMPtr<mozIStorageStatement> deletePages = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("DELETE FROM moz_startup_pages WHERE "
+                         "last_hit <= :cutoff"));
+  if (!deletePages) {
+    return;
+  }
+  mozStorageStatementScoper scopedPages(deletePages);
+
+  nsresult rv = deletePages->BindInt32ByName(NS_LITERAL_CSTRING("cutoff"),
+                                             cutoff);
+  RETURN_IF_FAILED(rv);
+
+  deletePages->Execute();
+}
+
+int32_t
+Seer::GetSubresourceCount()
+{
+  nsCOMPtr<mozIStorageStatement> count = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("SELECT COUNT(id) FROM moz_subresources"));
+  if (!count) {
+    return 0;
+  }
+  mozStorageStatementScoper scopedCount(count);
+
+  bool hasRows;
+  nsresult rv = count->ExecuteStep(&hasRows);
+  if (NS_FAILED(rv) || !hasRows) {
+    return 0;
+  }
+
+  int32_t subresourceCount = 0;
+  count->GetInt32(0, &subresourceCount);
+
+  return subresourceCount;
+}
+
+void
+Seer::Cleanup()
+{
+  MOZ_ASSERT(!NS_IsMainThread(), "Seer::Cleanup called on main thread!");
+
+  nsresult rv = EnsureInitStorage();
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
+  int64_t dbFileSize = GetDBFileSize();
+  float preservePercentage = static_cast<float>(mPreservePercentage) / 100.0;
+  int64_t evictionCutoff = static_cast<int64_t>(mMaxDBSize) * preservePercentage;
+  if (dbFileSize < evictionCutoff) {
+    return;
+  }
+
+  CommitTransaction();
+  BeginTransaction();
+
+  PRTime now = PR_Now();
+  if (mLastCleanupTime) {
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_DELTA,
+                          (now - mLastCleanupTime) / 1000);
+  }
+  mLastCleanupTime = now;
+
+  CleanupOrigins(now);
+  CleanupStartupPages(now);
+
+  dbFileSize = GetDBFileSizeAfterVacuum();
+  if (dbFileSize < evictionCutoff) {
+    // We've deleted enough stuff, time to free up the disk space and be on
+    // our way.
+    VacuumDatabase();
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_SUCCEEDED, true);
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_TIME,
+                          (PR_Now() - mLastCleanupTime) / 1000);
+    return;
+  }
+
+  bool canDelete = true;
+  while (canDelete && (dbFileSize >= evictionCutoff)) {
+    int32_t subresourceCount = GetSubresourceCount();
+    if (!subresourceCount) {
+      canDelete = false;
+      break;
+    }
+
+    // DB size scales pretty much linearly with the number of rows in
+    // moz_subresources, so we can guess how many rows we need to delete pretty
+    // accurately.
+    float percentNeeded = static_cast<float>(dbFileSize - evictionCutoff) /
+      static_cast<float>(dbFileSize);
+
+    int32_t subresourcesToDelete = static_cast<int32_t>(percentNeeded * subresourceCount);
+    if (!subresourcesToDelete) {
+      // We're getting pretty close to nothing here, anyway, so we may as well
+      // just trash it all. This delete cascades to moz_subresources, as well.
+      rv = mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_pages;"));
+      if (NS_FAILED(rv)) {
+        canDelete = false;
+        break;
+      }
+    } else {
+      nsCOMPtr<mozIStorageStatement> deleteStatement = mStatements.GetCachedStatement(
+          NS_LITERAL_CSTRING("DELETE FROM moz_subresources WHERE id IN "
+                            "(SELECT id FROM moz_subresources ORDER BY "
+                            "last_hit ASC LIMIT :limit);"));
+      if (!deleteStatement) {
+        canDelete = false;
+        break;
+      }
+      mozStorageStatementScoper scopedDelete(deleteStatement);
+
+      rv = deleteStatement->BindInt32ByName(NS_LITERAL_CSTRING("limit"),
+                                            subresourcesToDelete);
+      if (NS_FAILED(rv)) {
+        canDelete = false;
+        break;
+      }
+
+      rv = deleteStatement->Execute();
+      if (NS_FAILED(rv)) {
+        canDelete = false;
+        break;
+      }
+
+      // Now we clean up pages that no longer reference any subresources
+      rv = mDB->ExecuteSimpleSQL(
+          NS_LITERAL_CSTRING("DELETE FROM moz_pages WHERE id NOT IN "
+                             "(SELECT DISTINCT(pid) FROM moz_subresources);"));
+      if (NS_FAILED(rv)) {
+        canDelete = false;
+        break;
+      }
+    }
+
+    if (canDelete) {
+      dbFileSize = GetDBFileSizeAfterVacuum();
+    }
+  }
+
+  if (!canDelete || (dbFileSize >= evictionCutoff)) {
+    // Last-ditch effort to free up space
+    ResetInternal();
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_SUCCEEDED, false);
+  } else {
+    // We do this to actually free up the space on disk
+    VacuumDatabase();
+    Telemetry::Accumulate(Telemetry::SEER_CLEANUP_SUCCEEDED, true);
+  }
+  Telemetry::Accumulate(Telemetry::SEER_CLEANUP_TIME,
+                        (PR_Now() - mLastCleanupTime) / 1000);
+}
+
+void
+Seer::VacuumDatabase()
+{
+  MOZ_ASSERT(!NS_IsMainThread(), "VacuumDatabase called on main thread!");
+
+  CommitTransaction();
+  mDB->ExecuteSimpleSQL(NS_LITERAL_CSTRING("VACUUM;"));
+  BeginTransaction();
+}
+
+#ifdef SEER_TESTS
+class SeerPrepareForDnsTestEvent : public nsRunnable
+{
+public:
+  SeerPrepareForDnsTestEvent(int64_t timestamp, const char *uri)
+    :mTimestamp(timestamp)
+    ,mUri(uri)
+  { }
+
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(!NS_IsMainThread(), "Preparing for DNS Test on main thread!");
+    gSeer->PrepareForDnsTestInternal(mTimestamp, mUri);
+    return NS_OK;
+  }
+
+private:
+  int64_t mTimestamp;
+  nsAutoCString mUri;
+};
+
+void
+Seer::PrepareForDnsTestInternal(int64_t timestamp, const nsACString &uri)
+{
+  nsCOMPtr<mozIStorageStatement> update = mStatements.GetCachedStatement(
+      NS_LITERAL_CSTRING("UPDATE moz_subresources SET last_hit = :timestamp, "
+                          "hits = 2 WHERE uri = :uri;"));
+  if (!update) {
+    return;
+  }
+  mozStorageStatementScoper scopedUpdate(update);
+
+  nsresult rv = update->BindInt64ByName(NS_LITERAL_CSTRING("timestamp"),
+                                        timestamp);
+  RETURN_IF_FAILED(rv);
+
+  rv = update->BindUTF8StringByName(NS_LITERAL_CSTRING("uri"), uri);
+  RETURN_IF_FAILED(rv);
+
+  update->Execute();
+}
+#endif
+
+NS_IMETHODIMP
+Seer::PrepareForDnsTest(int64_t timestamp, const char *uri)
+{
+#ifdef SEER_TESTS
+  MOZ_ASSERT(NS_IsMainThread(),
+             "Seer interface methods must be called on the main thread");
+
+  if (!mInitialized) {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+
+  nsRefPtr<SeerPrepareForDnsTestEvent> event =
+    new SeerPrepareForDnsTestEvent(timestamp, uri);
+  return mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);
+#else
+  return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
 // Helper functions to make using the seer easier from native code
 
 static nsresult
 EnsureGlobalSeer(nsINetworkSeer **aSeer)
 {
   nsresult rv;
   nsCOMPtr<nsINetworkSeer> seer = do_GetService("@mozilla.org/network/seer;1",
                                                 &rv);
--- a/netwerk/base/src/Seer.h
+++ b/netwerk/base/src/Seer.h
@@ -17,16 +17,17 @@
 
 #include "mozilla/Mutex.h"
 #include "mozilla/storage/StatementCache.h"
 #include "mozilla/TimeStamp.h"
 
 class nsIDNSService;
 class nsINetworkSeerVerifier;
 class nsIThread;
+class nsITimer;
 
 class mozIStorageConnection;
 class mozIStorageService;
 class mozIStorageStatement;
 
 namespace mozilla {
 namespace net {
 
@@ -56,16 +57,19 @@ public:
   static nsresult Create(nsISupports *outer, const nsIID& iid, void **result);
 
 private:
   friend class SeerPredictionEvent;
   friend class SeerLearnEvent;
   friend class SeerResetEvent;
   friend class SeerPredictionRunner;
   friend class SeerDBShutdownRunner;
+  friend class SeerCommitTimerInitEvent;
+  friend class SeerNewTransactionEvent;
+  friend class SeerCleanupEvent;
 
   void CheckForAndDeleteOldDBFile();
   nsresult EnsureInitStorage();
 
   // This is a proxy for the information we need from an nsIURI
   struct UriInfo {
     nsAutoCString spec;
     nsAutoCString origin;
@@ -147,16 +151,36 @@ private:
 
   void LearnForToplevel(const UriInfo &uri);
   void LearnForSubresource(const UriInfo &targetURI, const UriInfo &sourceURI);
   void LearnForRedirect(const UriInfo &targetURI, const UriInfo &sourceURI);
   void LearnForStartup(const UriInfo &uri);
 
   void ResetInternal();
 
+  void BeginTransaction()
+  {
+    mDB->BeginTransaction();
+  }
+
+  void CommitTransaction()
+  {
+    mDB->CommitTransaction();
+  }
+
+  int64_t GetDBFileSize();
+  int64_t GetDBFileSizeAfterVacuum();
+  void MaybeScheduleCleanup();
+  void Cleanup();
+  void CleanupOrigins(PRTime now);
+  void CleanupStartupPages(PRTime now);
+  int32_t GetSubresourceCount();
+
+  void VacuumDatabase();
+
   // Observer-related stuff
   nsresult InstallObserver();
   void RemoveObserver();
 
   bool mInitialized;
 
   bool mEnabled;
   bool mEnableHoverOnSSL;
@@ -195,14 +219,26 @@ private:
   nsCOMPtr<nsIDNSService> mDnsService;
 
   int32_t mQueueSize;
   mozilla::Mutex mQueueSizeLock;
 
   nsAutoPtr<SeerTelemetryAccumulators> mAccumulators;
 
   nsRefPtr<SeerDNSListener> mDNSListener;
+
+  nsCOMPtr<nsITimer> mCommitTimer;
+
+#ifdef SEER_TESTS
+  friend class SeerPrepareForDnsTestEvent;
+  void PrepareForDnsTestInternal(int64_t timestamp, const nsACString &uri);
+#endif
+
+  bool mCleanupScheduled;
+  int32_t mMaxDBSize;
+  int32_t mPreservePercentage;
+  PRTime mLastCleanupTime;
 };
 
 } // ::mozilla::net
 } // ::mozilla
 
 #endif // mozilla_net_Seer_h
--- a/netwerk/base/src/Tickler.cpp
+++ b/netwerk/base/src/Tickler.cpp
@@ -75,17 +75,19 @@ nsresult
 Tickler::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mTimer);
   MOZ_ASSERT(!mActive);
   MOZ_ASSERT(!mThread);
   MOZ_ASSERT(!mFD);
 
-  GeckoAppShell::EnableNetworkNotifications();
+  if (AndroidBridge::HasEnv()) {
+      GeckoAppShell::EnableNetworkNotifications();
+  }
 
   mFD = PR_OpenUDPSocket(PR_AF_INET);
   if (!mFD)
     return NS_ERROR_FAILURE;
 
   // make sure new socket has a ttl of 1
   // failure is not fatal.
   PRSocketOptionData opt;
--- a/netwerk/base/src/moz.build
+++ b/netwerk/base/src/moz.build
@@ -124,8 +124,11 @@ if 'rtsp' in CONFIG['NECKO_PROTOCOLS']:
         '/netwerk/protocol/rtsp/controller',
         '/netwerk/protocol/rtsp/rtsp',
     ]
 
 if CONFIG['MOZ_ENABLE_QTNETWORK']:
     LOCAL_INCLUDES += [
         '/netwerk/system/qt',
     ]
+
+if CONFIG['ENABLE_TESTS']:
+    DEFINES['SEER_TESTS'] = True
--- a/netwerk/dns/DNSRequestParent.h
+++ b/netwerk/dns/DNSRequestParent.h
@@ -23,17 +23,17 @@ public:
   NS_DECL_NSIDNSLISTENER
 
   DNSRequestParent();
   virtual ~DNSRequestParent();
 
   void DoAsyncResolve(const nsACString  &hostname, uint32_t flags);
 
 protected:
-  virtual void ActorDestroy(ActorDestroyReason why);
+  virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 private:
   uint32_t mFlags;
   bool mIPCClosed;  // true if IPDL channel has been closed (child crash)
 };
 
 } // namespace net
 } // namespace mozilla
 #endif // mozilla_net_DNSRequestParent_h
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -23,47 +23,50 @@ public:
   virtual ~NeckoChild();
 
   static void InitNeckoChild();
   static void DestroyNeckoChild();
 
 protected:
   virtual PHttpChannelChild*
     AllocPHttpChannelChild(PBrowserChild*, const SerializedLoadContext&,
-                           const HttpChannelCreationArgs& aOpenArgs);
-  virtual bool DeallocPHttpChannelChild(PHttpChannelChild*);
-  virtual PCookieServiceChild* AllocPCookieServiceChild();
-  virtual bool DeallocPCookieServiceChild(PCookieServiceChild*);
-  virtual PWyciwygChannelChild* AllocPWyciwygChannelChild();
-  virtual bool DeallocPWyciwygChannelChild(PWyciwygChannelChild*);
+                           const HttpChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
+  virtual bool DeallocPHttpChannelChild(PHttpChannelChild*) MOZ_OVERRIDE;
+  virtual PCookieServiceChild* AllocPCookieServiceChild() MOZ_OVERRIDE;
+  virtual bool DeallocPCookieServiceChild(PCookieServiceChild*) MOZ_OVERRIDE;
+  virtual PWyciwygChannelChild* AllocPWyciwygChannelChild() MOZ_OVERRIDE;
+  virtual bool DeallocPWyciwygChannelChild(PWyciwygChannelChild*) MOZ_OVERRIDE;
   virtual PFTPChannelChild*
     AllocPFTPChannelChild(PBrowserChild* aBrowser,
                           const SerializedLoadContext& aSerialized,
-                          const FTPChannelCreationArgs& aOpenArgs);
-  virtual bool DeallocPFTPChannelChild(PFTPChannelChild*);
-  virtual PWebSocketChild* AllocPWebSocketChild(PBrowserChild*, const SerializedLoadContext&);
-  virtual bool DeallocPWebSocketChild(PWebSocketChild*);
-  virtual PTCPSocketChild* AllocPTCPSocketChild();
-  virtual bool DeallocPTCPSocketChild(PTCPSocketChild*);
-  virtual PTCPServerSocketChild* AllocPTCPServerSocketChild(const uint16_t& aLocalPort,
-                                                       const uint16_t& aBacklog,
-                                                       const nsString& aBinaryType);
-  virtual bool DeallocPTCPServerSocketChild(PTCPServerSocketChild*);
+                          const FTPChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
+  virtual bool DeallocPFTPChannelChild(PFTPChannelChild*) MOZ_OVERRIDE;
+  virtual PWebSocketChild*
+    AllocPWebSocketChild(PBrowserChild*, const SerializedLoadContext&) MOZ_OVERRIDE;
+  virtual bool DeallocPWebSocketChild(PWebSocketChild*) MOZ_OVERRIDE;
+  virtual PTCPSocketChild* AllocPTCPSocketChild() MOZ_OVERRIDE;
+  virtual bool DeallocPTCPSocketChild(PTCPSocketChild*) MOZ_OVERRIDE;
+  virtual PTCPServerSocketChild*
+    AllocPTCPServerSocketChild(const uint16_t& aLocalPort,
+                               const uint16_t& aBacklog,
+                               const nsString& aBinaryType) MOZ_OVERRIDE;
+  virtual bool DeallocPTCPServerSocketChild(PTCPServerSocketChild*) MOZ_OVERRIDE;
   virtual PUDPSocketChild* AllocPUDPSocketChild(const nsCString& aHost,
                                                 const uint16_t& aPort,
-                                                const nsCString& aFilter);
-  virtual bool DeallocPUDPSocketChild(PUDPSocketChild*);
+                                                const nsCString& aFilter) MOZ_OVERRIDE;
+  virtual bool DeallocPUDPSocketChild(PUDPSocketChild*) MOZ_OVERRIDE;
   virtual PDNSRequestChild* AllocPDNSRequestChild(const nsCString& aHost,
-                                                  const uint32_t& aFlags);
-  virtual bool DeallocPDNSRequestChild(PDNSRequestChild*);
-  virtual PRemoteOpenFileChild* AllocPRemoteOpenFileChild(const URIParams&,
-                                                          const OptionalURIParams&);
-  virtual bool DeallocPRemoteOpenFileChild(PRemoteOpenFileChild*);
-  virtual PRtspControllerChild* AllocPRtspControllerChild();
-  virtual bool DeallocPRtspControllerChild(PRtspControllerChild*);
+                                                  const uint32_t& aFlags) MOZ_OVERRIDE;
+  virtual bool DeallocPDNSRequestChild(PDNSRequestChild*) MOZ_OVERRIDE;
+  virtual PRemoteOpenFileChild*
+    AllocPRemoteOpenFileChild(const URIParams&,
+                              const OptionalURIParams&) MOZ_OVERRIDE;
+  virtual bool DeallocPRemoteOpenFileChild(PRemoteOpenFileChild*) MOZ_OVERRIDE;
+  virtual PRtspControllerChild* AllocPRtspControllerChild() MOZ_OVERRIDE;
+  virtual bool DeallocPRtspControllerChild(PRtspControllerChild*) MOZ_OVERRIDE;
 };
 
 /**
  * Reference to the PNecko Child protocol.
  * Null if this is not a content process.
  */
 extern PNeckoChild *gNeckoChild;
 
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -65,87 +65,89 @@ public:
   RecvPCookieServiceConstructor(PCookieServiceParent* aActor) MOZ_OVERRIDE
   {
     return PNeckoParent::RecvPCookieServiceConstructor(aActor);
   }
 
 protected:
   virtual PHttpChannelParent*
     AllocPHttpChannelParent(PBrowserParent*, const SerializedLoadContext&,
-                            const HttpChannelCreationArgs& aOpenArgs);
+                            const HttpChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
   virtual bool
     RecvPHttpChannelConstructor(
                       PHttpChannelParent* aActor,
                       PBrowserParent* aBrowser,
                       const SerializedLoadContext& aSerialized,
-                      const HttpChannelCreationArgs& aOpenArgs);
-  virtual bool DeallocPHttpChannelParent(PHttpChannelParent*);
-  virtual bool DeallocPCookieServiceParent(PCookieServiceParent*);
-  virtual PWyciwygChannelParent* AllocPWyciwygChannelParent();
-  virtual bool DeallocPWyciwygChannelParent(PWyciwygChannelParent*);
+                      const HttpChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
+  virtual bool DeallocPHttpChannelParent(PHttpChannelParent*) MOZ_OVERRIDE;
+  virtual bool DeallocPCookieServiceParent(PCookieServiceParent*) MOZ_OVERRIDE;
+  virtual PWyciwygChannelParent* AllocPWyciwygChannelParent() MOZ_OVERRIDE;
+  virtual bool DeallocPWyciwygChannelParent(PWyciwygChannelParent*) MOZ_OVERRIDE;
   virtual PFTPChannelParent*
     AllocPFTPChannelParent(PBrowserParent* aBrowser,
                            const SerializedLoadContext& aSerialized,
-                           const FTPChannelCreationArgs& aOpenArgs);
+                           const FTPChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
   virtual bool
     RecvPFTPChannelConstructor(
                       PFTPChannelParent* aActor,
                       PBrowserParent* aBrowser,
                       const SerializedLoadContext& aSerialized,
-                      const FTPChannelCreationArgs& aOpenArgs);
-  virtual bool DeallocPFTPChannelParent(PFTPChannelParent*);
-  virtual PWebSocketParent* AllocPWebSocketParent(PBrowserParent* browser,
-                                                  const SerializedLoadContext& aSerialized);
-  virtual bool DeallocPWebSocketParent(PWebSocketParent*);
-  virtual PTCPSocketParent* AllocPTCPSocketParent();
+                      const FTPChannelCreationArgs& aOpenArgs) MOZ_OVERRIDE;
+  virtual bool DeallocPFTPChannelParent(PFTPChannelParent*) MOZ_OVERRIDE;
+  virtual PWebSocketParent*
+    AllocPWebSocketParent(PBrowserParent* browser,
+                          const SerializedLoadContext& aSerialized) MOZ_OVERRIDE;
+  virtual bool DeallocPWebSocketParent(PWebSocketParent*) MOZ_OVERRIDE;
+  virtual PTCPSocketParent* AllocPTCPSocketParent() MOZ_OVERRIDE;
 
   virtual PRemoteOpenFileParent* AllocPRemoteOpenFileParent(const URIParams& aFileURI,
                                                             const OptionalURIParams& aAppURI)
                                                             MOZ_OVERRIDE;
   virtual bool RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
                                               const URIParams& aFileURI,
                                               const OptionalURIParams& aAppURI)
                                               MOZ_OVERRIDE;
   virtual bool DeallocPRemoteOpenFileParent(PRemoteOpenFileParent* aActor)
                                             MOZ_OVERRIDE;
 
-  virtual bool DeallocPTCPSocketParent(PTCPSocketParent*);
-  virtual PTCPServerSocketParent* AllocPTCPServerSocketParent(const uint16_t& aLocalPort,
-                                                        const uint16_t& aBacklog,
-                                                        const nsString& aBinaryType);
+  virtual bool DeallocPTCPSocketParent(PTCPSocketParent*) MOZ_OVERRIDE;
+  virtual PTCPServerSocketParent*
+    AllocPTCPServerSocketParent(const uint16_t& aLocalPort,
+                                const uint16_t& aBacklog,
+                                const nsString& aBinaryType) MOZ_OVERRIDE;
   virtual bool RecvPTCPServerSocketConstructor(PTCPServerSocketParent*,
                                                const uint16_t& aLocalPort,
                                                const uint16_t& aBacklog,
-                                               const nsString& aBinaryType);
-  virtual bool DeallocPTCPServerSocketParent(PTCPServerSocketParent*);
+                                               const nsString& aBinaryType) MOZ_OVERRIDE;
+  virtual bool DeallocPTCPServerSocketParent(PTCPServerSocketParent*) MOZ_OVERRIDE;
   virtual PUDPSocketParent* AllocPUDPSocketParent(const nsCString& aHost,
                                                   const uint16_t& aPort,
-                                                  const nsCString& aFilter);
+                                                  const nsCString& aFilter) MOZ_OVERRIDE;
   virtual bool RecvPUDPSocketConstructor(PUDPSocketParent*,
                                          const nsCString& aHost,
                                          const uint16_t& aPort,
-                                         const nsCString& aFilter);
-  virtual bool DeallocPUDPSocketParent(PUDPSocketParent*);
+                                         const nsCString& aFilter) MOZ_OVERRIDE;
+  virtual bool DeallocPUDPSocketParent(PUDPSocketParent*) MOZ_OVERRIDE;
   virtual PDNSRequestParent* AllocPDNSRequestParent(const nsCString& aHost,
-                                                    const uint32_t& aFlags);
+                                                    const uint32_t& aFlags) MOZ_OVERRIDE;
   virtual bool RecvPDNSRequestConstructor(PDNSRequestParent* actor,
                                           const nsCString& hostName,
-                                          const uint32_t& flags);
-  virtual bool DeallocPDNSRequestParent(PDNSRequestParent*);
+                                          const uint32_t& flags) MOZ_OVERRIDE;
+  virtual bool DeallocPDNSRequestParent(PDNSRequestParent*) MOZ_OVERRIDE;
   virtual bool RecvHTMLDNSPrefetch(const nsString& hostname,
-                                   const uint16_t& flags);
+                                   const uint16_t& flags) MOZ_OVERRIDE;
   virtual bool RecvCancelHTMLDNSPrefetch(const nsString& hostname,
                                          const uint16_t& flags,
-                                         const nsresult& reason);
+                                         const nsresult& reason) MOZ_OVERRIDE;
 
   virtual mozilla::ipc::IProtocol*
   CloneProtocol(Channel* aChannel,
                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
-  virtual PRtspControllerParent* AllocPRtspControllerParent();
-  virtual bool DeallocPRtspControllerParent(PRtspControllerParent*);
+  virtual PRtspControllerParent* AllocPRtspControllerParent() MOZ_OVERRIDE;
+  virtual bool DeallocPRtspControllerParent(PRtspControllerParent*) MOZ_OVERRIDE;
 
 private:
   nsCString mCoreAppsBasePath;
   nsCString mWebAppsBasePath;
 };
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/protocol/http/HttpChannelChild.h
+++ b/netwerk/protocol/http/HttpChannelChild.h
@@ -95,35 +95,35 @@ protected:
                           const bool& useResponseHead,
                           const nsHttpHeaderArray& requestHeaders,
                           const bool& isFromCache,
                           const bool& cacheEntryAvailable,
                           const uint32_t& cacheExpirationTime,
                           const nsCString& cachedCharset,
                           const nsCString& securityInfoSerialization,
                           const NetAddr& selfAddr,
-                          const NetAddr& peerAddr);
+                          const NetAddr& peerAddr) MOZ_OVERRIDE;
   bool RecvOnTransportAndData(const nsresult& status,
                               const uint64_t& progress,
                               const uint64_t& progressMax,
                               const nsCString& data,
                               const uint64_t& offset,
-                              const uint32_t& count);
+                              const uint32_t& count) MOZ_OVERRIDE;
   bool RecvOnStopRequest(const nsresult& statusCode);
-  bool RecvOnProgress(const uint64_t& progress, const uint64_t& progressMax);
-  bool RecvOnStatus(const nsresult& status);
-  bool RecvFailedAsyncOpen(const nsresult& status);
+  bool RecvOnProgress(const uint64_t& progress, const uint64_t& progressMax) MOZ_OVERRIDE;
+  bool RecvOnStatus(const nsresult& status) MOZ_OVERRIDE;
+  bool RecvFailedAsyncOpen(const nsresult& status) MOZ_OVERRIDE;
   bool RecvRedirect1Begin(const uint32_t& newChannel,
                           const URIParams& newURI,
                           const uint32_t& redirectFlags,
-                          const nsHttpResponseHead& responseHead);
-  bool RecvRedirect3Complete();
+                          const nsHttpResponseHead& responseHead) MOZ_OVERRIDE;
+  bool RecvRedirect3Complete() MOZ_OVERRIDE;
   bool RecvAssociateApplicationCache(const nsCString& groupID,
-                                     const nsCString& clientID);
-  bool RecvDeleteSelf();
+                                     const nsCString& clientID) MOZ_OVERRIDE;
+  bool RecvDeleteSelf() MOZ_OVERRIDE;
 
   bool GetAssociatedContentSecurity(nsIAssociatedContentSecurity** res = nullptr);
   virtual void DoNotifyListenerCleanup();
 
 private:
   RequestHeaderTuples mClientSetRequestHeaders;
   nsCOMPtr<nsIChildChannel> mRedirectChannelChild;
   nsCOMPtr<nsISupports> mSecurityInfo;
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -72,30 +72,30 @@ protected:
                    const bool&                forceAllowThirdPartyCookie,
                    const bool&                doResumeAt,
                    const uint64_t&            startPos,
                    const nsCString&           entityID,
                    const bool&                chooseApplicationCache,
                    const nsCString&           appCacheClientID,
                    const bool&                allowSpdy);
 
-  virtual bool RecvSetPriority(const uint16_t& priority);
-  virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset);
-  virtual bool RecvSuspend();
-  virtual bool RecvResume();
-  virtual bool RecvCancel(const nsresult& status);
+  virtual bool RecvSetPriority(const uint16_t& priority) MOZ_OVERRIDE;
+  virtual bool RecvSetCacheTokenCachedCharset(const nsCString& charset) MOZ_OVERRIDE;
+  virtual bool RecvSuspend() MOZ_OVERRIDE;
+  virtual bool RecvResume() MOZ_OVERRIDE;
+  virtual bool RecvCancel(const nsresult& status) MOZ_OVERRIDE;
   virtual bool RecvRedirect2Verify(const nsresult& result,
                                    const RequestHeaderTuples& changedHeaders,
-                                   const OptionalURIParams&   apiRedirectUri);
+                                   const OptionalURIParams& apiRedirectUri) MOZ_OVERRIDE;
   virtual bool RecvUpdateAssociatedContentSecurity(const int32_t& broken,
-                                                   const int32_t& no);
-  virtual bool RecvDocumentChannelCleanup();
-  virtual bool RecvMarkOfflineCacheEntryAsForeign();
+                                                   const int32_t& no) MOZ_OVERRIDE;
+  virtual bool RecvDocumentChannelCleanup() MOZ_OVERRIDE;
+  virtual bool RecvMarkOfflineCacheEntryAsForeign() MOZ_OVERRIDE;
 
-  virtual void ActorDestroy(ActorDestroyReason why);
+  virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
 protected:
   friend class HttpChannelParentListener;
   nsRefPtr<mozilla::dom::TabParent> mTabParent;
 
 private:
   nsCOMPtr<nsIChannel>                    mChannel;
   nsCOMPtr<nsICacheEntry>       mCacheEntry;
--- a/netwerk/protocol/websocket/WebSocketChannelChild.h
+++ b/netwerk/protocol/websocket/WebSocketChannelChild.h
@@ -34,23 +34,22 @@ class WebSocketChannelChild : public Bas
   NS_IMETHOD SendBinaryMsg(const nsACString &aMsg);
   NS_IMETHOD SendBinaryStream(nsIInputStream *aStream, uint32_t aLength);
   NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo);
 
   void AddIPDLReference();
   void ReleaseIPDLReference();
 
  private:
-  bool RecvOnStart(const nsCString& aProtocol, const nsCString& aExtensions);
-  bool RecvOnStop(const nsresult& aStatusCode);
-  bool RecvOnMessageAvailable(const nsCString& aMsg);
-  bool RecvOnBinaryMessageAvailable(const nsCString& aMsg);
-  bool RecvOnAcknowledge(const uint32_t& aSize);
-  bool RecvOnServerClose(const uint16_t& aCode, const nsCString &aReason);
-  bool RecvAsyncOpenFailed();
+  bool RecvOnStart(const nsCString& aProtocol, const nsCString& aExtensions) MOZ_OVERRIDE;
+  bool RecvOnStop(const nsresult& aStatusCode) MOZ_OVERRIDE;
+  bool RecvOnMessageAvailable(const nsCString& aMsg) MOZ_OVERRIDE;
+  bool RecvOnBinaryMessageAvailable(const nsCString& aMsg) MOZ_OVERRIDE;
+  bool RecvOnAcknowledge(const uint32_t& aSize) MOZ_OVERRIDE;
+  bool RecvOnServerClose(const uint16_t& aCode, const nsCString &aReason) MOZ_OVERRIDE;
 
   void OnStart(const nsCString& aProtocol, const nsCString& aExtensions);
   void OnStop(const nsresult& aStatusCode);
   void OnMessageAvailable(const nsCString& aMsg);
   void OnBinaryMessageAvailable(const nsCString& aMsg);
   void OnAcknowledge(const uint32_t& aSize);
   void OnServerClose(const uint16_t& aCode, const nsCString& aReason);
   void AsyncOpenFailed();  
--- a/netwerk/protocol/websocket/WebSocketChannelParent.h
+++ b/netwerk/protocol/websocket/WebSocketChannelParent.h
@@ -37,25 +37,25 @@ class WebSocketChannelParent : public PW
  private:
   bool RecvAsyncOpen(const URIParams& aURI,
                      const nsCString& aOrigin,
                      const nsCString& aProtocol,
                      const bool& aSecure,
                      const uint32_t& aPingInterval,
                      const bool& aClientSetPingInterval,
                      const uint32_t& aPingTimeout,
-                     const bool& aClientSetPingTimeout);
-  bool RecvClose(const uint16_t & code, const nsCString & reason);
-  bool RecvSendMsg(const nsCString& aMsg);
-  bool RecvSendBinaryMsg(const nsCString& aMsg);
+                     const bool& aClientSetPingTimeout) MOZ_OVERRIDE;
+  bool RecvClose(const uint16_t & code, const nsCString & reason) MOZ_OVERRIDE;
+  bool RecvSendMsg(const nsCString& aMsg) MOZ_OVERRIDE;
+  bool RecvSendBinaryMsg(const nsCString& aMsg) MOZ_OVERRIDE;
   bool RecvSendBinaryStream(const InputStreamParams& aStream,
-                            const uint32_t& aLength);
-  bool RecvDeleteSelf();
+                            const uint32_t& aLength) MOZ_OVERRIDE;
+  bool RecvDeleteSelf() MOZ_OVERRIDE;
 
-  void ActorDestroy(ActorDestroyReason why);
+  void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   nsCOMPtr<nsIAuthPromptProvider> mAuthProvider;
   nsCOMPtr<nsIWebSocketChannel> mChannel;
   nsCOMPtr<nsILoadContext> mLoadContext;
   bool mIPCOpen;
 
 };
 
--- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.h
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.h
@@ -55,21 +55,21 @@ public:
 
   bool IsSuspended();
 
 protected:
   bool RecvOnStartRequest(const nsresult& statusCode,
                           const int64_t& contentLength,
                           const int32_t& source,
                           const nsCString& charset,
-                          const nsCString& securityInfo);
+                          const nsCString& securityInfo) MOZ_OVERRIDE;
   bool RecvOnDataAvailable(const nsCString& data,
-                           const uint64_t& offset);
-  bool RecvOnStopRequest(const nsresult& statusCode);
-  bool RecvCancelEarly(const nsresult& statusCode);
+                           const uint64_t& offset) MOZ_OVERRIDE;
+  bool RecvOnStopRequest(const nsresult& statusCode) MOZ_OVERRIDE;
+  bool RecvCancelEarly(const nsresult& statusCode) MOZ_OVERRIDE;
 
   void OnStartRequest(const nsresult& statusCode,
                       const int64_t& contentLength,
                       const int32_t& source,
                       const nsCString& charset,
                       const nsCString& securityInfo);
   void OnDataAvailable(const nsCString& data,
                        const uint64_t& offset);
--- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.h
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.h
@@ -29,31 +29,31 @@ public:
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIINTERFACEREQUESTOR
 
   WyciwygChannelParent();
   virtual ~WyciwygChannelParent();
 
 protected:
-  virtual bool RecvInit(const URIParams& uri);
+  virtual bool RecvInit(const URIParams& uri) MOZ_OVERRIDE;
   virtual bool RecvAsyncOpen(const URIParams& original,
                              const uint32_t& loadFlags,
                              const IPC::SerializedLoadContext& loadContext,
-                             PBrowserParent* parent);
-  virtual bool RecvWriteToCacheEntry(const nsString& data);
-  virtual bool RecvCloseCacheEntry(const nsresult& reason);
+                             PBrowserParent* parent) MOZ_OVERRIDE;
+  virtual bool RecvWriteToCacheEntry(const nsString& data) MOZ_OVERRIDE;
+  virtual bool RecvCloseCacheEntry(const nsresult& reason) MOZ_OVERRIDE;
   virtual bool RecvSetCharsetAndSource(const int32_t& source,
-                                       const nsCString& charset);
-  virtual bool RecvSetSecurityInfo(const nsCString& securityInfo);
-  virtual bool RecvCancel(const nsresult& statusCode);
+                                       const nsCString& charset) MOZ_OVERRIDE;
+  virtual bool RecvSetSecurityInfo(const nsCString& securityInfo) MOZ_OVERRIDE;
+  virtual bool RecvCancel(const nsresult& statusCode) MOZ_OVERRIDE;
   virtual bool RecvAppData(const IPC::SerializedLoadContext& loadContext,
-                           PBrowserParent* parent);
+                           PBrowserParent* parent) MOZ_OVERRIDE;
 
-  virtual void ActorDestroy(ActorDestroyReason why);
+  virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   bool SetupAppData(const IPC::SerializedLoadContext& loadContext,
                     PBrowserParent* aParent);
 
   nsCOMPtr<nsIWyciwygChannel> mChannel;
   bool mIPCClosed;
   bool mReceivedAppData;
   nsCOMPtr<nsILoadContext> mLoadContext;
--- a/netwerk/test/unit/test_seer.js
+++ b/netwerk/test/unit/test_seer.js
@@ -211,24 +211,17 @@ DnsContinueVerifier.prototype = {
     // This means that the seer has learned and done our "checkpoint" prediction
     // Now we can get on with the prediction we actually want to test
 
     // tstamp is 10 days older than now - just over 1 week, which will ensure we
     // hit our cutoff for dns vs. preconnect. This is all in usec, hence the
     // x1000 on the Date object value.
     var tstamp = (new Date().valueOf() * 1000) - (10 * 86400 * 1000000);
 
-    var dbfile = FileUtils.getFile("ProfD", ["netpredictions.sqlite"]);
-    var dbconn = Services.storage.openDatabase(dbfile);
-    // We also need to update hits, since the toplevel has been "loaded" a
-    // second time (from the prediction that kicked off this callback) to ensure
-    // that the seer will try to do anything for this subresource.
-    var stmt = "UPDATE moz_subresources SET last_hit = " + tstamp + ", hits = 2 WHERE uri = '" + this.subresource + "';";
-    dbconn.executeSimpleSQL(stmt);
-    dbconn.close();
+    seer.prepareForDnsTest(tstamp, this.subresource);
 
     var verifier = new Verifier("dns", [], this.preresolves);
     seer.predict(this.tluri, null, seer.PREDICT_LOAD, load_context, verifier);
   },
 
   onPredictDNS: function _dnsContinueVerifier_onPredictDNS() {
     do_check_true(false, "Shouldn't have gotten a preresolve prediction here!");
   }
--- a/python/mozboot/mozboot/fedora.py
+++ b/python/mozboot/mozboot/fedora.py
@@ -17,16 +17,17 @@ class FedoraBootstrapper(BaseBootstrappe
         self.yum_groupinstall(
             'Development Tools',
             'Development Libraries',
             'GNOME Software Development')
 
         self.yum_install(
             'alsa-lib-devel',
             'autoconf213',
+            'gcc-c++',
             'glibc-static',
             'gstreamer-devel',
             'gstreamer-plugins-base-devel',
             'libstdc++-static',
             'libXt-devel',
             'mercurial',
             'mesa-libGL-devel',
             'pulseaudio-libs-devel',
--- a/python/mozbuild/mozpack/files.py
+++ b/python/mozbuild/mozpack/files.py
@@ -3,16 +3,19 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import errno
 import os
 import re
 import shutil
 import stat
 import uuid
+import mozbuild.makeutil as makeutil
+from mozbuild.preprocessor import Preprocessor
+from mozbuild.util import FileAvoidWrite
 from mozpack.executables import (
     is_executable,
     may_strip,
     strip,
     may_elfhack,
     elfhack,
 )
 from mozpack.chrome.manifest import ManifestEntry
@@ -35,16 +38,20 @@ class Dest(object):
       read from it.
     - a call to write() after a read() will re-open the underlying file,
       emptying it, and write to it.
     '''
     def __init__(self, path):
         self.path = path
         self.mode = None
 
+    @property
+    def name(self):
+        return self.path
+
     def read(self, length=-1):
         if self.mode != 'r':
             self.file = open(self.path, 'rb')
             self.mode = 'r'
         return self.file.read(length)
 
     def write(self, data):
         if self.mode != 'w':
@@ -62,16 +69,46 @@ class Dest(object):
 
 
 class BaseFile(object):
     '''
     Base interface and helper for file copying. Derived class may implement
     their own copy function, or rely on BaseFile.copy using the open() member
     function and/or the path property.
     '''
+    @staticmethod
+    def is_older(first, second):
+        '''
+        Compares the modification time of two files, and returns whether the
+        ``first`` file is older than the ``second`` file.
+        '''
+        # os.path.getmtime returns a result in seconds with precision up to
+        # the microsecond. But microsecond is too precise because
+        # shutil.copystat only copies milliseconds, and seconds is not
+        # enough precision.
+        return int(os.path.getmtime(first) * 1000) \
+                <= int(os.path.getmtime(second) * 1000)
+
+    @staticmethod
+    def any_newer(dest, inputs):
+        '''
+        Compares the modification time of ``dest`` to multiple input files, and
+        returns whether any of the ``inputs`` is newer (has a later mtime) than
+        ``dest``.
+        '''
+        # os.path.getmtime returns a result in seconds with precision up to
+        # the microsecond. But microsecond is too precise because
+        # shutil.copystat only copies milliseconds, and seconds is not
+        # enough precision.
+        dest_mtime = int(os.path.getmtime(dest) * 1000)
+        for input in inputs:
+            if dest_mtime < int(os.path.getmtime(input) * 1000):
+                return True
+        return False
+
     def copy(self, dest, skip_if_older=True):
         '''
         Copy the BaseFile content to the destination given as a string or a
         Dest instance. Avoids replacing existing files if the BaseFile content
         matches that of the destination, or in case of plain files, if the
         destination is newer than the original file. This latter behaviour is
         disabled when skip_if_older is False.
         Returns whether a copy was actually performed (True) or not (False).
@@ -80,22 +117,17 @@ class BaseFile(object):
             dest = Dest(dest)
         else:
             assert isinstance(dest, Dest)
 
         can_skip_content_check = False
         if not dest.exists():
             can_skip_content_check = True
         elif getattr(self, 'path', None) and getattr(dest, 'path', None):
-            # os.path.getmtime returns a result in seconds with precision up to
-            # the microsecond. But microsecond is too precise because
-            # shutil.copystat only copies milliseconds, and seconds is not
-            # enough precision.
-            if skip_if_older and int(os.path.getmtime(self.path) * 1000) \
-                    <= int(os.path.getmtime(dest.path) * 1000):
+            if skip_if_older and BaseFile.is_older(self.path, dest.path):
                 return False
             elif os.path.getsize(self.path) != os.path.getsize(dest.path):
                 can_skip_content_check = True
 
         if can_skip_content_check:
             if getattr(self, 'path', None) and getattr(dest, 'path', None):
                 shutil.copy2(self.path, dest.path)
             else:
@@ -287,16 +319,86 @@ class ExistingFile(BaseFile):
         if not self.required:
             return
 
         if not dest.exists():
             errors.fatal("Required existing file doesn't exist: %s" %
                 dest.path)
 
 
+class PreprocessedFile(BaseFile):
+    '''
+    File class for a file that is preprocessed. PreprocessedFile.copy() runs
+    the preprocessor on the file to create the output.
+    '''
+    def __init__(self, path, depfile_path, marker, defines, extra_depends=None):
+        self.path = path
+        self.depfile = depfile_path
+        self.marker = marker
+        self.defines = defines
+        self.extra_depends = list(extra_depends or [])
+
+    def copy(self, dest, skip_if_older=True):
+        '''
+        Invokes the preprocessor to create the destination file.
+        '''
+        if isinstance(dest, basestring):
+            dest = Dest(dest)
+        else:
+            assert isinstance(dest, Dest)
+
+        # We have to account for the case where the destination exists and is a
+        # symlink to something. Since we know the preprocessor is certainly not
+        # going to create a symlink, we can just remove the existing one. If the
+        # destination is not a symlink, we leave it alone, since we're going to
+        # overwrite its contents anyway.
+        # If symlinks aren't supported at all, we can skip this step.
+        if hasattr(os, 'symlink'):
+            if os.path.islink(dest.path):
+                os.remove(dest.path)
+
+        pp_deps = set(self.extra_depends)
+
+        # If a dependency file was specified, and it exists, add any
+        # dependencies from that file to our list.
+        if self.depfile and os.path.exists(self.depfile):
+            target = mozpack.path.normpath(dest.name)
+            with open(self.depfile, 'rb') as fileobj:
+                for rule in makeutil.read_dep_makefile(fileobj):
+                    if target in rule.targets():
+                        pp_deps.update(rule.dependencies())
+
+        skip = False
+        if dest.exists() and skip_if_older:
+            # If a dependency file was specified, and it doesn't exist,
+            # assume that the preprocessor needs to be rerun. That will
+            # regenerate the dependency file.
+            if self.depfile and not os.path.exists(self.depfile):
+                skip = False
+            else:
+                skip = not BaseFile.any_newer(dest.path, pp_deps)
+
+        if skip:
+            return False
+
+        deps_out = None
+        if self.depfile:
+            deps_out = FileAvoidWrite(self.depfile)
+        pp = Preprocessor(defines=self.defines, marker=self.marker)
+
+        with open(self.path, 'rU') as input:
+            pp.processFile(input=input, output=dest, depfile=deps_out)
+
+        dest.close()
+        if self.depfile:
+            deps_out.close()
+
+        return True
+
+
 class GeneratedFile(BaseFile):
     '''
     File class for content with no previous existence on the filesystem.
     '''
     def __init__(self, content):
         self.content = content
 
     def open(self):
--- a/python/mozbuild/mozpack/manifests.py
+++ b/python/mozbuild/mozpack/manifests.py
@@ -1,21 +1,23 @@
 # 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/.
 
 from __future__ import unicode_literals
 
 from contextlib import contextmanager
+import json
 
 from .files import (
     AbsoluteSymlinkFile,
     ExistingFile,
     File,
     FileFinder,
+    PreprocessedFile,
 )
 import mozpack.path as mozpath
 
 
 # This probably belongs in a more generic module. Where?
 @contextmanager
 def _auto_fileobj(path, fileobj, mode='r'):
     if path and fileobj:
@@ -64,51 +66,60 @@ class InstallManifest(object):
           exist.
 
       patternsymlink -- Paths matched by the expression in the source path
           will be symlinked to the destination directory.
 
       patterncopy -- Similar to patternsymlink except files are copied, not
           symlinked.
 
+      preprocess -- The file specified at the source path will be run through
+          the preprocessor, and the output will be written to the destination
+          path.
+
     Version 1 of the manifest was the initial version.
     Version 2 added optional path support
     Version 3 added support for pattern entries.
+    Version 4 added preprocessed file support.
     """
+
+    CURRENT_VERSION = 4
+
     FIELD_SEPARATOR = '\x1f'
 
     SYMLINK = 1
     COPY = 2
     REQUIRED_EXISTS = 3
     OPTIONAL_EXISTS = 4
     PATTERN_SYMLINK = 5
     PATTERN_COPY = 6
+    PREPROCESS = 7
 
     def __init__(self, path=None, fileobj=None):
         """Create a new InstallManifest entry.
 
         If path is defined, the manifest will be populated with data from the
         file path.
 
-        If fh is defined, the manifest will be populated with data read
+        If fileobj is defined, the manifest will be populated with data read
         from the specified file object.
 
         Both path and fileobj cannot be defined.
         """
         self._dests = {}
+        self._source_file = None
 
-        if not path and not fileobj:
-            return
-
-        with _auto_fileobj(path, fileobj, 'rb') as fh:
-            self._load_from_fileobj(fh)
+        if path or fileobj:
+            with _auto_fileobj(path, fileobj, 'rb') as fh:
+                self._source_file = fh.name
+                self._load_from_fileobj(fh)
 
     def _load_from_fileobj(self, fileobj):
         version = fileobj.readline().rstrip()
-        if version not in ('1', '2', '3'):
+        if version not in ('1', '2', '3', '4'):
             raise UnreadableInstallManifest('Unknown manifest version: ' %
                 version)
 
         for line in fileobj:
             line = line.rstrip()
 
             fields = line.split(self.FIELD_SEPARATOR)
 
@@ -139,16 +150,22 @@ class InstallManifest(object):
                 self.add_pattern_symlink(base, pattern, dest)
                 continue
 
             if record_type == self.PATTERN_COPY:
                 _, base, pattern, dest = fields[1:]
                 self.add_pattern_copy(base, pattern, dest)
                 continue
 
+            if record_type == self.PREPROCESS:
+                dest, source, deps, marker, defines = fields[1:]
+                self.add_preprocess(source, dest, deps, marker,
+                    self._decode_field_entry(defines))
+                continue
+
             raise UnreadableInstallManifest('Unknown record type: %d' %
                 record_type)
 
     def __len__(self):
         return len(self._dests)
 
     def __contains__(self, item):
         return item in self._dests
@@ -163,26 +180,42 @@ class InstallManifest(object):
         if not isinstance(other, InstallManifest):
             raise ValueError('Can only | with another instance of InstallManifest.')
 
         for dest in sorted(other._dests):
             self._add_entry(dest, other._dests[dest])
 
         return self
 
+    def _encode_field_entry(self, data):
+        """Converts an object into a format that can be stored in the manifest file.
+
+        Complex data types, such as ``dict``, need to be converted into a text
+        representation before they can be written to a file.
+        """
+        return json.dumps(data, sort_keys=True)
+
+    def _decode_field_entry(self, data):
+        """Restores an object from a format that can be stored in the manifest file.
+
+        Complex data types, such as ``dict``, need to be converted into a text
+        representation before they can be written to a file.
+        """
+        return json.loads(data)
+
     def write(self, path=None, fileobj=None):
         """Serialize this manifest to a file or file object.
 
         If path is specified, that file will be written to. If fileobj is specified,
         the serialized content will be written to that file object.
 
         It is an error if both are specified.
         """
         with _auto_fileobj(path, fileobj, 'wb') as fh:
-            fh.write('3\n')
+            fh.write('%d\n' % self.CURRENT_VERSION)
 
             for dest in sorted(self._dests):
                 entry = self._dests[dest]
 
                 parts = ['%d' % entry[0], dest]
                 parts.extend(entry[1:])
                 fh.write('%s\n' % self.FIELD_SEPARATOR.join(
                     p.encode('utf-8') for p in parts))
@@ -235,22 +268,34 @@ class InstallManifest(object):
     def add_pattern_copy(self, base, pattern, dest):
         """Add a pattern match that results in copies.
 
         See ``add_pattern_symlink()`` for usage.
         """
         self._add_entry(mozpath.join(base, pattern, dest),
             (self.PATTERN_COPY, base, pattern, dest))
 
+    def add_preprocess(self, source, dest, deps, marker='#', defines={}):
+        """Add a preprocessed file to this manifest.
+
+        ``source`` will be passed through preprocessor.py, and the output will be
+        written to ``dest``.
+        """
+        self._add_entry(dest,
+            (self.PREPROCESS, source, deps, marker, self._encode_field_entry(defines)))
+
     def _add_entry(self, dest, entry):
         if dest in self._dests:
             raise ValueError('Item already in manifest: %s' % dest)
 
         self._dests[dest] = entry
 
+    def _get_deps(self, dest):
+        return {self._source_file} if self._source_file else set()
+
     def populate_registry(self, registry):
         """Populate a mozpack.copier.FileRegistry instance with data from us.
 
         The caller supplied a FileRegistry instance (or at least something that
         conforms to its interface) and that instance is populated with data
         from this manifest.
         """
         for dest in sorted(self._dests):
@@ -284,10 +329,19 @@ class InstallManifest(object):
                     cls = File
 
                 for path in paths:
                     source = mozpath.join(base, path)
                     registry.add(mozpath.join(dest, path), cls(source))
 
                 continue
 
+            if install_type == self.PREPROCESS:
+                registry.add(dest, PreprocessedFile(entry[1],
+                    depfile_path=entry[2],
+                    marker=entry[3],
+                    defines=self._decode_field_entry(entry[4]),
+                    extra_depends=self._get_deps(dest)))
+
+                continue
+
             raise Exception('Unknown install type defined in manifest: %d' %
                 install_type)
--- a/python/mozbuild/mozpack/test/test_files.py
+++ b/python/mozbuild/mozpack/test/test_files.py
@@ -11,16 +11,17 @@ from mozpack.files import (
     Dest,
     ExistingFile,
     FileFinder,
     File,
     GeneratedFile,
     JarFinder,
     ManifestFile,
     MinifiedProperties,
+    PreprocessedFile,
     XPTFile,
 )
 from mozpack.mozjar import (
     JarReader,
     JarWriter,
 )
 from mozpack.chrome.manifest import (
     ManifestContent,
@@ -322,16 +323,138 @@ class TestAbsoluteSymlinkFile(TestWithTm
         self.assertEqual(link, source)
 
         s = AbsoluteSymlinkFile(source)
         self.assertFalse(s.copy(dest))
 
         link = os.readlink(dest)
         self.assertEqual(link, source)
 
+class TestPreprocessedFile(TestWithTmpDir):
+    def test_preprocess(self):
+        '''
+        Test that copying the file invokes the preprocessor
+        '''
+        src = self.tmppath('src')
+        dest = self.tmppath('dest')
+
+        with open(src, 'wb') as tmp:
+            tmp.write('#ifdef FOO\ntest\n#endif')
+
+        f = PreprocessedFile(src, depfile_path=None, marker='#', defines={'FOO': True})
+        self.assertTrue(f.copy(dest))
+
+        self.assertEqual('test\n', open(dest, 'rb').read())
+
+    def test_preprocess_file_no_write(self):
+        '''
+        Test various conditions where PreprocessedFile.copy is expected not to
+        write in the destination file.
+        '''
+        src = self.tmppath('src')
+        dest = self.tmppath('dest')
+        depfile = self.tmppath('depfile')
+
+        with open(src, 'wb') as tmp:
+            tmp.write('#ifdef FOO\ntest\n#endif')