Merge the last PGO-green inbound changeset to m-c.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 16 Aug 2012 20:50:16 -0400
changeset 102564 a79132ac2f0579c589c143ddec56d59e91e978ff
parent 102530 1ecca798b1fb7dec63dabf3cea9cbf3c4ec01ac9 (current diff)
parent 102563 773ecacea4f7062626f708182ae807d66f65e34c (diff)
child 102590 498d4cb8db09e21a3a83bde554fb5759b5d6723b
push id23296
push userryanvm@gmail.com
push dateFri, 17 Aug 2012 00:50:18 +0000
treeherdermozilla-central@a79132ac2f05 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone17.0a1
first release with
nightly linux32
a79132ac2f05 / 17.0a1 / 20120817030555 / files
nightly linux64
a79132ac2f05 / 17.0a1 / 20120817030555 / files
nightly mac
a79132ac2f05 / 17.0a1 / 20120817030555 / files
nightly win32
a79132ac2f05 / 17.0a1 / 20120817030555 / files
nightly win64
a79132ac2f05 / 17.0a1 / 20120817030555 / 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 the last PGO-green inbound changeset to m-c.
toolkit/mozapps/extensions/test/xpcshell/head_addons.js
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -367,16 +367,17 @@ nsBrowserAccess.prototype = {
 Services.obs.addObserver(function onSystemMessage(subject, topic, data) {
   let msg = JSON.parse(data);
   let origin = Services.io.newURI(msg.manifest, null, null).prePath;
   shell.sendChromeEvent({
     type: 'open-app',
     url: msg.uri,
     origin: origin,
     manifest: msg.manifest,
+    isActivity: (msg.type == 'activity'),
     target: msg.target
   });
 }, 'system-messages-open-app', false);
 
 Services.obs.addObserver(function(aSubject, aTopic, aData) {
   shell.sendEvent(shell.contentBrowser.contentWindow,
                   "mozChromeEvent", { type: "fullscreenoriginchange",
                                       fullscreenorigin: aData } );
--- a/configure.in
+++ b/configure.in
@@ -5791,26 +5791,26 @@ esac
 MOZ_ARG_DISABLE_BOOL(crashreporter,
 [  --disable-crashreporter Disable breakpad crash reporting],
     MOZ_CRASHREPORTER=,
     MOZ_CRASHREPORTER=1)
 
 if test -n "$MOZ_CRASHREPORTER"; then
    AC_DEFINE(MOZ_CRASHREPORTER)
 
-  if (test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS") && \
+  if test "$OS_TARGET" = "Linux" -o "$OS_ARCH" = "SunOS" && \
     test -z "$SKIP_LIBRARY_CHECKS"; then
     PKG_CHECK_MODULES(MOZ_GTHREAD, gthread-2.0)
     AC_SUBST(MOZ_GTHREAD_CFLAGS)
     AC_SUBST(MOZ_GTHREAD_LIBS)
 
     MOZ_CHECK_HEADERS([curl/curl.h], [], [AC_MSG_ERROR([Couldn't find curl/curl.h which is required for the crash reporter.  Use --disable-crashreporter to disable the crash reporter.])])
   fi
 
-  if (test "$OS_ARCH" != "$HOST_OS_ARCH"); then
+  if test "$OS_ARCH" != "$HOST_OS_ARCH"; then
     AC_MSG_ERROR([Breakpad tools do not support compiling on $HOST_OS_ARCH while targeting $OS_ARCH.  Use --disable-crashreporter.])
   fi
 
   if test "$OS_ARCH" = "WINNT" -a -z "$HAVE_64BIT_OS"; then
     MOZ_CRASHREPORTER_INJECTOR=1
     AC_DEFINE(MOZ_CRASHREPORTER_INJECTOR)
   fi
 fi
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -8,16 +8,17 @@
  * Overview
  * This contains a set of classes and utilities for CSP.  It is in this
  * separate file for testing purposes.
  */
 
 const Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
 
 // Module stuff
 var EXPORTED_SYMBOLS = ["CSPRep", "CSPSourceList", "CSPSource", "CSPHost",
                         "CSPWarning", "CSPError", "CSPdebug",
                         "CSPViolationReportListener", "CSPLocalizer"];
@@ -26,16 +27,51 @@ var STRINGS_URI = "chrome://global/local
 
 // these are not exported
 var gIoService = Components.classes["@mozilla.org/network/io-service;1"]
                  .getService(Components.interfaces.nsIIOService);
 
 var gETLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"]
                    .getService(Components.interfaces.nsIEffectiveTLDService);
 
+// These regexps represent the concrete syntax on the w3 spec as of 7-5-2012
+// scheme          = <scheme production from RFC 3986>
+const R_SCHEME     = new RegExp ("([a-zA-Z0-9\\-]+)", 'i');
+const R_GETSCHEME  = new RegExp ("^" + R_SCHEME.source + "(?=\\:)", 'i');
+
+// scheme-source   = scheme ":"
+const R_SCHEMESRC  = new RegExp ("^" + R_SCHEME.source + "\\:$", 'i');
+
+// host-char       = ALPHA / DIGIT / "-"
+const R_HOSTCHAR   = new RegExp ("[a-zA-Z0-9\\-]", 'i');
+
+// host            = "*" / [ "*." ] 1*host-char *( "." 1*host-char )
+const R_HOST       = new RegExp ("\\*|(((\\*\\.)?" + R_HOSTCHAR.source +
+                                      "+)(\\." + R_HOSTCHAR.source +"+)+)",'i');
+// port            = ":" ( 1*DIGIT / "*" )
+const R_PORT       = new RegExp ("(\\:([0-9]+|\\*))", 'i');
+
+// host-source     = [ scheme "://" ] host [ port ]
+const R_HOSTSRC    = new RegExp ("^((" + R_SCHEME.source + "\\:\\/\\/)?("
+                                       +   R_HOST.source + ")"
+                                       +   R_PORT.source + "?)$", 'i');
+
+// ext-host-source = host-source "/" *( <VCHAR except ";" and ","> )
+//                 ; ext-host-source is reserved for future use.
+const R_EXTHOSTSRC = new RegExp ("^" + R_HOSTSRC.source + "\\/[:print:]+$", 'i');
+
+// keyword-source  = "'self'" / "'unsafe-inline'" / "'unsafe-eval'"
+const R_KEYWORDSRC = new RegExp ("^('self'|'unsafe-inline'|'unsafe-eval')$", 'i');
+
+// source-exp      = scheme-source / host-source / keyword-source
+const R_SOURCEEXP  = new RegExp (R_SCHEMESRC.source + "|" +
+                                   R_HOSTSRC.source + "|" +
+                                R_KEYWORDSRC.source,  'i');
+
+
 var gPrefObserver = {
   get debugEnabled () {
     if (!this._branch)
       this._initialize();
     return this._debugEnabled;
   },
 
   _initialize: function() {
@@ -583,46 +619,53 @@ function CSPSourceList() {
  *        URI or CSPSource representing the "self" source
  * @param enforceSelfChecks (optional)
  *        if present, and "true", will check to be sure "self" has the
  *        appropriate values to inherit when they are omitted from the source.
  * @returns
  *        an instance of CSPSourceList 
  */
 CSPSourceList.fromString = function(aStr, self, enforceSelfChecks) {
-  // Source list is:
-  //    <host-dir-value> ::= <source-list>
-  //                       | "'none'"
-  //    <source-list>    ::= <source>
-  //                       | <source-list>" "<source>
+  // source-list = *WSP [ source-expression *( 1*WSP source-expression ) *WSP ]
+  //             / *WSP "'none'" *WSP
 
   /* If self parameter is passed, convert to CSPSource,
      unless it is already a CSPSource. */
   if(self && !(self instanceof CSPSource)) {
      self = CSPSource.create(self);
   }
 
   var slObj = new CSPSourceList();
-  if (aStr === "'none'")
-    return slObj;
-
-  if (aStr === "*") {
-    slObj._permitAllSources = true;
+  aStr = aStr.trim();
+  // w3 specifies case insensitive equality
+  if (aStr.toUpperCase() === "'NONE'"){
+    slObj._permitAllSources = false;
     return slObj;
   }
 
   var tokens = aStr.split(/\s+/);
   for (var i in tokens) {
-    if (tokens[i] === "") continue;
+    if (!R_SOURCEEXP.test(tokens[i])){
+      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
+                                           [tokens[i]]));
+      continue;
+    }
     var src = CSPSource.create(tokens[i], self, enforceSelfChecks);
     if (!src) {
-      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource", [tokens[i]]));
+      CSPWarning(CSPLocalizer.getFormatStr("failedToParseUnrecognizedSource",
+                                           [tokens[i]]));
       continue;
     }
-    slObj._sources.push(src);
+    // if a source is a *, then we can permit all sources
+    if (src.permitAll){
+      slObj._permitAllSources = true;
+      return slObj;
+    } else {
+      slObj._sources.push(src);
+    }
   }
 
   return slObj;
 };
 
 CSPSourceList.prototype = {
   /**
    * Compares one CSPSourceList to another.
@@ -782,16 +825,19 @@ CSPSourceList.prototype = {
 /**
  * Class to model a source (scheme, host, port)
  */
 function CSPSource() {
   this._scheme = undefined;
   this._port = undefined;
   this._host = undefined;
 
+  //when set to true, this allows all source
+  this._permitAll = false;
+
   // when set to true, this source represents 'self'
   this._isSelf = false;
 }
 
 /**
  * General factory method to create a new source from one of the following
  * types:
  *  - nsURI
@@ -919,157 +965,93 @@ CSPSource.fromString = function(aStr, se
   if (!aStr)
     return null;
 
   if (!(typeof aStr === 'string')) {
     CSPError(CSPLocalizer.getStr("argumentIsNotString"));
     return null;
   }
 
+  var sObj = new CSPSource();
+  sObj._self = self;
+
+  // if equal, return does match
+  if (aStr === "*"){
+    sObj._permitAll = true;
+    return sObj;
+  }
+
   if (!self && enforceSelfChecks) {
     CSPError(CSPLocalizer.getStr("selfDataNotProvided"));
     return null;
   }
 
   if (self && !(self instanceof CSPSource)) {
     self = CSPSource.create(self, undefined, false);
   }
 
-  var sObj = new CSPSource();
-  sObj._self = self;
+  // check for scheme-source match
+  if (R_SCHEMESRC.test(aStr)){
+    var schemeSrcMatch = R_GETSCHEME.exec(aStr);
+    sObj._scheme = schemeSrcMatch[0];
+    if (!sObj._host) sObj._host = CSPHost.fromString("*");
+    if (!sObj._port) sObj._port = "*";
+    return sObj;
+  }
+
+  // check for host-source or ext-host-source match
+  if (R_HOSTSRC.test(aStr) || R_EXTHOSTSRC.test(aStr)){
+    var schemeMatch = R_GETSCHEME.exec(aStr);
+    if (!schemeMatch)
+      sObj._scheme = self.scheme;
+    else {
+      sObj._scheme = schemeMatch[0];
+    }
 
-  // take care of 'self' keyword
-  if (aStr === "'self'") {
-    if (!self) {
+    var hostMatch = R_HOST.exec(aStr);
+    if (!hostMatch) {
+      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
+      return null;
+    }
+    sObj._host = CSPHost.fromString(hostMatch[0]);
+    var portMatch = R_PORT.exec(aStr);
+    if (!portMatch) {
+      // gets the default port for the given scheme
+      defPort = Services.io.getProtocolHandler(sObj._scheme).defaultPort;
+      if (!defPort) {
+        CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource", [aStr]));
+        return null;
+      }
+      sObj._port = defPort;
+    }
+    else {
+      // strip the ':' from the port
+      sObj._port = portMatch[0].substr(1);
+    }
+    return sObj;
+  }
+
+  // check for 'self' (case insensitive)
+  if (aStr.toUpperCase() === "'SELF'"){
+    if (!self){
       CSPError(CSPLocalizer.getStr("selfKeywordNoSelfData"));
       return null;
     }
     sObj._self = self.clone();
     sObj._isSelf = true;
     return sObj;
   }
-
-  // We could just create a URI and then send this off to fromURI, but
-  // there's no way to leave out the scheme or wildcard the port in an nsURI.
-  // That has to be supported here.
-
-  // split it up
-  var chunks = aStr.split(":");
-
-  // If there is only one chunk, it's gotta be a host.
-  if (chunks.length == 1) {
-    sObj._host = CSPHost.fromString(chunks[0]);
-    if (!sObj._host) {
-      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-      return null;
-    }
-
-    // enforce 'self' inheritance
-    if (enforceSelfChecks) {
-      // note: the non _scheme accessor checks sObj._self
-      if (!sObj.scheme || !sObj.port) {
-        CSPError(CSPLocalizer.getFormatStr("hostSourceWithoutData",[aStr]));
-        return null;
-      }
-    }
-    return sObj;
-  }
-
-  // If there are two chunks, it's either scheme://host or host:port
-  //   ... but scheme://host can have an empty host.
-  //   ... and host:port can have an empty host
-  if (chunks.length == 2) {
-
-    // is the last bit a port?
-    if (chunks[1] === "*" || chunks[1].match(/^\d+$/)) {
-      sObj._port = chunks[1];
-      // then the previous chunk *must* be a host or empty.
-      if (chunks[0] !== "") {
-        sObj._host = CSPHost.fromString(chunks[0]);
-        if (!sObj._host) {
-          CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-          return null;
-        }
-      }
-      // enforce 'self' inheritance 
-      // (scheme:host requires port, host:port does too.  Wildcard support is
-      // only available if the scheme and host are wildcarded)
-      if (enforceSelfChecks) {
-        // note: the non _scheme accessor checks sObj._self
-        if (!sObj.scheme || !sObj.host || !sObj.port) {
-          CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
-          return null;
-        }
-      }
-    }
-    // is the first bit a scheme?
-    else if (CSPSource.validSchemeName(chunks[0])) {
-      sObj._scheme = chunks[0];
-      // then the second bit *must* be a host or empty
-      if (chunks[1] === "") {
-        // Allow scheme-only sources!  These default to wildcard host/port,
-        // especially since host and port don't always matter.
-        // Example: "javascript:" and "data:" 
-        if (!sObj._host) sObj._host = CSPHost.fromString("*");
-        if (!sObj._port) sObj._port = "*";
-      } else {
-        // some host was defined.
-        // ... remove <= 3 leading slashes (from the scheme) and parse
-        var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
-        // ... and parse
-        sObj._host = CSPHost.fromString(cleanHost);
-        if (!sObj._host) {
-          CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidHost",[cleanHost]));
-          return null;
-        }
-      }
-
-      // enforce 'self' inheritance (scheme-only should be scheme:*:* now, and
-      // if there was a host provided it should be scheme:host:selfport
-      if (enforceSelfChecks) {
-        // note: the non _scheme accessor checks sObj._self
-        if (!sObj.scheme || !sObj.host || !sObj.port) {
-          CSPError(CSPLocalizer.getFormatStr("sourceWithoutData",[aStr]));
-          return null;
-        }
-      }
-    }
-    else  {
-      // AAAH!  Don't know what to do!  No valid scheme or port!
-      CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
-      return null;
-    }
-
-    return sObj;
-  }
-
-  // If there are three chunks, we got 'em all!
-  if (!CSPSource.validSchemeName(chunks[0])) {
-    CSPError(CSPLocalizer.getFormatStr("couldntParseScheme",[aStr]));
-    return null;
-  }
-  sObj._scheme = chunks[0];
-  if (!(chunks[2] === "*" || chunks[2].match(/^\d+$/))) {
-    CSPError(CSPLocalizer.getFormatStr("couldntParsePort",[aStr]));
-    return null;
-  }
-
-  sObj._port = chunks[2];
-
-  // ... remove <= 3 leading slashes (from the scheme) and parse
-  var cleanHost = chunks[1].replace(/^\/{0,3}/,"");
-  sObj._host = CSPHost.fromString(cleanHost);
-
-  return sObj._host ? sObj : null;
+  CSPError(CSPLocalizer.getFormatStr("couldntParseInvalidSource",[aStr]));
+  return null;
 };
 
 CSPSource.validSchemeName = function(aStr) {
   // <scheme-name>       ::= <alpha><scheme-suffix>
-  // <scheme-suffix>     ::= <scheme-chr> 
-  //                      | <scheme-suffix><scheme-chr> 
+  // <scheme-suffix>     ::= <scheme-chr>
+  //                      | <scheme-suffix><scheme-chr>
   // <scheme-chr>        ::= <letter> | <digit> | "+" | "." | "-"
   
   return aStr.match(/^[a-zA-Z][a-zA-Z0-9+.-]*$/);
 };
 
 CSPSource.prototype = {
 
   get scheme () {
@@ -1083,17 +1065,23 @@ CSPSource.prototype = {
   get host () {
     if (this._isSelf && this._self)
       return this._self.host;
     if (!this._host && this._self)
       return this._self.host;
     return this._host;
   },
 
-  /** 
+  get permitAll () {
+    if (this._isSelf && this._self)
+      return this._self.permitAll;
+    return this._permitAll;
+  },
+
+  /**
    * If this doesn't have a nonstandard port (hard-defined), use the default
    * port for this source's scheme. Should never inherit port from 'self'.
    */
   get port () {
     if (this._isSelf && this._self)
       return this._self.port;
     if (this._port) return this._port;
     // if no port, get the default port for the scheme
--- a/content/base/src/nsNodeInfo.cpp
+++ b/content/base/src/nsNodeInfo.cpp
@@ -77,17 +77,17 @@ nsNodeInfo::~nsNodeInfo()
   NS_RELEASE(mOwnerManager);
 }
 
 
 nsNodeInfo::nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
                        PRUint16 aNodeType, nsIAtom* aExtraName,
                        nsNodeInfoManager *aOwnerManager)
 {
-  CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
+  CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
   NS_ABORT_IF_FALSE(aOwnerManager, "Invalid aOwnerManager");
 
   // Initialize mInner
   NS_ADDREF(mInner.mName = aName);
   NS_IF_ADDREF(mInner.mPrefix = aPrefix);
   mInner.mNamespaceID = aNamespaceID;
   mInner.mNodeType = aNodeType;
   NS_ADDREF(mOwnerManager = aOwnerManager);
--- a/content/base/src/nsNodeInfo.h
+++ b/content/base/src/nsNodeInfo.h
@@ -12,16 +12,18 @@
 #ifndef nsNodeInfo_h___
 #define nsNodeInfo_h___
 
 #include "nsINodeInfo.h"
 #include "nsNodeInfoManager.h"
 #include "plhash.h"
 #include "nsIAtom.h"
 #include "nsCOMPtr.h"
+#include "nsIDOMNode.h"
+#include "nsGkAtoms.h"
 
 class nsFixedSizeAllocator;
 
 class nsNodeInfo : public nsINodeInfo
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsNodeInfo)
@@ -58,50 +60,54 @@ public:
 private:
   static nsFixedSizeAllocator* sNodeInfoPool;
 
   /**
    * This method gets called by Release() when it's time to delete 
    * this object, instead of always deleting the object we'll put the
    * object in the cache unless the cache is already full.
    */
-   void LastRelease();
+  void LastRelease();
 };
 
-#define CHECK_VALID_NODEINFO(_nodeType, _name, _namespaceID, _extraName)    \
-NS_ABORT_IF_FALSE(_nodeType == nsIDOMNode::ELEMENT_NODE ||                  \
-                  _nodeType == nsIDOMNode::ATTRIBUTE_NODE ||                \
-                  _nodeType == nsIDOMNode::TEXT_NODE ||                     \
-                  _nodeType == nsIDOMNode::CDATA_SECTION_NODE ||            \
-                  _nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||   \
-                  _nodeType == nsIDOMNode::COMMENT_NODE ||                  \
-                  _nodeType == nsIDOMNode::DOCUMENT_NODE ||                 \
-                  _nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||            \
-                  _nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||        \
-                  _nodeType == PR_UINT16_MAX,                               \
-                  "Invalid nodeType");                                      \
-NS_ABORT_IF_FALSE((_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||  \
-                   _nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==          \
-                  (_extraName != nullptr),                                   \
-                  "Supply aExtraName for and only for PIs and doctypes");   \
-NS_ABORT_IF_FALSE(_nodeType == nsIDOMNode::ELEMENT_NODE ||                  \
-                  _nodeType == nsIDOMNode::ATTRIBUTE_NODE ||                \
-                  _nodeType == PR_UINT16_MAX ||                             \
-                  aNamespaceID == kNameSpaceID_None,                        \
-                  "Only attributes and elements can be in a namespace");    \
-NS_ABORT_IF_FALSE(_name && _name != nsGkAtoms::_empty, "Invalid localName");\
-NS_ABORT_IF_FALSE(((_nodeType == nsIDOMNode::TEXT_NODE) ==                  \
-                   (_name == nsGkAtoms::textTagName)) &&                    \
-                  ((_nodeType == nsIDOMNode::CDATA_SECTION_NODE) ==         \
-                   (_name == nsGkAtoms::cdataTagName)) &&                   \
-                  ((_nodeType == nsIDOMNode::COMMENT_NODE) ==               \
-                   (_name == nsGkAtoms::commentTagName)) &&                 \
-                  ((_nodeType == nsIDOMNode::DOCUMENT_NODE) ==              \
-                   (_name == nsGkAtoms::documentNodeName)) &&               \
-                  ((_nodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==     \
-                   (_name == nsGkAtoms::documentFragmentNodeName)) &&       \
-                  ((_nodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==         \
-                   (_name == nsGkAtoms::documentTypeNodeName)) &&           \
-                  ((_nodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==\
-                   (_name == nsGkAtoms::processingInstructionTagName)),     \
-                  "Wrong localName for nodeType");
+inline void
+CheckValidNodeInfo(PRUint16 aNodeType, nsIAtom *aName, PRInt32 aNamespaceID,
+                   nsIAtom* aExtraName)
+{
+  NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
+                    aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
+                    aNodeType == nsIDOMNode::TEXT_NODE ||
+                    aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
+                    aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
+                    aNodeType == nsIDOMNode::COMMENT_NODE ||
+                    aNodeType == nsIDOMNode::DOCUMENT_NODE ||
+                    aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
+                    aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
+                    aNodeType == PR_UINT16_MAX,
+                    "Invalid nodeType");
+  NS_ABORT_IF_FALSE((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
+                     aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
+                    !!aExtraName,
+                    "Supply aExtraName for and only for PIs and doctypes");
+  NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
+                    aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
+                    aNodeType == PR_UINT16_MAX ||
+                    aNamespaceID == kNameSpaceID_None,
+                    "Only attributes and elements can be in a namespace");
+  NS_ABORT_IF_FALSE(aName && aName != nsGkAtoms::_empty, "Invalid localName");
+  NS_ABORT_IF_FALSE(((aNodeType == nsIDOMNode::TEXT_NODE) ==
+                     (aName == nsGkAtoms::textTagName)) &&
+                    ((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
+                     (aName == nsGkAtoms::cdataTagName)) &&
+                    ((aNodeType == nsIDOMNode::COMMENT_NODE) ==
+                     (aName == nsGkAtoms::commentTagName)) &&
+                    ((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
+                     (aName == nsGkAtoms::documentNodeName)) &&
+                    ((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
+                     (aName == nsGkAtoms::documentFragmentNodeName)) &&
+                    ((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
+                     (aName == nsGkAtoms::documentTypeNodeName)) &&
+                    ((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
+                     (aName == nsGkAtoms::processingInstructionTagName)),
+                    "Wrong localName for nodeType");
+}
 
 #endif /* nsNodeInfo_h___ */
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -205,17 +205,17 @@ nsNodeInfoManager::DropDocumentReference
 }
 
 
 already_AddRefed<nsINodeInfo>
 nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
                                PRInt32 aNamespaceID, PRUint16 aNodeType,
                                nsIAtom* aExtraName /* = nullptr */)
 {
-  CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
+  CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
 
   nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType,
                                       aExtraName);
 
   void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
 
   if (node) {
     nsINodeInfo* nodeInfo = static_cast<nsINodeInfo *>(node);
@@ -251,17 +251,17 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
                                PRInt32 aNamespaceID, PRUint16 aNodeType,
                                nsINodeInfo** aNodeInfo)
 {
 #ifdef DEBUG
   {
     nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aName);
-    CHECK_VALID_NODEINFO(aNodeType, nameAtom, aNamespaceID, nullptr);
+    CheckValidNodeInfo(aNodeType, nameAtom, aNamespaceID, nullptr);
   }
 #endif
 
   nsINodeInfo::nsNodeInfoInner tmpKey(aName, aPrefix, aNamespaceID, aNodeType);
 
   void *node = PL_HashTableLookup(mNodeInfoHash, &tmpKey);
 
   if (node) {
--- a/content/base/test/unit/test_csputils.js
+++ b/content/base/test/unit/test_csputils.js
@@ -154,39 +154,45 @@ test(
     });
 
 ///////////////////// Test the Source object //////////////////////
 
 test(
     function test_CSPSource_fromString() {
     // can't do these tests because "self" is not defined.
       //"basic source should not be null.");
-      do_check_neq(null, CSPSource.fromString("a.com"));
+      do_check_neq(null, CSPSource.fromString("a.com", "http://abc.com"));
 
       //"ldh characters should all work for host.");
-      do_check_neq(null, CSPSource.fromString("a2-c.com"));
+      do_check_neq(null, CSPSource.fromString("a2-c.com", "https://a.com"));
 
       //"wildcard should work in first token for host.");
-      do_check_neq(null, CSPSource.fromString("*.a.com"));
+      do_check_neq(null, CSPSource.fromString("*.a.com", "http://abc.com"));
 
       //print(" --- Ignore the following two errors if they print ---");
       //"wildcard should not work in non-first token for host.");
-      do_check_eq(null, CSPSource.fromString("x.*.a.com"));
+      do_check_eq(null, CSPSource.fromString("x.*.a.com", "http://a.com"));
 
       //"funny characters (#) should not work for host.");
-      do_check_eq(null, CSPSource.fromString("a#2-c.com"));
+      do_check_eq(null, CSPSource.fromString("a#2-c.com", "http://a.com"));
 
       //print(" --- Stop ignoring errors that print ---\n");
 
       //"failed to parse host with port.");
-      do_check_neq(null, CSPSource.create("a.com:23"));
+      do_check_neq(null, CSPSource.create("a.com:23", "http://a.com"));
       //"failed to parse host with scheme.");
-      do_check_neq(null, CSPSource.create("https://a.com"));
+      do_check_neq(null, CSPSource.create("https://a.com", "http://a.com"));
       //"failed to parse host with scheme and port.");
-      do_check_neq(null, CSPSource.create("https://a.com:200"));
+      do_check_neq(null, CSPSource.create("https://a.com:200", "http://a.com"));
+
+      //Check to make sure we don't match multiple instances with regex
+      do_check_eq(null, CSPSource.create("http://foo.com:bar.com:23"));
+      //Port parsing should work for all schemes
+      do_check_neq(null, CSPSource.create("data:"));
+      do_check_neq(null, CSPSource.create("javascript:"));
     });
 
 test(
     function test_CSPSource_fromString_withSelf() {
       var src;
       src = CSPSource.create("a.com", "https://foobar.com:443");
       //"src should inherit port *
       do_check_true(src.permits("https://a.com:443"));
@@ -265,16 +271,17 @@ test(
 
 test(
     function test_CSPSourceList_permits() {
       var nullSourceList = CSPSourceList.fromString("'none'");
       var simpleSourceList = CSPSourceList.fromString("a.com", URI("http://self.com"));
       var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88",
                                                       URI("http://self.com:88"));
       var allSourceList = CSPSourceList.fromString("*");
+      var allAndMoreSourceList = CSPSourceList.fromString("* https://bar.com 'none'");
 
       //'none' should permit none."
       do_check_false( nullSourceList.permits("http://a.com"));
       //a.com should permit a.com"
       do_check_true( simpleSourceList.permits("http://a.com"));
       //wrong host"
       do_check_false( simpleSourceList.permits("http://b.com"));
       //double list permits http://bar.com:88"
@@ -288,25 +295,27 @@ test(
       //"double list does not permit foo.com on http"
       do_check_false( doubleSourceList.permits("http://foo.com"));
 
       //"* does not permit specific host"
       do_check_true( allSourceList.permits("http://x.com:23"));
       //"* does not permit a long host with no port"
       do_check_true( allSourceList.permits("http://a.b.c.d.e.f.g.h.i.j.k.l.x.com"));
 
+      //* short circuts parsing
+      do_check_true(allAndMoreSourceList.permits("http://a.com"));
     });
 
 test(
     function test_CSPSourceList_intersect() {
       // for this test, 'self' values are irrelevant
       // policy a /\ policy b intersects policies, not context (where 'self'
       // values come into play)
       var nullSourceList = CSPSourceList.fromString("'none'");
-      var simpleSourceList = CSPSourceList.fromString("a.com");
+      var simpleSourceList = CSPSourceList.fromString("http://a.com");
       var doubleSourceList = CSPSourceList.fromString("https://foo.com http://bar.com:88");
       var singleFooSourceList = CSPSourceList.fromString("https://foo.com");
       var allSourceList = CSPSourceList.fromString("*");
 
       //"Intersection of one source with 'none' source list should be none.");
       do_check_true(nullSourceList.intersectWith(simpleSourceList).isNone());
       //"Intersection of two sources with 'none' source list should be none.");
       do_check_true(nullSourceList.intersectWith(doubleSourceList).isNone());
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -98,17 +98,17 @@ XBLFinalize(JSFreeOp *fop, JSObject *obj
 // admittedly convoluted.  Better would be for XBL-backed elements to be proxies
 // that could resolve fields onto themselves.  But given that XBL bindings are
 // associated with elements mutably -- you can add/remove/change -moz-binding
 // whenever you want, alas -- doing so would require all elements to be proxies,
 // which isn't performant now.  So we do this two-step instead.
 static const uint32_t XBLPROTO_SLOT = 0;
 static const uint32_t FIELD_SLOT = 1;
 
-static bool
+bool
 ValueHasISupportsPrivate(const JS::Value &v)
 {
   if (!v.isObject()) {
     return false;
   }
 
   JSClass* clasp = ::JS_GetClass(&v.toObject());
   const uint32_t HAS_PRIVATE_NSISUPPORTS =
@@ -209,17 +209,17 @@ InstallXBLField(JSContext* cx,
   }
 
   if (!::JS_IsExceptionPending(cx)) {
     xpc::Throw(cx, rv);
   }
   return false;
 }
 
-static bool
+bool
 FieldGetterImpl(JSContext *cx, JS::CallArgs args)
 {
   const JS::Value &thisv = args.thisv();
   MOZ_ASSERT(ValueHasISupportsPrivate(thisv));
 
   JS::Rooted<JSObject*> thisObj(cx, &thisv.toObject());
 
   bool installed = false;
@@ -241,21 +241,21 @@ FieldGetterImpl(JSContext *cx, JS::CallA
   args.rval().set(v);
   return true;
 }
 
 static JSBool
 FieldGetter(JSContext *cx, unsigned argc, JS::Value *vp)
 {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  return JS::CallNonGenericMethod(cx, ValueHasISupportsPrivate, FieldGetterImpl,
-                                  args);
+  return JS::CallNonGenericMethod<ValueHasISupportsPrivate, FieldGetterImpl>
+                                 (cx, args);
 }
 
-static bool
+bool
 FieldSetterImpl(JSContext *cx, JS::CallArgs args)
 {
   const JS::Value &thisv = args.thisv();
   MOZ_ASSERT(ValueHasISupportsPrivate(thisv));
 
   JS::Rooted<JSObject*> thisObj(cx, &thisv.toObject());
 
   bool installed = false;
@@ -269,18 +269,18 @@ FieldSetterImpl(JSContext *cx, JS::CallA
                           args.length() > 0 ? args[0] : JS::UndefinedValue());
   return JS_SetPropertyById(cx, thisObj, id, v.address());
 }
 
 static JSBool
 FieldSetter(JSContext *cx, unsigned argc, JS::Value *vp)
 {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  return JS::CallNonGenericMethod(cx, ValueHasISupportsPrivate, FieldSetterImpl,
-                                  args);
+  return JS::CallNonGenericMethod<ValueHasISupportsPrivate, FieldSetterImpl>
+                                 (cx, args);
 }
 
 static JSBool
 XBLResolve(JSContext *cx, JSHandleObject obj, JSHandleId id, unsigned flags,
            JSMutableHandleObject objp)
 {
   objp.set(NULL);
 
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -207,17 +207,17 @@ IDBTransaction::OnNewRequest()
 
 void
 IDBTransaction::OnRequestFinished()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mPendingRequests, "Mismatched calls!");
   --mPendingRequests;
   if (!mPendingRequests) {
-    NS_ASSERTION(mAbortCode || mReadyState == IDBTransaction::LOADING,
+    NS_ASSERTION(NS_FAILED(mAbortCode) || mReadyState == IDBTransaction::LOADING,
                  "Bad state!");
     mReadyState = IDBTransaction::COMMITTING;
     CommitOrRollback();
   }
 }
 
 void
 IDBTransaction::RemoveObjectStore(const nsAString& aName)
@@ -838,17 +838,17 @@ CommitHelper::Run()
     // destroyed on correct thread.
     mTransaction->ClearCreatedFileInfos();
     if (mUpdateFileRefcountFunction) {
       mUpdateFileRefcountFunction->ClearFileInfoEntries();
       mUpdateFileRefcountFunction = nullptr;
     }
 
     nsCOMPtr<nsIDOMEvent> event;
-    if (mAbortCode) {
+    if (NS_FAILED(mAbortCode)) {
       if (mTransaction->GetMode() == IDBTransaction::VERSION_CHANGE) {
         // This will make the database take a snapshot of it's DatabaseInfo
         mTransaction->Database()->Close();
         // Then remove the info from the hash as it contains invalid data.
         DatabaseInfo::Remove(mTransaction->Database()->Id());
       }
 
       event = CreateGenericEvent(NS_LITERAL_STRING(ABORT_EVT_STR),
@@ -893,26 +893,26 @@ CommitHelper::Run()
   IDBDatabase* database = mTransaction->Database();
   if (database->IsInvalidated()) {
     mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
   }
 
   if (mConnection) {
     IndexedDatabaseManager::SetCurrentWindow(database->GetOwner());
 
-    if (!mAbortCode && mUpdateFileRefcountFunction &&
+    if (NS_SUCCEEDED(mAbortCode) && mUpdateFileRefcountFunction &&
         NS_FAILED(mUpdateFileRefcountFunction->UpdateDatabase(mConnection))) {
       mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
-    if (!mAbortCode && NS_FAILED(WriteAutoIncrementCounts())) {
+    if (NS_SUCCEEDED(mAbortCode) && NS_FAILED(WriteAutoIncrementCounts())) {
       mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
     }
 
-    if (!mAbortCode) {
+    if (NS_SUCCEEDED(mAbortCode)) {
       NS_NAMED_LITERAL_CSTRING(release, "COMMIT TRANSACTION");
       nsresult rv = mConnection->ExecuteSimpleSQL(release);
       if (NS_SUCCEEDED(rv)) {
         if (mUpdateFileRefcountFunction) {
           mUpdateFileRefcountFunction->UpdateFileInfos();
         }
         CommitAutoIncrementCounts();
       }
@@ -921,17 +921,17 @@ CommitHelper::Run()
         // which we know better as NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR.
         mAbortCode = NS_ERROR_DOM_INDEXEDDB_QUOTA_ERR;
       }
       else {
         mAbortCode = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       }
     }
 
-    if (mAbortCode) {
+    if (NS_FAILED(mAbortCode)) {
       RevertAutoIncrementCounts();
       NS_NAMED_LITERAL_CSTRING(rollback, "ROLLBACK TRANSACTION");
       if (NS_FAILED(mConnection->ExecuteSimpleSQL(rollback))) {
         NS_WARNING("Failed to rollback transaction!");
       }
     }
   }
 
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -2438,17 +2438,18 @@ NPError NP_CALLBACK
             rv = contextStack->Pop(nullptr);
           }
         }
         return NS_SUCCEEDED(rv) ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR;
       }
 
     case NPPVpluginKeepLibraryInMemory: {
       NPBool bCached = (result != nullptr);
-      return inst->SetCached(bCached);
+      inst->SetCached(bCached);
+      return NPERR_NO_ERROR;
     }
 
     case NPPVpluginUsesDOMForCursorBool: {
       bool useDOMForCursor = (result != nullptr);
       return inst->SetUsesDOMForCursor(useDOMForCursor);
     }
 
 #ifndef MOZ_WIDGET_ANDROID
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -83,25 +83,22 @@ static bool EnsureGLContext()
 
   return sPluginContext != nullptr;
 }
 
 class SharedPluginTexture {
 public:
   NS_INLINE_DECL_REFCOUNTING(SharedPluginTexture)
 
-  SharedPluginTexture() :
-    mCurrentHandle(0), mNeedNewImage(false), mLock("SharedPluginTexture.mLock")
+  SharedPluginTexture() : mLock("SharedPluginTexture.mLock")
   {
   }
 
   ~SharedPluginTexture()
   {
-    // This will be destroyed in the compositor (as it normally is)
-    mCurrentHandle = 0;
   }
 
   TextureInfo Lock()
   {
     if (!EnsureGLContext()) {
       mTextureInfo.mTexture = 0;
       return mTextureInfo;
     }
@@ -110,54 +107,44 @@ public:
       sPluginContext->fGenTextures(1, &mTextureInfo.mTexture);
     }
 
     mLock.Lock();
     return mTextureInfo;
   }
 
   void Release(TextureInfo& aTextureInfo)
-  {
-    mNeedNewImage = true;
- 
+  { 
     mTextureInfo = aTextureInfo;
     mLock.Unlock();
   } 
 
   SharedTextureHandle CreateSharedHandle()
   {
     MutexAutoLock lock(mLock);
 
-    if (!mNeedNewImage)
-      return mCurrentHandle;
-
     if (!EnsureGLContext())
       return 0;
 
-    mNeedNewImage = false;
-
     if (mTextureInfo.mWidth == 0 || mTextureInfo.mHeight == 0)
       return 0;
 
-    mCurrentHandle = sPluginContext->CreateSharedHandle(TextureImage::ThreadShared, (void*)mTextureInfo.mTexture, GLContext::TextureID);
+    SharedTextureHandle handle = sPluginContext->CreateSharedHandle(TextureImage::ThreadShared, (void*)mTextureInfo.mTexture, GLContext::TextureID);
 
     // We want forget about this now, so delete the texture. Assigning it to zero
     // ensures that we create a new one in Lock()
     sPluginContext->fDeleteTextures(1, &mTextureInfo.mTexture);
     mTextureInfo.mTexture = 0;
     
-    return mCurrentHandle;
+    return handle;
   }
 
 private:
   TextureInfo mTextureInfo;
-  SharedTextureHandle mCurrentHandle;
  
-  bool mNeedNewImage;
-
   Mutex mLock;
 };
 
 #endif
 
 using namespace mozilla;
 using namespace mozilla::plugins::parent;
 
@@ -997,17 +984,17 @@ nsSurfaceTexture* nsNPAPIPluginInstance:
   nsCOMPtr<nsIRunnable> frameCallback = NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable);
   surface->SetFrameAvailableCallback(frameCallback);
   return surface;
 }
 
 void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
 {
   if (mRunning == RUNNING && mOwner)
-    RedrawPlugin();
+    AndroidBridge::Bridge()->ScheduleComposite();
 }
 
 void* nsNPAPIPluginInstance::AcquireContentWindow()
 {
   if (!mContentSurface) {
     mContentSurface = CreateSurfaceTexture();
 
     if (!mContentSurface)
@@ -1115,21 +1102,20 @@ nsNPAPIPluginInstance::GetJSObject(JSCon
 
   *outObject = nsNPObjWrapper::GetNewOrUsed(&mNPP, cx, npobj);
 
   _releaseobject(npobj);
 
   return NS_OK;
 }
 
-nsresult
+void
 nsNPAPIPluginInstance::SetCached(bool aCache)
 {
   mCached = aCache;
-  return NS_OK;
 }
 
 bool
 nsNPAPIPluginInstance::ShouldCache()
 {
   return mCached;
 }
 
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -227,17 +227,17 @@ public:
   bool CanFireNotifications() {
     return mRunning == RUNNING || mRunning == DESTROYING;
   }
 
   // return is only valid when the plugin is not running
   mozilla::TimeStamp StopTime();
 
   // cache this NPAPI plugin
-  nsresult SetCached(bool aCache);
+  void SetCached(bool aCache);
 
   already_AddRefed<nsPIDOMWindow> GetDOMWindow();
 
   nsresult PrivateModeStateChanged(bool aEnabled);
 
   nsresult GetDOMElement(nsIDOMElement* *result);
 
   nsNPAPITimer* TimerWithID(uint32_t id, PRUint32* index);
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -1494,17 +1494,17 @@ XMLHttpRequest::ReleaseProxy(ReleaseType
   if (mProxy) {
     if (aType == XHRIsGoingAway) {
       // We're in a GC finalizer, so we can't do a sync call here (and we don't
       // need to).
       nsRefPtr<AsyncTeardownRunnable> runnable =
         new AsyncTeardownRunnable(mProxy);
       mProxy = nullptr;
 
-      if (NS_DispatchToMainThread(runnable)) {
+      if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
         NS_ERROR("Failed to dispatch teardown runnable!");
       }
     } else {
       // This isn't necessary if the worker is going away or the XHR is going
       // away.
       if (aType == Default) {
         // Don't let any more events run.
         mProxy->mOuterEventStreamId++;
--- a/gfx/2d/Blur.cpp
+++ b/gfx/2d/Blur.cpp
@@ -343,42 +343,39 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& a
     mDirtyRect = *aDirtyRect;
     Rect requiredBlurArea = mDirtyRect.Intersect(rect);
     requiredBlurArea.Inflate(Size(aBlurRadius + aSpreadRadius));
     rect = requiredBlurArea.Intersect(rect);
   } else {
     mHasDirtyRect = false;
   }
 
-  if (rect.IsEmpty()) {
+  mRect = IntRect(rect.x, rect.y, rect.width, rect.height);
+  if (mRect.IsEmpty()) {
     return;
   }
 
   if (aSkipRect) {
     // If we get passed a skip rect, we can lower the amount of
     // blurring/spreading we need to do. We convert it to IntRect to avoid
     // expensive int<->float conversions if we were to use Rect instead.
     Rect skipRect = *aSkipRect;
     skipRect.RoundIn();
     skipRect.Deflate(Size(aBlurRadius + aSpreadRadius));
     mSkipRect = IntRect(skipRect.x, skipRect.y, skipRect.width, skipRect.height);
 
-    IntRect shadowIntRect(rect.x, rect.y, rect.width, rect.height);
-    mSkipRect.IntersectRect(mSkipRect, shadowIntRect);
-
-    if (mSkipRect.IsEqualInterior(shadowIntRect))
+    mSkipRect = mSkipRect.Intersect(mRect);
+    if (mSkipRect.IsEqualInterior(mRect))
       return;
 
-    mSkipRect -= shadowIntRect.TopLeft();
+    mSkipRect -= mRect.TopLeft();
   } else {
     mSkipRect = IntRect(0, 0, 0, 0);
   }
 
-  mRect = IntRect(rect.x, rect.y, rect.width, rect.height);
-
   CheckedInt<int32_t> stride = RoundUpToMultipleOf4(mRect.width);
   if (stride.isValid()) {
     mStride = stride.value();
 
     CheckedInt<int32_t> size = CheckedInt<int32_t>(mStride) * mRect.height *
                                sizeof(unsigned char);
     if (size.isValid()) {
       mData = static_cast<unsigned char*>(malloc(size.value()));
--- a/gfx/layers/ImageLayers.cpp
+++ b/gfx/layers/ImageLayers.cpp
@@ -5,16 +5,17 @@
 
 #include "mozilla/ipc/Shmem.h"
 #include "mozilla/ipc/CrossProcessMutex.h"
 #include "ImageLayers.h"
 #include "SharedTextureImage.h"
 #include "gfxImageSurface.h"
 #include "gfxSharedImageSurface.h"
 #include "yuv_convert.h"
+#include "gfxUtils.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/ImageContainerChild.h"
 
 #ifdef XP_MACOSX
 #include "mozilla/gfx/QuartzSupport.h"
 #endif
 
 #ifdef XP_WIN
@@ -459,38 +460,32 @@ PlanarYCbCrImage::SetData(const Data &aD
 already_AddRefed<gfxASurface>
 PlanarYCbCrImage::GetAsSurface()
 {
   if (mSurface) {
     nsRefPtr<gfxASurface> result = mSurface.get();
     return result.forget();
   }
 
-  nsRefPtr<gfxImageSurface> imageSurface =
-    new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
-  
-  gfx::YUVType type = 
-    gfx::TypeFromSize(mData.mYSize.width,
-                      mData.mYSize.height,
-                      mData.mCbCrSize.width,
-                      mData.mCbCrSize.height);
+  gfxASurface::gfxImageFormat format = GetOffscreenFormat();
 
-  // Convert from YCbCr to RGB now
-  gfx::ConvertYCbCrToRGB32(mData.mYChannel,
-                           mData.mCbChannel,
-                           mData.mCrChannel,
-                           imageSurface->Data(),
-                           mData.mPicX,
-                           mData.mPicY,
-                           mData.mPicSize.width,
-                           mData.mPicSize.height,
-                           mData.mYStride,
-                           mData.mCbCrStride,
-                           imageSurface->Stride(),
-                           type);
+  gfxIntSize size(mSize);
+  gfxUtils::GetYCbCrToRGBDestFormatAndSize(mData, format, size);
+  if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
+      size.height > PlanarYCbCrImage::MAX_DIMENSION) {
+    NS_ERROR("Illegal image dest width or height");
+    return nullptr;
+  }
+
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface(mSize, format);
+
+  gfxUtils::ConvertYCbCrToRGB(mData, format, mSize,
+                              imageSurface->Data(),
+                              imageSurface->Stride());
 
   mSurface = imageSurface;
 
   return imageSurface.forget().get();
 }
 
 #ifdef XP_MACOSX
 void
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -88,17 +88,17 @@ InitPrefCaches()
            "detected at line %u for image of "   \
            "type %s\n", this, __LINE__,          \
            mSourceDataMimeType.get()));          \
   PR_END_MACRO
 
 #define CONTAINER_ENSURE_SUCCESS(status)      \
   PR_BEGIN_MACRO                              \
   nsresult _status = status; /* eval once */  \
-  if (_status) {                              \
+  if (NS_FAILED(_status)) {                   \
     LOG_CONTAINER_ERROR;                      \
     DoError();                                \
     return _status;                           \
   }                                           \
  PR_END_MACRO
 
 #define CONTAINER_ENSURE_TRUE(arg, rv)  \
   PR_BEGIN_MACRO                        \
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1032,17 +1032,17 @@ MapObject::size_impl(JSContext *cx, Call
     args.rval().setNumber(map.count());
     return true;
 }
 
 JSBool
 MapObject::size(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, size_impl, args);
+    return CallNonGenericMethod<MapObject::is, MapObject::size_impl>(cx, args);
 }
 
 bool
 MapObject::get_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(MapObject::is(args.thisv()));
 
     ValueMap &map = extract(args);
@@ -1054,17 +1054,17 @@ MapObject::get_impl(JSContext *cx, CallA
         args.rval().setUndefined();
     return true;
 }
 
 JSBool
 MapObject::get(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, get_impl, args);
+    return CallNonGenericMethod<MapObject::is, MapObject::get_impl>(cx, args);
 }
 
 bool
 MapObject::has_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(MapObject::is(args.thisv()));
 
     ValueMap &map = extract(args);
@@ -1072,17 +1072,17 @@ MapObject::has_impl(JSContext *cx, CallA
     args.rval().setBoolean(map.has(key));
     return true;
 }
 
 JSBool
 MapObject::has(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, has_impl, args);
+    return CallNonGenericMethod<MapObject::is, MapObject::has_impl>(cx, args);
 }
 
 bool
 MapObject::set_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(MapObject::is(args.thisv()));
 
     ValueMap &map = extract(args);
@@ -1095,17 +1095,17 @@ MapObject::set_impl(JSContext *cx, CallA
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 MapObject::set(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, set_impl, args);
+    return CallNonGenericMethod<MapObject::is, MapObject::set_impl>(cx, args);
 }
 
 bool
 MapObject::delete_impl(JSContext *cx, CallArgs args)
 {
     // MapObject::mark does not mark deleted entries. Incremental GC therefore
     // requires that no RelocatableValue objects pointing to heap values be
     // left alive in the ValueMap.
@@ -1125,17 +1125,17 @@ MapObject::delete_impl(JSContext *cx, Ca
     args.rval().setBoolean(found);
     return true;
 }
 
 JSBool
 MapObject::delete_(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, delete_impl, args);
+    return CallNonGenericMethod<MapObject::is, MapObject::delete_impl>(cx, args);
 }
 
 bool
 MapObject::iterator_impl(JSContext *cx, CallArgs args)
 {
     Rooted<MapObject*> mapobj(cx, &args.thisv().toObject().asMap());
     ValueMap &map = *mapobj->getData();
     Rooted<JSObject*> iterobj(cx, MapIteratorObject::create(cx, mapobj, &map));
@@ -1404,17 +1404,17 @@ SetObject::size_impl(JSContext *cx, Call
     args.rval().setNumber(set.count());
     return true;
 }
 
 JSBool
 SetObject::size(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, size_impl, args);
+    return CallNonGenericMethod<SetObject::is, SetObject::size_impl>(cx, args);
 }
 
 bool
 SetObject::has_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     ValueSet &set = extract(args);
@@ -1422,17 +1422,17 @@ SetObject::has_impl(JSContext *cx, CallA
     args.rval().setBoolean(set.has(key));
     return true;
 }
 
 JSBool
 SetObject::has(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, has_impl, args);
+    return CallNonGenericMethod<SetObject::is, SetObject::has_impl>(cx, args);
 }
 
 bool
 SetObject::add_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     ValueSet &set = extract(args);
@@ -1444,17 +1444,17 @@ SetObject::add_impl(JSContext *cx, CallA
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 SetObject::add(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, add_impl, args);
+    return CallNonGenericMethod<SetObject::is, SetObject::add_impl>(cx, args);
 }
 
 bool
 SetObject::delete_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     ValueSet &set = extract(args);
@@ -1465,17 +1465,17 @@ SetObject::delete_impl(JSContext *cx, Ca
     args.rval().setBoolean(found);
     return true;
 }
 
 JSBool
 SetObject::delete_(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, delete_impl, args);
+    return CallNonGenericMethod<SetObject::is, SetObject::delete_impl>(cx, args);
 }
 
 bool
 SetObject::iterator_impl(JSContext *cx, CallArgs args)
 {
     Rooted<SetObject*> setobj(cx, &args.thisv().toObject().asSet());
     ValueSet &set = *setobj->getData();
     Rooted<JSObject*> iterobj(cx, SetIteratorObject::create(cx, setobj, &set));
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -291,35 +291,35 @@ CompileRegExpObject(JSContext *cx, RegEx
     RegExpObject *reobj = builder.build(escapedSourceStr, RegExpFlag(flags | res->getFlags()));
     if (!reobj)
         return false;
 
     args.rval().setObject(*reobj);
     return true;
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 IsRegExp(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&RegExpClass);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 regexp_compile_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsRegExp(args.thisv()));
     RegExpObjectBuilder builder(cx, &args.thisv().toObject().asRegExp());
     return CompileRegExpObject(cx, builder, args);
 }
 
-static JSBool
+JSBool
 regexp_compile(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsRegExp, regexp_compile_impl, args);
+    return CallNonGenericMethod<IsRegExp, regexp_compile_impl>(cx, args);
 }
 
 static JSBool
 regexp_construct(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (!IsConstructing(args)) {
@@ -336,34 +336,34 @@ regexp_construct(JSContext *cx, unsigned
             return true;
         }
     }
 
     RegExpObjectBuilder builder(cx);
     return CompileRegExpObject(cx, builder, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 regexp_toString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsRegExp(args.thisv()));
 
     JSString *str = args.thisv().toObject().asRegExp().toString(cx);
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
-static JSBool
+JSBool
 regexp_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsRegExp, regexp_toString_impl, args);
+    return CallNonGenericMethod<IsRegExp, regexp_toString_impl>(cx, args);
 }
 
 static JSFunctionSpec regexp_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,  regexp_toString,    0,0),
 #endif
     JS_FN(js_toString_str,  regexp_toString,    0,0),
     JS_FN("compile",        regexp_compile,     2,0),
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1522,44 +1522,59 @@ CallMethodIfWrapped(JSContext *cx, IsAcc
  *       args.rval().setInt32(42);
  *       return true;
  *   }
  *
  * The implementation function is guaranteed to be called *only* with a |this|
  * value which is considered acceptable.
  *
  * Now to implement the actual method, write a JSNative that calls the method
- * declared below, passing the appropriate arguments.
+ * declared below, passing the appropriate template and runtime arguments.
  *
  *   static JSBool
  *   answer_getAnswer(JSContext *cx, unsigned argc, JS::Value *vp)
  *   {
  *       JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
- *       return JS::CallNonGenericMethod(cx, IsAnswerObject,
-                                         answer_getAnswer_impl, args);
+ *       return JS::CallNonGenericMethod<IsAnswerObject, answer_getAnswer_impl>(cx, args);
  *   }
  *
+ * Note that, because they are used as template arguments, the predicate
+ * and implementation functions must have external linkage. (This is
+ * unfortunate, but GCC wasn't inlining things as one would hope when we
+ * passed them as function arguments.)
+ *
  * JS::CallNonGenericMethod will test whether |args.thisv()| is acceptable.  If
  * it is, it will call the provided implementation function, which will return
  * a value and indicate success.  If it is not, it will attempt to unwrap
  * |this| and call the implementation function on the unwrapped |this|.  If
  * that succeeds, all well and good.  If it doesn't succeed, a TypeError will
  * be thrown.
  *
  * Note: JS::CallNonGenericMethod will only work correctly if it's called in
  *       tail position in a JSNative.  Do not call it from any other place.
  */
+template<IsAcceptableThis Test, NativeImpl Impl>
 JS_ALWAYS_INLINE bool
-CallNonGenericMethod(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args)
+CallNonGenericMethod(JSContext *cx, CallArgs args)
 {
     const Value &thisv = args.thisv();
-    if (test(thisv))
-        return impl(cx, args);
-
-    return detail::CallMethodIfWrapped(cx, test, impl, args);
+    if (Test(thisv))
+        return Impl(cx, args);
+
+    return detail::CallMethodIfWrapped(cx, Test, Impl, args);
+}
+
+JS_ALWAYS_INLINE bool
+CallNonGenericMethod(JSContext *cx, IsAcceptableThis Test, NativeImpl Impl, CallArgs args)
+{
+    const Value &thisv = args.thisv();
+    if (Test(thisv))
+        return Impl(cx, args);
+
+    return detail::CallMethodIfWrapped(cx, Test, Impl, args);
 }
 
 }  /* namespace JS */
 
 /************************************************************************/
 
 /*
  * JS::Value and jsval are the same type; jsval is the old name, kept around
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -1392,23 +1392,23 @@ class ArraySharpDetector
     }
 
     ~ArraySharpDetector() {
         if (success && !sharp)
             js_LeaveSharpObject(cx, NULL);
     }
 };
 
-static bool
+JS_ALWAYS_INLINE bool
 IsArray(const Value &v)
 {
     return v.isObject() && v.toObject().isArray();
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 array_toSource_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsArray(args.thisv()));
 
     Rooted<JSObject*> obj(cx, &args.thisv().toObject());
     RootedValue elt(cx);
 
     ArraySharpDetector detector(cx);
@@ -1467,22 +1467,22 @@ array_toSource_impl(JSContext *cx, CallA
     JSString *str = sb.finishString();
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
-static JSBool
+JSBool
 array_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     JS_CHECK_RECURSION(cx, return false);
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsArray, array_toSource_impl, args);
+    return CallNonGenericMethod<IsArray, array_toSource_impl>(cx, args);
 }
 #endif
 
 class AutoArrayCycleDetector
 {
     JSContext *cx;
     JSObject *obj;
     uint32_t genBefore;
--- a/js/src/jsbool.cpp
+++ b/js/src/jsbool.cpp
@@ -41,24 +41,24 @@ Class js::BooleanClass = {
     JS_PropertyStub,         /* delProperty */
     JS_PropertyStub,         /* getProperty */
     JS_StrictPropertyStub,   /* setProperty */
     JS_EnumerateStub,
     JS_ResolveStub,
     JS_ConvertStub
 };
 
-static bool
+JS_ALWAYS_INLINE bool
 IsBoolean(const Value &v)
 {
     return v.isBoolean() || (v.isObject() && v.toObject().hasClass(&BooleanClass));
 }
 
 #if JS_HAS_TOSOURCE
-static bool
+JS_ALWAYS_INLINE bool
 bool_toSource_impl(JSContext *cx, CallArgs args)
 {
     const Value &thisv = args.thisv();
     JS_ASSERT(IsBoolean(thisv));
 
     bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().asBoolean().unbox();
 
     StringBuffer sb(cx);
@@ -67,58 +67,58 @@ bool_toSource_impl(JSContext *cx, CallAr
 
     JSString *str = sb.finishString();
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 }
 
-static JSBool
+JSBool
 bool_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsBoolean, bool_toSource_impl, args);
+    return CallNonGenericMethod<IsBoolean, bool_toSource_impl>(cx, args);
 }
 #endif
 
-static bool
+JS_ALWAYS_INLINE bool
 bool_toString_impl(JSContext *cx, CallArgs args)
 {
     const Value &thisv = args.thisv();
     JS_ASSERT(IsBoolean(thisv));
 
     bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().asBoolean().unbox();
     args.rval().setString(cx->runtime->atomState.booleanAtoms[b ? 1 : 0]);
     return true;
 }
 
-static JSBool
+JSBool
 bool_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsBoolean, bool_toString_impl, args);
+    return CallNonGenericMethod<IsBoolean, bool_toString_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 bool_valueOf_impl(JSContext *cx, CallArgs args)
 {
     const Value &thisv = args.thisv();
     JS_ASSERT(IsBoolean(thisv));
 
     bool b = thisv.isBoolean() ? thisv.toBoolean() : thisv.toObject().asBoolean().unbox();
     args.rval().setBoolean(b);
     return true;
 }
 
-static JSBool
+JSBool
 bool_valueOf(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsBoolean, bool_valueOf_impl, args);
+    return CallNonGenericMethod<IsBoolean, bool_valueOf_impl>(cx, args);
 }
 
 static JSFunctionSpec boolean_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,  bool_toSource,  0, 0),
 #endif
     JS_FN(js_toString_str,  bool_toString,  0, 0),
     JS_FS_END
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -1435,41 +1435,41 @@ GetCachedLocalTime(JSContext *cx, JSObje
 {
     if (!obj || !CacheLocalTime(cx, obj))
         return false;
 
     *time = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_TIME).toDouble();
     return true;
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 IsDate(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&DateClass);
 }
 
 /*
  * See ECMA 15.9.5.4 thru 15.9.5.23
  */
-static bool
+JS_ALWAYS_INLINE bool
 date_getTime_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
     args.rval().set(args.thisv().toObject().getDateUTCTime());
     return true;
 }
 
 static JSBool
 date_getTime(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getTime_impl, args);
+    return CallNonGenericMethod<IsDate, date_getTime_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
@@ -1484,301 +1484,301 @@ date_getYear_impl(JSContext *cx, CallArg
 
     return true;
 }
 
 static JSBool
 date_getYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getYear_impl, args);
+    return CallNonGenericMethod<IsDate, date_getYear_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getFullYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR));
     return true;
 }
 
 static JSBool
 date_getFullYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getFullYear_impl, args);
+    return CallNonGenericMethod<IsDate, date_getFullYear_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getUTCFullYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double result = args.thisv().toObject().getDateUTCTime().toNumber();
     if (MOZ_DOUBLE_IS_FINITE(result))
         result = YearFromTime(result);
 
     args.rval().setNumber(result);
     return true;
 }
 
 static JSBool
 date_getUTCFullYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getUTCFullYear_impl, args);
+    return CallNonGenericMethod<IsDate, date_getUTCFullYear_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getMonth_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MONTH));
     return true;
 }
 
 static JSBool
 date_getMonth(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getMonth_impl, args);
+    return CallNonGenericMethod<IsDate, date_getMonth_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getUTCMonth_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double d = args.thisv().toObject().getDateUTCTime().toNumber();
     args.rval().setNumber(MonthFromTime(d));
     return true;
 }
 
 static JSBool
 date_getUTCMonth(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getUTCMonth_impl, args);
+    return CallNonGenericMethod<IsDate, date_getUTCMonth_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getDate_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DATE));
     return true;
 }
 
 static JSBool
 date_getDate(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getDate_impl, args);
+    return CallNonGenericMethod<IsDate, date_getDate_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getUTCDate_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double result = args.thisv().toObject().getDateUTCTime().toNumber();
     if (MOZ_DOUBLE_IS_FINITE(result))
         result = DateFromTime(result);
 
     args.rval().setNumber(result);
     return true;
 }
 
 static JSBool
 date_getUTCDate(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getUTCDate_impl, args);
+    return CallNonGenericMethod<IsDate, date_getUTCDate_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getDay_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DAY));
     return true;
 }
 
 static JSBool
 date_getDay(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getDay_impl, args);
+    return CallNonGenericMethod<IsDate, date_getDay_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getUTCDay_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double result = args.thisv().toObject().getDateUTCTime().toNumber();
     if (MOZ_DOUBLE_IS_FINITE(result))
         result = WeekDay(result);
 
     args.rval().setNumber(result);
     return true;
 }
 
 static JSBool
 date_getUTCDay(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getUTCDay_impl, args);
+    return CallNonGenericMethod<IsDate, date_getUTCDay_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getHours_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_HOURS));
     return true;
 }
 
 static JSBool
 date_getHours(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getHours_impl, args);
+    return CallNonGenericMethod<IsDate, date_getHours_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getUTCHours_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double result = args.thisv().toObject().getDateUTCTime().toNumber();
     if (MOZ_DOUBLE_IS_FINITE(result))
         result = HourFromTime(result);
 
     args.rval().setNumber(result);
     return JS_TRUE;
 }
 
 static JSBool
 date_getUTCHours(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getUTCHours_impl, args);
+    return CallNonGenericMethod<IsDate, date_getUTCHours_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getMinutes_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MINUTES));
     return true;
 }
 
 static JSBool
 date_getMinutes(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getMinutes_impl, args);
+    return CallNonGenericMethod<IsDate, date_getMinutes_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getUTCMinutes_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double result = args.thisv().toObject().getDateUTCTime().toNumber();
     if (MOZ_DOUBLE_IS_FINITE(result))
         result = MinFromTime(result);
 
     args.rval().setNumber(result);
     return true;
 }
 
 static JSBool
 date_getUTCMinutes(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getUTCMinutes_impl, args);
+    return CallNonGenericMethod<IsDate, date_getUTCMinutes_impl>(cx, args);
 }
 
 /* Date.getSeconds is mapped to getUTCSeconds */
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getUTCSeconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (!CacheLocalTime(cx, thisObj))
         return false;
 
     args.rval().set(thisObj->getSlot(JSObject::JSSLOT_DATE_LOCAL_SECONDS));
     return true;
 }
 
 static JSBool
 date_getUTCSeconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getUTCSeconds_impl, args);
+    return CallNonGenericMethod<IsDate, date_getUTCSeconds_impl>(cx, args);
 }
 
 /* Date.getMilliseconds is mapped to getUTCMilliseconds */
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getUTCMilliseconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double result = args.thisv().toObject().getDateUTCTime().toNumber();
     if (MOZ_DOUBLE_IS_FINITE(result))
         result = msFromTime(result);
 
     args.rval().setNumber(result);
     return true;
 }
 
 static JSBool
 date_getUTCMilliseconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getUTCMilliseconds_impl, args);
+    return CallNonGenericMethod<IsDate, date_getUTCMilliseconds_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_getTimezoneOffset_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     double utctime = thisObj->getDateUTCTime().toNumber();
 
     double localtime;
@@ -1794,20 +1794,20 @@ date_getTimezoneOffset_impl(JSContext *c
     args.rval().setNumber(result);
     return true;
 }
 
 static JSBool
 date_getTimezoneOffset(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_getTimezoneOffset_impl, args);
+    return CallNonGenericMethod<IsDate, date_getTimezoneOffset_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_setTime_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     if (args.length() == 0) {
         SetDateToNaN(cx, thisObj, args.rval().address());
         return true;
@@ -1819,17 +1819,17 @@ date_setTime_impl(JSContext *cx, CallArg
 
     return SetUTCTime(cx, thisObj, TimeClip(result), args.rval().address());
 }
 
 static JSBool
 date_setTime(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setTime_impl, args);
+    return CallNonGenericMethod<IsDate, date_setTime_impl>(cx, args);
 }
 
 static bool
 GetMsecsOrDefault(JSContext *cx, const CallArgs &args, unsigned i, double t, double *millis)
 {
     if (args.length() <= i) {
         *millis = msFromTime(t);
         return true;
@@ -1853,17 +1853,17 @@ GetMinsOrDefault(JSContext *cx, const Ca
     if (args.length() <= i) {
         *mins = MinFromTime(t);
         return true;
     }
     return ToNumber(cx, args[i], mins);
 }
 
 /* ES5 15.9.5.28. */
-static bool
+JS_ALWAYS_INLINE bool
 date_setMilliseconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
@@ -1880,21 +1880,21 @@ date_setMilliseconds_impl(JSContext *cx,
     /* Steps 4-5. */
     return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 static JSBool
 date_setMilliseconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setMilliseconds_impl, args);
+    return CallNonGenericMethod<IsDate, date_setMilliseconds_impl>(cx, args);
 }
 
 /* ES5 15.9.5.29. */
-static bool
+JS_ALWAYS_INLINE bool
 date_setUTCMilliseconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = thisObj->getDateUTCTime().toNumber();
@@ -1911,21 +1911,21 @@ date_setUTCMilliseconds_impl(JSContext *
     /* Steps 4-5. */
     return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 static JSBool
 date_setUTCMilliseconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setUTCMilliseconds_impl, args);
+    return CallNonGenericMethod<IsDate, date_setUTCMilliseconds_impl>(cx, args);
 }
 
 /* ES5 15.9.5.30. */
-static bool
+JS_ALWAYS_INLINE bool
 date_setSeconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
@@ -1950,20 +1950,20 @@ date_setSeconds_impl(JSContext *cx, Call
     return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 /* ES5 15.9.5.31. */
 static JSBool
 date_setSeconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setSeconds_impl, args);
+    return CallNonGenericMethod<IsDate, date_setSeconds_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_setUTCSeconds_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = thisObj->getDateUTCTime().toNumber();
@@ -1988,20 +1988,20 @@ date_setUTCSeconds_impl(JSContext *cx, C
     return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 /* ES5 15.9.5.32. */
 static JSBool
 date_setUTCSeconds(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setUTCSeconds_impl, args);
+    return CallNonGenericMethod<IsDate, date_setUTCSeconds_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_setMinutes_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
@@ -2031,20 +2031,20 @@ date_setMinutes_impl(JSContext *cx, Call
     return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 /* ES5 15.9.5.33. */
 static JSBool
 date_setMinutes(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setMinutes_impl, args);
+    return CallNonGenericMethod<IsDate, date_setMinutes_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_setUTCMinutes_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = thisObj->getDateUTCTime().toNumber();
@@ -2074,20 +2074,20 @@ date_setUTCMinutes_impl(JSContext *cx, C
     return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 /* ES5 15.9.5.34. */
 static JSBool
 date_setUTCMinutes(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setUTCMinutes_impl, args);
+    return CallNonGenericMethod<IsDate, date_setUTCMinutes_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_setHours_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
@@ -2122,20 +2122,20 @@ date_setHours_impl(JSContext *cx, CallAr
     return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 /* ES5 15.9.5.35. */
 static JSBool
 date_setHours(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setHours_impl, args);
+    return CallNonGenericMethod<IsDate, date_setHours_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_setUTCHours_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = thisObj->getDateUTCTime().toNumber();
@@ -2170,20 +2170,20 @@ date_setUTCHours_impl(JSContext *cx, Cal
     return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 /* ES5 15.9.5.36. */
 static JSBool
 date_setUTCHours(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setUTCHours_impl, args);
+    return CallNonGenericMethod<IsDate, date_setUTCHours_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_setDate_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
@@ -2203,20 +2203,20 @@ date_setDate_impl(JSContext *cx, CallArg
     return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 /* ES5 15.9.5.37. */
 static JSBool
 date_setDate(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setDate_impl, args);
+    return CallNonGenericMethod<IsDate, date_setDate_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_setUTCDate_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = thisObj->getDateUTCTime().toNumber();
@@ -2235,17 +2235,17 @@ date_setUTCDate_impl(JSContext *cx, Call
     /* Steps 5-6. */
     return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 static JSBool
 date_setUTCDate(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setUTCDate_impl, args);
+    return CallNonGenericMethod<IsDate, date_setUTCDate_impl>(cx, args);
 }
 
 static bool
 GetDateOrDefault(JSContext *cx, const CallArgs &args, unsigned i, double t, double *date)
 {
     if (args.length() <= i) {
         *date = DateFromTime(t);
         return true;
@@ -2259,17 +2259,17 @@ GetMonthOrDefault(JSContext *cx, const C
     if (args.length() <= i) {
         *month = MonthFromTime(t);
         return true;
     }
     return ToNumber(cx, args[i], month);
 }
 
 /* ES5 15.9.5.38. */
-static bool
+JS_ALWAYS_INLINE bool
 date_setMonth_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = LocalTime(thisObj->getDateUTCTime().toNumber(), cx);
@@ -2293,21 +2293,21 @@ date_setMonth_impl(JSContext *cx, CallAr
     /* Steps 6-7. */
     return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 static JSBool
 date_setMonth(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setMonth_impl, args);
+    return CallNonGenericMethod<IsDate, date_setMonth_impl>(cx, args);
 }
 
 /* ES5 15.9.5.39. */
-static bool
+JS_ALWAYS_INLINE bool
 date_setUTCMonth_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = thisObj->getDateUTCTime().toNumber();
@@ -2331,17 +2331,17 @@ date_setUTCMonth_impl(JSContext *cx, Cal
     /* Steps 6-7. */
     return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 static JSBool
 date_setUTCMonth(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setUTCMonth_impl, args);
+    return CallNonGenericMethod<IsDate, date_setUTCMonth_impl>(cx, args);
 }
 
 static double
 ThisLocalTimeOrZero(Handle<JSObject*> date, JSContext *cx)
 {
     double t = date->getDateUTCTime().toNumber();
     if (MOZ_DOUBLE_IS_NaN(t))
         return +0;
@@ -2351,17 +2351,17 @@ ThisLocalTimeOrZero(Handle<JSObject*> da
 static double
 ThisUTCTimeOrZero(Handle<JSObject*> date)
 {
     double t = date->getDateUTCTime().toNumber();
     return MOZ_DOUBLE_IS_NaN(t) ? +0 : t;
 }
 
 /* ES5 15.9.5.40. */
-static bool
+JS_ALWAYS_INLINE bool
 date_setFullYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = ThisLocalTimeOrZero(thisObj, cx);
@@ -2390,21 +2390,21 @@ date_setFullYear_impl(JSContext *cx, Cal
     /* Steps 7-8. */
     return SetUTCTime(cx, thisObj, u, args.rval().address());
 }
 
 static JSBool
 date_setFullYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setFullYear_impl, args);
+    return CallNonGenericMethod<IsDate, date_setFullYear_impl>(cx, args);
 }
 
 /* ES5 15.9.5.41. */
-static bool
+JS_ALWAYS_INLINE bool
 date_setUTCFullYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = ThisUTCTimeOrZero(thisObj);
@@ -2433,21 +2433,21 @@ date_setUTCFullYear_impl(JSContext *cx, 
     /* Steps 7-8. */
     return SetUTCTime(cx, thisObj, v, args.rval().address());
 }
 
 static JSBool
 date_setUTCFullYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setUTCFullYear_impl, args);
+    return CallNonGenericMethod<IsDate, date_setUTCFullYear_impl>(cx, args);
 }
 
 /* ES5 Annex B.2.5. */
-static bool
+JS_ALWAYS_INLINE bool
 date_setYear_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     /* Step 1. */
     double t = ThisLocalTimeOrZero(thisObj, cx);
@@ -2477,17 +2477,17 @@ date_setYear_impl(JSContext *cx, CallArg
     /* Steps 7-8. */
     return SetUTCTime(cx, thisObj, TimeClip(u), args.rval().address());
 }
 
 static JSBool
 date_setYear(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_setYear_impl, args);
+    return CallNonGenericMethod<IsDate, date_setYear_impl>(cx, args);
 }
 
 /* constants for toString, toUTCString */
 static char js_NaN_date_str[] = "Invalid Date";
 static const char* days[] =
 {
    "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
 };
@@ -2523,17 +2523,17 @@ print_iso_string(char* buf, size_t size,
                 int(DateFromTime(utctime)),
                 int(HourFromTime(utctime)),
                 int(MinFromTime(utctime)),
                 int(SecFromTime(utctime)),
                 int(msFromTime(utctime)));
 }
 
 /* ES5 B.2.6. */
-static bool
+JS_ALWAYS_INLINE bool
 date_toGMTString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double utctime = args.thisv().toObject().getDateUTCTime().toNumber();
 
     char buf[100];
     if (!MOZ_DOUBLE_IS_FINITE(utctime))
@@ -2548,20 +2548,20 @@ date_toGMTString_impl(JSContext *cx, Cal
     return true;
 }
 
 /* ES5 15.9.5.43. */
 static JSBool
 date_toGMTString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toGMTString_impl, args);
+    return CallNonGenericMethod<IsDate, date_toGMTString_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_toISOString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     double utctime = args.thisv().toObject().getDateUTCTime().toNumber();
     if (!MOZ_DOUBLE_IS_FINITE(utctime)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INVALID_DATE);
         return false;
@@ -2577,17 +2577,17 @@ date_toISOString_impl(JSContext *cx, Cal
     return true;
 
 }
 
 static JSBool
 date_toISOString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toISOString_impl, args);
+    return CallNonGenericMethod<IsDate, date_toISOString_impl>(cx, args);
 }
 
 /* ES5 15.9.5.44. */
 static JSBool
 date_toJSON(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
@@ -2833,34 +2833,34 @@ ToLocaleStringHelper(JSContext *cx, Call
                           "%#c"
 #else
                           "%c"
 #endif
                          );
 }
 
 /* ES5 15.9.5.5. */
-static bool
+JS_ALWAYS_INLINE bool
 date_toLocaleString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     return ToLocaleStringHelper(cx, args, thisObj);
 }
 
 static JSBool
 date_toLocaleString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toLocaleString_impl, args);
+    return CallNonGenericMethod<IsDate, date_toLocaleString_impl>(cx, args);
 }
 
 /* ES5 15.9.5.6. */
-static bool
+JS_ALWAYS_INLINE bool
 date_toLocaleDateString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     /*
      * Use '%#x' for windows, because '%x' is backward-compatible and non-y2k
      * with msvc; '%#x' requests that a full year be used in the result string.
      */
@@ -2875,37 +2875,37 @@ date_toLocaleDateString_impl(JSContext *
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     return ToLocaleHelper(cx, args, thisObj, format);
 }
 
 static JSBool
 date_toLocaleDateString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toLocaleDateString_impl, args);
+    return CallNonGenericMethod<IsDate, date_toLocaleDateString_impl>(cx, args);
 }
 
 /* ES5 15.9.5.7. */
-static bool
+JS_ALWAYS_INLINE bool
 date_toLocaleTimeString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
     return ToLocaleHelper(cx, args, thisObj, "%X");
 }
 
 static JSBool
 date_toLocaleTimeString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toLocaleTimeString_impl, args);
+    return CallNonGenericMethod<IsDate, date_toLocaleTimeString_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_toLocaleFormat_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     if (args.length() == 0)
         return ToLocaleStringHelper(cx, args, thisObj);
@@ -2921,55 +2921,55 @@ date_toLocaleFormat_impl(JSContext *cx, 
 
     return ToLocaleHelper(cx, args, thisObj, fmtbytes.ptr());
 }
 
 static JSBool
 date_toLocaleFormat(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toLocaleFormat_impl, args);
+    return CallNonGenericMethod<IsDate, date_toLocaleFormat_impl>(cx, args);
 }
 
 /* ES5 15.9.5.4. */
-static bool
+JS_ALWAYS_INLINE bool
 date_toTimeString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     return date_format(cx, args.thisv().toObject().getDateUTCTime().toNumber(),
                        FORMATSPEC_TIME, args);
 }
 
 static JSBool
 date_toTimeString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toTimeString_impl, args);
+    return CallNonGenericMethod<IsDate, date_toTimeString_impl>(cx, args);
 }
 
 /* ES5 15.9.5.3. */
-static bool
+JS_ALWAYS_INLINE bool
 date_toDateString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     return date_format(cx, args.thisv().toObject().getDateUTCTime().toNumber(),
                        FORMATSPEC_DATE, args);
 }
 
 static JSBool
 date_toDateString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toDateString_impl, args);
+    return CallNonGenericMethod<IsDate, date_toDateString_impl>(cx, args);
 }
 
 #if JS_HAS_TOSOURCE
-static bool
+JS_ALWAYS_INLINE bool
 date_toSource_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     StringBuffer sb(cx);
     if (!sb.append("(new Date(") ||
         !NumberValueToStringBuffer(cx, args.thisv().toObject().getDateUTCTime(), sb) ||
         !sb.append("))"))
@@ -2983,51 +2983,51 @@ date_toSource_impl(JSContext *cx, CallAr
     args.rval().setString(str);
     return true;
 }
 
 static JSBool
 date_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toSource_impl, args);
+    return CallNonGenericMethod<IsDate, date_toSource_impl>(cx, args);
 }
 #endif
 
-static bool
+JS_ALWAYS_INLINE bool
 date_toString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
     return date_format(cx, args.thisv().toObject().getDateUTCTime().toNumber(),
                        FORMATSPEC_FULL, args);
 }
 
 static JSBool
 date_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_toString_impl, args);
+    return CallNonGenericMethod<IsDate, date_toString_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 date_valueOf_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsDate(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     args.rval().set(thisObj->getDateUTCTime());
     return true;
 }
 
 static JSBool
 date_valueOf(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsDate, date_valueOf_impl, args);
+    return CallNonGenericMethod<IsDate, date_valueOf_impl>(cx, args);
 }
 
 static JSFunctionSpec date_static_methods[] = {
     JS_FN("UTC",                 date_UTC,                MAXARGS,0),
     JS_FN("parse",               date_parse,              1,0),
     JS_FN("now",                 date_now,                0,0),
     JS_FS_END
 };
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -746,23 +746,23 @@ Iterator(JSContext *cx, unsigned argc, V
     unsigned flags = JSITER_OWNONLY | (keyonly ? 0 : (JSITER_FOREACH | JSITER_KEYVALUE));
 
     if (!ValueToIterator(cx, flags, MutableHandleValue::fromMarkedLocation(&args[0])))
         return false;
     args.rval().set(args[0]);
     return true;
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 IsIterator(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&PropertyIteratorObject::class_);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 iterator_next_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsIterator(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     if (!js_IteratorMore(cx, thisObj, args.rval()))
         return false;
@@ -778,21 +778,21 @@ iterator_next_impl(JSContext *cx, CallAr
 static JSBool
 iterator_iterator(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().set(args.thisv());
     return true;
 }
 
-static JSBool
+JSBool
 iterator_next(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsIterator, iterator_next_impl, args);
+    return CallNonGenericMethod<IsIterator, iterator_next_impl>(cx, args);
 }
 
 static JSFunctionSpec iterator_methods[] = {
     JS_FN("iterator",  iterator_iterator,   0, 0),
     JS_FN("next",      iterator_next,       0, 0),
     JS_FS_END
 };
 
@@ -1584,23 +1584,23 @@ CloseGenerator(JSContext *cx, JSObject *
     }
 
     if (gen->state == JSGEN_CLOSED)
         return JS_TRUE;
 
     return SendToGenerator(cx, JSGENOP_CLOSE, obj, gen, UndefinedValue());
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 IsGenerator(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&GeneratorClass);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 generator_send_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsGenerator(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     JSGenerator *gen = (JSGenerator *) thisObj->getPrivate();
     if (!gen || gen->state == JSGEN_CLOSED) {
@@ -1620,24 +1620,24 @@ generator_send_impl(JSContext *cx, CallA
     {
         return false;
     }
 
     args.rval().set(gen->fp->returnValue());
     return true;
 }
 
-static JSBool
+JSBool
 generator_send(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsGenerator, generator_send_impl, args);
+    return CallNonGenericMethod<IsGenerator, generator_send_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 generator_next_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsGenerator(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     JSGenerator *gen = (JSGenerator *) thisObj->getPrivate();
     if (!gen || gen->state == JSGEN_CLOSED) {
@@ -1647,24 +1647,24 @@ generator_next_impl(JSContext *cx, CallA
 
     if (!SendToGenerator(cx, JSGENOP_NEXT, thisObj, gen, UndefinedValue()))
         return false;
 
     args.rval().set(gen->fp->returnValue());
     return true;
 }
 
-static JSBool
+JSBool
 generator_next(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsGenerator, generator_next_impl, args);
+    return CallNonGenericMethod<IsGenerator, generator_next_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 generator_throw_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsGenerator(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     JSGenerator *gen = (JSGenerator *) thisObj->getPrivate();
     if (!gen || gen->state == JSGEN_CLOSED) {
@@ -1678,24 +1678,24 @@ generator_throw_impl(JSContext *cx, Call
     {
         return false;
     }
 
     args.rval().set(gen->fp->returnValue());
     return true;
 }
 
-static JSBool
+JSBool
 generator_throw(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsGenerator, generator_throw_impl, args);
+    return CallNonGenericMethod<IsGenerator, generator_throw_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 generator_close_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsGenerator(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
 
     JSGenerator *gen = (JSGenerator *) thisObj->getPrivate();
     if (!gen || gen->state == JSGEN_CLOSED) {
@@ -1712,21 +1712,21 @@ generator_close_impl(JSContext *cx, Call
 
     if (!SendToGenerator(cx, JSGENOP_CLOSE, thisObj, gen, UndefinedValue()))
         return false;
 
     args.rval().set(gen->fp->returnValue());
     return true;
 }
 
-static JSBool
+JSBool
 generator_close(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsGenerator, generator_close_impl, args);
+    return CallNonGenericMethod<IsGenerator, generator_close_impl>(cx, args);
 }
 
 #define JSPROP_ROPERM   (JSPROP_READONLY | JSPROP_PERMANENT)
 
 static JSFunctionSpec generator_methods[] = {
     JS_FN("iterator",  iterator_iterator,  0, 0),
     JS_FN("next",      generator_next,     0,JSPROP_ROPERM),
     JS_FN("send",      generator_send,     1,JSPROP_ROPERM),
--- a/js/src/jsnum.cpp
+++ b/js/src/jsnum.cpp
@@ -458,32 +458,32 @@ Number(JSContext *cx, unsigned argc, Val
 
     JSObject *obj = NumberObject::create(cx, vp[0].toNumber());
     if (!obj)
         return false;
     vp->setObject(*obj);
     return true;
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 IsNumber(const Value &v)
 {
     return v.isNumber() || (v.isObject() && v.toObject().hasClass(&NumberClass));
 }
 
 inline double
 Extract(const Value &v)
 {
     if (v.isNumber())
         return v.toNumber();
     return v.toObject().asNumber().unbox();
 }
 
 #if JS_HAS_TOSOURCE
-static bool
+JS_ALWAYS_INLINE bool
 num_toSource_impl(JSContext *cx, CallArgs args)
 {
     double d = Extract(args.thisv());
 
     StringBuffer sb(cx);
     if (!sb.append("(new Number(") ||
         !NumberValueToStringBuffer(cx, NumberValue(d), sb) ||
         !sb.append("))"))
@@ -497,17 +497,17 @@ num_toSource_impl(JSContext *cx, CallArg
     args.rval().setString(str);
     return true;
 }
 
 static JSBool
 num_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsNumber, num_toSource_impl, args);
+    return CallNonGenericMethod<IsNumber, num_toSource_impl>(cx, args);
 }
 #endif
 
 ToCStringBuf::ToCStringBuf() :dbuf(NULL)
 {
     JS_STATIC_ASSERT(sbufSize >= DTOSTR_STANDARD_BUFFER_SIZE);
 }
 
@@ -588,17 +588,17 @@ IntToCString(ToCStringBuf *cbuf, int i, 
         *--cp = '-';
 
     return cp.get();
 }
 
 static JSString * JS_FASTCALL
 js_NumberToStringWithBase(JSContext *cx, double d, int base);
 
-static bool
+JS_ALWAYS_INLINE bool
 num_toString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsNumber(args.thisv()));
 
     double d = Extract(args.thisv());
 
     int32_t base = 10;
     if (args.hasDefined(0)) {
@@ -621,20 +621,20 @@ num_toString_impl(JSContext *cx, CallArg
     args.rval().setString(str);
     return true;
 }
 
 static JSBool
 num_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsNumber, num_toString_impl, args);
+    return CallNonGenericMethod<IsNumber, num_toString_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 num_toLocaleString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsNumber(args.thisv()));
 
     double d = Extract(args.thisv());
 
     Rooted<JSString*> str(cx, js_NumberToStringWithBase(cx, d, 10));
     if (!str) {
@@ -750,39 +750,38 @@ num_toLocaleString_impl(JSContext *cx, C
     cx->free_(buf);
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
-static JSBool
+JSBool
 num_toLocaleString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsNumber, num_toLocaleString_impl, args);
+    return CallNonGenericMethod<IsNumber, num_toLocaleString_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 num_valueOf_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsNumber(args.thisv()));
     args.rval().setNumber(Extract(args.thisv()));
     return true;
 }
 
 JSBool
 js_num_valueOf(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsNumber, num_valueOf_impl, args);
+    return CallNonGenericMethod<IsNumber, num_valueOf_impl>(cx, args);
 }
 
-
 const unsigned MAX_PRECISION = 100;
 
 static bool
 ComputePrecisionInRange(JSContext *cx, int minPrecision, int maxPrecision, const Value &v,
                         int *precision)
 {
     double prec;
     if (!ToInteger(cx, v, &prec))
@@ -813,40 +812,40 @@ DToStrResult(JSContext *cx, double d, JS
     args.rval().setString(str);
     return true;
 }
 
 /*
  * In the following three implementations, we allow a larger range of precision
  * than ECMA requires; this is permitted by ECMA-262.
  */
-static bool
+JS_ALWAYS_INLINE bool
 num_toFixed_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsNumber(args.thisv()));
 
     int precision;
     if (args.length() == 0) {
         precision = 0;
     } else {
         if (!ComputePrecisionInRange(cx, -20, MAX_PRECISION, args[0], &precision))
             return false;
     }
 
     return DToStrResult(cx, Extract(args.thisv()), DTOSTR_FIXED, precision, args);
 }
 
-static JSBool
+JSBool
 num_toFixed(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsNumber, num_toFixed_impl, args);
+    return CallNonGenericMethod<IsNumber, num_toFixed_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 num_toExponential_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsNumber(args.thisv()));
 
     JSDToStrMode mode;
     int precision;
     if (args.length() == 0) {
         mode = DTOSTR_STANDARD_EXPONENTIAL;
@@ -855,24 +854,24 @@ num_toExponential_impl(JSContext *cx, Ca
         mode = DTOSTR_EXPONENTIAL;
         if (!ComputePrecisionInRange(cx, 0, MAX_PRECISION, args[0], &precision))
             return false;
     }
 
     return DToStrResult(cx, Extract(args.thisv()), mode, precision + 1, args);
 }
 
-static JSBool
+JSBool
 num_toExponential(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsNumber, num_toExponential_impl, args);
+    return CallNonGenericMethod<IsNumber, num_toExponential_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 num_toPrecision_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsNumber(args.thisv()));
 
     double d = Extract(args.thisv());
 
     if (!args.hasDefined(0)) {
         JSString *str = js_NumberToStringWithBase(cx, d, 10);
@@ -893,21 +892,21 @@ num_toPrecision_impl(JSContext *cx, Call
         mode = DTOSTR_PRECISION;
         if (!ComputePrecisionInRange(cx, 1, MAX_PRECISION, args[0], &precision))
             return false;
     }
 
     return DToStrResult(cx, d, mode, precision, args);
 }
 
-static JSBool
+JSBool
 num_toPrecision(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsNumber, num_toPrecision_impl, args);
+    return CallNonGenericMethod<IsNumber, num_toPrecision_impl>(cx, args);
 }
 
 static JSFunctionSpec number_methods[] = {
 #if JS_HAS_TOSOURCE
     JS_FN(js_toSource_str,       num_toSource,          0, 0),
 #endif
     JS_FN(js_toString_str,       num_toString,          1, 0),
     JS_FN(js_toLocaleString_str, num_toLocaleString,    0, 0),
--- a/js/src/jsstr.cpp
+++ b/js/src/jsstr.cpp
@@ -453,17 +453,17 @@ ThisToStringForStringProto(JSContext *cx
     JSString *str = ToStringSlow(cx, call.thisv());
     if (!str)
         return NULL;
 
     call.setThis(StringValue(str));
     return str;
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 IsString(const Value &v)
 {
     return v.isString() || (v.isObject() && v.toObject().hasClass(&StringClass));
 }
 
 #if JS_HAS_TOSOURCE
 
 /*
@@ -479,17 +479,17 @@ str_quote(JSContext *cx, unsigned argc, 
         return false;
     str = js_QuoteString(cx, str, '"');
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 str_toSource_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsString(args.thisv()));
 
     Rooted<JSString*> str(cx, ToString(cx, args.thisv()));
     if (!str)
         return false;
 
@@ -503,41 +503,41 @@ str_toSource_impl(JSContext *cx, CallArg
 
     str = sb.finishString();
     if (!str)
         return false;
     args.rval().setString(str);
     return true;
 }
 
-static JSBool
+JSBool
 str_toSource(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsString, str_toSource_impl, args);
+    return CallNonGenericMethod<IsString, str_toSource_impl>(cx, args);
 }
 
 #endif /* JS_HAS_TOSOURCE */
 
-static bool
+JS_ALWAYS_INLINE bool
 str_toString_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsString(args.thisv()));
 
     args.rval().setString(args.thisv().isString()
                               ? args.thisv().toString()
                               : args.thisv().toObject().asString().unbox());
     return true;
 }
 
 JSBool
 js_str_toString(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsString, str_toString_impl, args);
+    return CallNonGenericMethod<IsString, str_toString_impl>(cx, args);
 }
 
 /*
  * Java-like string native methods.
  */
 
 JS_ALWAYS_INLINE bool
 ValueToIntegerRange(JSContext *cx, const Value &v, int32_t *out)
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -111,35 +111,35 @@ ToClampedIndex(JSContext *cx, const Valu
 static ArrayBufferObject *
 getArrayBuffer(JSObject *obj)
 {
     while (obj && !obj->isArrayBuffer())
         obj = obj->getProto();
     return obj ? &obj->asArrayBuffer() : NULL;
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 IsArrayBuffer(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&ArrayBufferClass);
 }
 
-bool
+JS_ALWAYS_INLINE bool
 ArrayBufferObject::byteLengthGetterImpl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsArrayBuffer(args.thisv()));
     args.rval().setInt32(args.thisv().toObject().asArrayBuffer().byteLength());
     return true;
 }
 
 JSBool
 ArrayBufferObject::byteLengthGetter(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsArrayBuffer, byteLengthGetterImpl, args);
+    return CallNonGenericMethod<IsArrayBuffer, byteLengthGetterImpl>(cx, args);
 }
 
 bool
 ArrayBufferObject::fun_slice_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsArrayBuffer(args.thisv()));
 
     Rooted<JSObject*> thisObj(cx, &args.thisv().toObject());
@@ -167,17 +167,17 @@ ArrayBufferObject::fun_slice_impl(JSCont
     args.rval().setObject(*nobj);
     return true;
 }
 
 JSBool
 ArrayBufferObject::fun_slice(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsArrayBuffer, fun_slice_impl, args);
+    return CallNonGenericMethod<IsArrayBuffer, fun_slice_impl>(cx, args);
 }
 
 /*
  * new ArrayBuffer(byteLength)
  */
 JSBool
 ArrayBufferObject::class_constructor(JSContext *cx, unsigned argc, Value *vp)
 {
@@ -310,17 +310,17 @@ ArrayBufferObject::createDataViewForThis
     CallArgs frobbedArgs = CallArgsFromVp(args.length() - 1, args.base());
     return DataViewObject::construct(cx, buffer, frobbedArgs, proto);
 }
 
 JSBool
 ArrayBufferObject::createDataViewForThis(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsArrayBuffer, createDataViewForThisImpl, args);
+    return CallNonGenericMethod<IsArrayBuffer, createDataViewForThisImpl>(cx, args);
 }
 
 void
 ArrayBufferObject::obj_trace(JSTracer *trc, JSObject *obj)
 {
     /*
      * If this object changes, it will get marked via the private data barrier,
      * so it's safe to leave it Unbarriered.
@@ -1418,17 +1418,18 @@ class TypedArrayTemplate
     // ValueGetter is a function that takes an unwrapped typed array object and
     // returns a Value. Given such a function, Getter<> is a native that
     // retrieves a given Value, probably from a slot on the object.
     template<Value ValueGetter(JSObject *obj)>
     static JSBool
     Getter(JSContext *cx, unsigned argc, Value *vp)
     {
         CallArgs args = CallArgsFromVp(argc, vp);
-        return CallNonGenericMethod(cx, IsThisClass, GetterImpl<ValueGetter>, args);
+        return CallNonGenericMethod<ThisTypeArray::IsThisClass,
+                                    ThisTypeArray::GetterImpl<ValueGetter> >(cx, args);
     }
 
     // Define an accessor for a read-only property that invokes a native getter
     template<Value ValueGetter(JSObject *obj)>
     static bool
     DefineGetter(JSContext *cx, PropertyName *name, HandleObject proto)
     {
         RootedId id(cx, NameToId(name));
@@ -1493,17 +1494,17 @@ class TypedArrayTemplate
         args.rval().setObject(*nobj);
         return true;
     }
 
     static JSBool
     fun_subarray(JSContext *cx, unsigned argc, Value *vp)
     {
         CallArgs args = CallArgsFromVp(argc, vp);
-        return CallNonGenericMethod(cx, IsThisClass, fun_subarray_impl, args);
+        return CallNonGenericMethod<ThisTypeArray::IsThisClass, ThisTypeArray::fun_subarray_impl>(cx, args);
     }
 
     /* move(begin, end, dest) */
     static bool
     fun_move_impl(JSContext *cx, CallArgs args)
     {
         JS_ASSERT(IsThisClass(args.thisv()));
         RootedObject tarray(cx, &args.thisv().toObject());
@@ -1556,17 +1557,17 @@ class TypedArrayTemplate
         args.rval().setUndefined();
         return true;
     }
 
     static JSBool
     fun_move(JSContext *cx, unsigned argc, Value *vp)
     {
         CallArgs args = CallArgsFromVp(argc, vp);
-        return CallNonGenericMethod(cx, IsThisClass, fun_move_impl, args);
+        return CallNonGenericMethod<ThisTypeArray::IsThisClass, ThisTypeArray::fun_move_impl>(cx, args);
     }
 
     /* set(array[, offset]) */
     static bool
     fun_set_impl(JSContext *cx, CallArgs args)
     {
         JS_ASSERT(IsThisClass(args.thisv()));
         RootedObject tarray(cx, &args.thisv().toObject());
@@ -1621,17 +1622,17 @@ class TypedArrayTemplate
         args.rval().setUndefined();
         return true;
     }
 
     static JSBool
     fun_set(JSContext *cx, unsigned argc, Value *vp)
     {
         CallArgs args = CallArgsFromVp(argc, vp);
-        return CallNonGenericMethod(cx, IsThisClass, fun_set_impl, args);
+        return CallNonGenericMethod<ThisTypeArray::IsThisClass, ThisTypeArray::fun_set_impl>(cx, args);
     }
 
   public:
     static JSObject *
     fromBuffer(JSContext *cx, HandleObject bufobj, int32_t byteOffsetInt, int32_t lengthInt,
                HandleObject proto)
     {
         if (!ObjectClassIs(*bufobj, ESClass_ArrayBuffer, cx)) {
@@ -2109,17 +2110,17 @@ ArrayBufferObject::createTypedArrayFromB
 }
 
 template<typename T>
 JSBool
 ArrayBufferObject::createTypedArrayFromBuffer(JSContext *cx, unsigned argc, Value *vp)
 {
     typedef TypedArrayTemplate<T> ArrayType;
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsArrayBuffer, createTypedArrayFromBufferImpl<T>, args);
+    return CallNonGenericMethod<IsArrayBuffer, createTypedArrayFromBufferImpl<T> >(cx, args);
 }
 
 // this default implementation is only valid for integer types
 // less than 32-bits in size.
 template<typename NativeType>
 void
 TypedArrayTemplate<NativeType>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32_t index,
                                                  MutableHandleValue vp)
@@ -2455,17 +2456,17 @@ DataViewObject::getInt8Impl(JSContext *c
     args.rval().setInt32(val);
     return true;
 }
 
 JSBool
 DataViewObject::fun_getInt8(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getInt8Impl, args);
+    return CallNonGenericMethod<is, getInt8Impl>(cx, args);
 }
 
 bool
 DataViewObject::getUint8Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2476,17 +2477,17 @@ DataViewObject::getUint8Impl(JSContext *
     args.rval().setInt32(val);
     return true;
 }
 
 JSBool
 DataViewObject::fun_getUint8(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getUint8Impl, args);
+    return CallNonGenericMethod<is, getUint8Impl>(cx, args);
 }
 
 bool
 DataViewObject::getInt16Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2497,17 +2498,17 @@ DataViewObject::getInt16Impl(JSContext *
     args.rval().setInt32(val);
     return true;
 }
 
 JSBool
 DataViewObject::fun_getInt16(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getInt16Impl, args);
+    return CallNonGenericMethod<is, getInt16Impl>(cx, args);
 }
 
 bool
 DataViewObject::getUint16Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2518,17 +2519,17 @@ DataViewObject::getUint16Impl(JSContext 
     args.rval().setInt32(val);
     return true;
 }
 
 JSBool
 DataViewObject::fun_getUint16(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getUint16Impl, args);
+    return CallNonGenericMethod<is, getUint16Impl>(cx, args);
 }
 
 bool
 DataViewObject::getInt32Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2539,17 +2540,17 @@ DataViewObject::getInt32Impl(JSContext *
     args.rval().setInt32(val);
     return true;
 }
 
 JSBool
 DataViewObject::fun_getInt32(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getInt32Impl, args);
+    return CallNonGenericMethod<is, getInt32Impl>(cx, args);
 }
 
 bool
 DataViewObject::getUint32Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2560,17 +2561,17 @@ DataViewObject::getUint32Impl(JSContext 
     args.rval().setNumber(val);
     return true;
 }
 
 JSBool
 DataViewObject::fun_getUint32(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getUint32Impl, args);
+    return CallNonGenericMethod<is, getUint32Impl>(cx, args);
 }
 
 bool
 DataViewObject::getFloat32Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2582,17 +2583,17 @@ DataViewObject::getFloat32Impl(JSContext
     args.rval().setDouble(JS_CANONICALIZE_NAN(val));
     return true;
 }
 
 JSBool
 DataViewObject::fun_getFloat32(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getFloat32Impl, args);
+    return CallNonGenericMethod<is, getFloat32Impl>(cx, args);
 }
 
 bool
 DataViewObject::getFloat64Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2604,17 +2605,17 @@ DataViewObject::getFloat64Impl(JSContext
     args.rval().setDouble(JS_CANONICALIZE_NAN(val));
     return true;
 }
 
 JSBool
 DataViewObject::fun_getFloat64(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getFloat64Impl, args);
+    return CallNonGenericMethod<is, getFloat64Impl>(cx, args);
 }
 
 bool
 DataViewObject::setInt8Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2624,17 +2625,17 @@ DataViewObject::setInt8Impl(JSContext *c
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 DataViewObject::fun_setInt8(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, setInt8Impl, args);
+    return CallNonGenericMethod<is, setInt8Impl>(cx, args);
 }
 
 bool
 DataViewObject::setUint8Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2644,17 +2645,17 @@ DataViewObject::setUint8Impl(JSContext *
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 DataViewObject::fun_setUint8(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, setUint8Impl, args);
+    return CallNonGenericMethod<is, setUint8Impl>(cx, args);
 }
 
 bool
 DataViewObject::setInt16Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2664,17 +2665,17 @@ DataViewObject::setInt16Impl(JSContext *
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 DataViewObject::fun_setInt16(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, setInt16Impl, args);
+    return CallNonGenericMethod<is, setInt16Impl>(cx, args);
 }
 
 bool
 DataViewObject::setUint16Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2684,17 +2685,17 @@ DataViewObject::setUint16Impl(JSContext 
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 DataViewObject::fun_setUint16(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, setUint16Impl, args);
+    return CallNonGenericMethod<is, setUint16Impl>(cx, args);
 }
 
 bool
 DataViewObject::setInt32Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2704,17 +2705,17 @@ DataViewObject::setInt32Impl(JSContext *
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 DataViewObject::fun_setInt32(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, setInt32Impl, args);
+    return CallNonGenericMethod<is, setInt32Impl>(cx, args);
 }
 
 bool
 DataViewObject::setUint32Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2724,17 +2725,17 @@ DataViewObject::setUint32Impl(JSContext 
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 DataViewObject::fun_setUint32(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, setUint32Impl, args);
+    return CallNonGenericMethod<is, setUint32Impl>(cx, args);
 }
 
 bool
 DataViewObject::setFloat32Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2744,17 +2745,17 @@ DataViewObject::setFloat32Impl(JSContext
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 DataViewObject::fun_setFloat32(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, setFloat32Impl, args);
+    return CallNonGenericMethod<is, setFloat32Impl>(cx, args);
 }
 
 bool
 DataViewObject::setFloat64Impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(is(args.thisv()));
 
     Rooted<DataViewObject*> thisView(cx, &args.thisv().toObject().asDataView());
@@ -2764,17 +2765,17 @@ DataViewObject::setFloat64Impl(JSContext
     args.rval().setUndefined();
     return true;
 }
 
 JSBool
 DataViewObject::fun_setFloat64(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, setFloat64Impl, args);
+    return CallNonGenericMethod<is, setFloat64Impl>(cx, args);
 }
 
 /***
  *** JS impl
  ***/
 
 /*
  * ArrayBufferObject (base)
@@ -3212,17 +3213,17 @@ DataViewObject::getterImpl(JSContext *cx
     return true;
 }
 
 template<Value ValueGetter(DataViewObject &view)>
 JSBool
 DataViewObject::getter(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, is, getterImpl<ValueGetter>, args);
+    return CallNonGenericMethod<is, getterImpl<ValueGetter> >(cx, args);
 }
 
 template<Value ValueGetter(DataViewObject &view)>
 bool
 DataViewObject::defineGetter(JSContext *cx, PropertyName *name, HandleObject proto)
 {
     RootedId id(cx, NameToId(name));
     unsigned flags = JSPROP_SHARED | JSPROP_GETTER | JSPROP_PERMANENT;
--- a/js/src/jsweakmap.cpp
+++ b/js/src/jsweakmap.cpp
@@ -113,23 +113,23 @@ GetKeyArg(JSContext *cx, CallArgs &args)
     // If the key is from another compartment, and we store the wrapper as the key
     // the wrapper might be GC-ed since it is not strong referenced (Bug 673468).
     // To avoid this we always use the unwrapped object as the key instead of its
     // security wrapper. This also means that if the keys are ever exposed they must
     // be re-wrapped (see: JS_NondeterministicGetWeakMapKeys).
     return JS_UnwrapObject(&key);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 IsWeakMap(const Value &v)
 {
     return v.isObject() && v.toObject().hasClass(&WeakMapClass);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 WeakMap_has_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsWeakMap(args.thisv()));
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                              "WeakMap.has", "0", "s");
         return false;
@@ -144,24 +144,24 @@ WeakMap_has_impl(JSContext *cx, CallArgs
             return true;
         }
     }
 
     args.rval().setBoolean(false);
     return true;
 }
 
-static JSBool
+JSBool
 WeakMap_has(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsWeakMap, WeakMap_has_impl, args);
+    return CallNonGenericMethod<IsWeakMap, WeakMap_has_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 WeakMap_get_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsWeakMap(args.thisv()));
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                              "WeakMap.get", "0", "s");
         return false;
@@ -176,24 +176,24 @@ WeakMap_get_impl(JSContext *cx, CallArgs
             return true;
         }
     }
 
     args.rval().set((args.length() > 1) ? args[1] : UndefinedValue());
     return true;
 }
 
-static JSBool
+JSBool
 WeakMap_get(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsWeakMap, WeakMap_get_impl, args);
+    return CallNonGenericMethod<IsWeakMap, WeakMap_get_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 WeakMap_delete_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsWeakMap(args.thisv()));
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                              "WeakMap.delete", "0", "s");
         return false;
@@ -209,24 +209,24 @@ WeakMap_delete_impl(JSContext *cx, CallA
             return true;
         }
     }
 
     args.rval().setBoolean(false);
     return true;
 }
 
-static JSBool
+JSBool
 WeakMap_delete(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsWeakMap, WeakMap_delete_impl, args);
+    return CallNonGenericMethod<IsWeakMap, WeakMap_delete_impl>(cx, args);
 }
 
-static bool
+JS_ALWAYS_INLINE bool
 WeakMap_set_impl(JSContext *cx, CallArgs args)
 {
     JS_ASSERT(IsWeakMap(args.thisv()));
 
     if (args.length() < 1) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_MORE_ARGS_NEEDED,
                              "WeakMap.set", "0", "s");
         return false;
@@ -261,21 +261,21 @@ WeakMap_set_impl(JSContext *cx, CallArgs
             JS_ReportWarning(cx, "Failed to preserve wrapper of wrapped native weak map key.");
         }
     }
 
     args.rval().setUndefined();
     return true;
 }
 
-static JSBool
+JSBool
 WeakMap_set(JSContext *cx, unsigned argc, Value *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return CallNonGenericMethod(cx, IsWeakMap, WeakMap_set_impl, args);
+    return CallNonGenericMethod<IsWeakMap, WeakMap_set_impl>(cx, args);
 }
 
 JS_FRIEND_API(JSBool)
 JS_NondeterministicGetWeakMapKeys(JSContext *cx, JSObject *obj, JSObject **ret)
 {
     if (!obj || !obj->isWeakMap()) {
         *ret = NULL;
         return true;
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -2119,19 +2119,38 @@ nsCSSRendering::PaintGradient(nsPresCont
       gfxRect tileRect = nsLayoutUtils::RectToGfxRect(
                       nsRect(x, y, aOneCellArea.width, aOneCellArea.height),
                       appUnitsPerPixel);
       // The actual area to fill with this tile is the intersection of this
       // tile with the overall area we're supposed to be filling
       gfxRect fillRect =
         forceRepeatToCoverTiles ? areaToFill : tileRect.Intersect(areaToFill);
       ctx->NewPath();
-      ctx->Translate(tileRect.TopLeft());
+      // If we can snap the gradient tile and fill rects, do so, but make sure
+      // that the gradient is scaled precisely to the tile rect.
+      gfxRect fillRectSnapped = fillRect;
+      // Don't snap the tileRect directly since that would lose information
+      // about the orientation of the current transform (i.e. vertical or
+      // horizontal flipping). Instead snap the corners independently so if
+      // the CTM has a flip, our Scale() below preserves the flip.
+      gfxPoint tileRectSnappedTopLeft = tileRect.TopLeft();
+      gfxPoint tileRectSnappedBottomRight = tileRect.BottomRight();
+      if (ctx->UserToDevicePixelSnapped(fillRectSnapped, true) &&
+          ctx->UserToDevicePixelSnapped(tileRectSnappedTopLeft, true) &&
+          ctx->UserToDevicePixelSnapped(tileRectSnappedBottomRight, true)) {
+        ctx->IdentityMatrix();
+        ctx->Rectangle(fillRectSnapped);
+        ctx->Translate(tileRectSnappedTopLeft);
+        ctx->Scale((tileRectSnappedBottomRight.x - tileRectSnappedTopLeft.x)/tileRect.width,
+                   (tileRectSnappedBottomRight.y - tileRectSnappedTopLeft.y)/tileRect.height);
+      } else {
+        ctx->Rectangle(fillRect);
+        ctx->Translate(tileRect.TopLeft());
+      }
       ctx->SetPattern(gradientPattern);
-      ctx->Rectangle(fillRect - tileRect.TopLeft(), true);
       ctx->Fill();
       ctx->SetMatrix(ctm);
     }
   }
 }
 
 void
 nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext,
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-flipped-1-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE HTML>
+<div style="height:100px; background:-moz-linear-gradient(bottom, black, white);"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-flipped-1.html
@@ -0,0 +1,2 @@
+<!DOCTYPE HTML>
+<div style="height:100px; background:-moz-linear-gradient(top, black, white); transform:scale(1,-1);"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-vertical-subpixel-1-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+  margin-top: 21px;
+  height: 30px;
+  background-image: -moz-linear-gradient(center top, black, white);
+}
+</style>
+</head>
+<body>
+<div></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/css-gradients/linear-vertical-subpixel-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+div {
+  margin-top: 20.7px;
+  height: 30px;
+  background-image: -moz-linear-gradient(center top, black, white);
+}
+</style>
+</head>
+<body>
+<div></div>
+</body>
+</html>
--- a/layout/reftests/css-gradients/reftest.list
+++ b/layout/reftests/css-gradients/reftest.list
@@ -16,16 +16,17 @@ fuzzy-if(!contentSameGfxBackendAsCanvas,
 == linear-diagonal-4a.html linear-diagonal-4-ref.html
 == linear-diagonal-4b.html linear-diagonal-4-ref.html
 == linear-diagonal-4c.html linear-diagonal-4-ref.html
 == linear-diagonal-5a.html linear-diagonal-5-ref.html
 == linear-diagonal-6a.html linear-diagonal-6-ref.html
 == linear-diagonal-7a.html linear-diagonal-7-ref.html
 == linear-diagonal-8a.html linear-diagonal-8-ref.html
 == linear-diagonal-9a.html linear-diagonal-9-ref.html
+fuzzy(1,800000) == linear-flipped-1.html linear-flipped-1-ref.html
 == linear-position-1a.html linear-position-1-ref.html
 == linear-repeat-1a.html linear-repeat-1-ref.html
 fails-if(d2d) == linear-repeat-1b.html linear-repeat-1-ref.html # bug 582236
 fails-if(d2d) == linear-repeat-1c.html linear-repeat-1-ref.html # bug 582236
 fails-if(d2d) == linear-repeat-1d.html linear-repeat-1-ref.html # bug 582236
 == linear-repeat-1e.html linear-repeat-1-ref.html
 fails-if(d2d) == linear-repeat-1f.html linear-repeat-1-ref.html # bug 582236
 fails-if(d2d) == linear-repeat-1g.html linear-repeat-1-ref.html # bug 582236
@@ -36,16 +37,17 @@ fails-if(d2d) == linear-repeat-1g.html l
 == linear-stops-1d.html linear-stops-1-ref.html
 == linear-stops-1e.html linear-stops-1-ref.html
 == linear-stops-1f.html linear-stops-1-ref.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1a.html linear-vertical-1-ref.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1b.html linear-vertical-1-ref.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1c.html linear-vertical-1-ref.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1d.html linear-vertical-1-ref.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,88500) fails-if(Android) == linear-vertical-1e.html linear-vertical-1-ref.html
+== linear-vertical-subpixel-1.html linear-vertical-subpixel-1-ref.html
 == linear-viewport.html linear-viewport-ref.html
 == linear-zero-length-1a.html linear-zero-length-1-ref.html
 == linear-zero-length-1b.html linear-zero-length-1-ref.html
 == linear-zero-length-1c.html linear-zero-length-1-ref.html
 == nostops.html about:blank
 == onestop.html about:blank
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fails-if(Android) random-if(d2d) == radial-1a.html radial-1-ref.html
 fuzzy-if(!contentSameGfxBackendAsCanvas,1,5884) fails-if(Android) random-if(d2d) == radial-1b.html radial-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/svg/crashtests/780963-1.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <script>
+
+function tweak() {
+  document.body.offsetTop;
+
+  var feImage = document.getElementsByTagName("feImage")[0];
+  feImage.setAttribute('filter', 'url(#f1)')
+  document.body.offsetTop;
+
+  var child = document.createElementNS('http://www.w3.org/2000/svg', 'g')
+  feImage.appendChild(child);
+}
+
+    </script>
+  </head>
+  <body onload="tweak()">
+    <svg xmlns="http://www.w3.org/2000/svg">
+      <filter filterUnits="userSpaceOnUse" id="f1">
+        <feImage/>
+      </filter>
+      <rect height="100" width="100"/>
+    </svg>
+  </body>
+</html>
--- a/layout/svg/crashtests/crashtests.list
+++ b/layout/svg/crashtests/crashtests.list
@@ -126,10 +126,11 @@ load 713413-1.svg
 load 722003-1.svg
 load 725918-1.svg
 load 732836-1.svg
 load 740627-1.svg
 load 740627-2.svg
 load 757704-1.svg
 load 757718-1.svg
 load 768351.svg
+load 780963-1.html
 load 757751-1.svg
 
--- a/mobile/android/base/GeckoInputConnection.java
+++ b/mobile/android/base/GeckoInputConnection.java
@@ -81,18 +81,18 @@ class GeckoInputConnection
     private static final char UNICODE_REGISTERED_SIGN           = '\u00ae';
     private static final char UNICODE_SQUARE_ROOT               = '\u221a';
     private static final char UNICODE_TRADEMARK_SIGN            = '\u2122';
     private static final char UNICODE_WHITE_BULLET              = '\u25e6';
     private static final char UNICODE_YEN_SIGN                  = '\u00a5';
 
     private static final Timer mIMETimer = new Timer("GeckoInputConnection Timer");
     private static int mIMEState;
-    private static String mIMETypeHint;
-    private static String mIMEActionHint;
+    private static String mIMETypeHint = "";
+    private static String mIMEActionHint = "";
 
     private String mCurrentInputMethod;
 
     // Is a composition active?
     private int mCompositionStart = NO_COMPOSITION_STRING;
     private boolean mCommittingText;
     private KeyCharacterMap mKeyCharacterMap;
     private final Editable mEditable;
@@ -107,18 +107,16 @@ class GeckoInputConnection
             return new GeckoInputConnection(targetView);
     }
 
     protected GeckoInputConnection(View targetView) {
         super(targetView, true);
         mEditable = Editable.Factory.getInstance().newEditable("");
         spanAndSelectEditable();
         mIMEState = IME_STATE_DISABLED;
-        mIMETypeHint = "";
-        mIMEActionHint = "";
     }
 
     @Override
     public boolean beginBatchEdit() {
         mBatchEditCount++;
         return true;
     }
 
@@ -814,18 +812,21 @@ class GeckoInputConnection
         else if (mIMEActionHint.equalsIgnoreCase("done"))
             outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE;
         else if (mIMEActionHint.equalsIgnoreCase("next"))
             outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT;
         else if (mIMEActionHint.equalsIgnoreCase("search"))
             outAttrs.imeOptions = EditorInfo.IME_ACTION_SEARCH;
         else if (mIMEActionHint.equalsIgnoreCase("send"))
             outAttrs.imeOptions = EditorInfo.IME_ACTION_SEND;
-        else if (mIMEActionHint != null && mIMEActionHint.length() != 0)
+        else if (mIMEActionHint.length() > 0) {
+            if (DEBUG)
+                Log.w(LOGTAG, "Unexpected mIMEActionHint=\"" + mIMEActionHint + "\"");
             outAttrs.actionLabel = mIMEActionHint;
+        }
 
         GeckoApp app = GeckoApp.mAppContext;
         DisplayMetrics metrics = app.getResources().getDisplayMetrics();
         if (Math.min(metrics.widthPixels, metrics.heightPixels) > INLINE_IME_MIN_DISPLAY_SIZE) {
             // prevent showing full-screen keyboard only when the screen is tall enough
             // to show some reasonable amount of the page (see bug 752709)
             outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_EXTRACT_UI
                                    | EditorInfo.IME_FLAG_NO_FULLSCREEN;
@@ -1027,33 +1028,39 @@ class GeckoInputConnection
                         if (DEBUG) Log.d(LOGTAG, ". . . notifyIME: cancel");
                         IMEStateUpdater.resetIME();
                         break;
 
                     case NOTIFY_IME_FOCUSCHANGE:
                         if (DEBUG) Log.d(LOGTAG, ". . . notifyIME: focus");
                         IMEStateUpdater.resetIME();
                         break;
+
+                    case NOTIFY_IME_SETOPENSTATE:
+                    default:
+                        if (DEBUG)
+                            throw new IllegalArgumentException("Unexpected NOTIFY_IME=" + type);
+                        break;
                 }
             }
         });
     }
 
     public void notifyIMEEnabled(final int state, final String typeHint, final String actionHint) {
         postToUiThread(new Runnable() {
             public void run() {
                 View v = getView();
                 if (v == null)
                     return;
 
                 /* When IME is 'disabled', IME processing is disabled.
                    In addition, the IME UI is hidden */
                 mIMEState = state;
-                mIMETypeHint = typeHint;
-                mIMEActionHint = actionHint;
+                mIMETypeHint = (typeHint == null) ? "" : typeHint;
+                mIMEActionHint = (actionHint == null) ? "" : actionHint;
                 IMEStateUpdater.enableIME();
             }
         });
     }
 
     public final void notifyIMEChange(final String text, final int start, final int end,
                                       final int newEnd) {
         postToUiThread(new Runnable() {
@@ -1437,15 +1444,25 @@ private static final class DebugGeckoInp
     public boolean onKeyLongPress(int keyCode, KeyEvent event) {
         Log.d(LOGTAG, "IME: onKeyLongPress(keyCode=" + keyCode + ", event=" + event + ")");
         GeckoApp.assertOnUiThread();
         return super.onKeyLongPress(keyCode, event);
     }
 
     @Override
     public void notifyIME(int type, int state) {
-        Log.d(LOGTAG, String.format("IME: >notifyIME(type=%d, state=%d)", type, state));
+        Log.d(LOGTAG, "IME: >notifyIME(type=" + type + ", state=" + state + ")");
         GeckoApp.assertOnGeckoThread();
         super.notifyIME(type, state);
     }
+
+    @Override
+    public void notifyIMEEnabled(int state, String typeHint, String actionHint) {
+        Log.d(LOGTAG, "IME: >notifyIMEEnabled(state=" + state + ", typeHint=\"" + typeHint
+                      + "\", actionHint=\"" + actionHint + "\"");
+        GeckoApp.assertOnGeckoThread();
+        if (state < IME_STATE_DISABLED || state > IME_STATE_PLUGIN)
+            throw new IllegalArgumentException("Unexpected IMEState=" + state);
+        super.notifyIMEEnabled(state, typeHint, actionHint);
+    }
 }
 
 }
--- a/mobile/android/base/sync/setup/SyncAccounts.java
+++ b/mobile/android/base/sync/setup/SyncAccounts.java
@@ -408,16 +408,24 @@ public class SyncAccounts {
     }
 
     String authority = BrowserContract.AUTHORITY;
     Logger.debug(LOG_TAG, "Setting authority " + authority + " to " +
                           (syncAutomatically ? "" : "not ") + "sync automatically.");
     ContentResolver.setSyncAutomatically(account, authority, syncAutomatically);
   }
 
+  public static void backgroundSetSyncAutomatically(final Account account, final boolean syncAutomatically) {
+    ThreadPool.run(new Runnable() {
+      @Override
+      public void run() {
+        setSyncAutomatically(account, syncAutomatically);
+      }
+    });
+  }
   /**
    * Bug 721760: try to start a vendor-specific Accounts & Sync activity on Moto
    * Blur devices.
    * <p>
    * Bug 773562: actually start and catch <code>ActivityNotFoundException</code>,
    * rather than just returning the <code>Intent</code> only, because some
    * Moto devices fail to start the activity.
    *
--- a/mobile/android/base/sync/syncadapter/SyncAdapter.java
+++ b/mobile/android/base/sync/syncadapter/SyncAdapter.java
@@ -83,16 +83,17 @@ public class SyncAdapter extends Abstrac
     }
     Editor edit = accountSharedPreferences.edit();
     edit.putLong(SyncConfiguration.PREF_EARLIEST_NEXT_SYNC, next);
     edit.commit();
   }
 
   /**
    * Handle an exception: update stats, invalidate auth token, log errors, etc.
+   * Wakes up sleeping threads by calling notifyMonitor().
    *
    * @param globalSession
    *          current global session, or null.
    * @param e
    *          Exception to handle.
    */
   protected void processException(final GlobalSession globalSession, final Exception e) {
     try {
@@ -159,20 +160,28 @@ public class SyncAdapter extends Abstrac
         return;
       }
 
       if (e instanceof CredentialException) {
         Logger.error(LOG_TAG, "Credentials attached to account were bad.");
         return;
       }
 
+      // Bug 755638 - Uncaught SecurityException when attempting to sync multiple Fennecs
+      // to the same Sync account.
+      // Uncheck Sync checkbox because we cannot sync this instance.
+      if (e instanceof SecurityException) {
+        Logger.error(LOG_TAG, "SecurityException, multiple Fennecs. Disabling this instance.", e);
+        SyncAccounts.backgroundSetSyncAutomatically(localAccount, false);
+        return;
+      }
       // Generic exception.
       Logger.error(LOG_TAG, "Unknown exception. Aborting sync.", e);
-    } catch (Exception ex) {
-      Logger.error(LOG_TAG, "Unknown exception. Aborting sync.", e);
+    } finally {
+      notifyMonitor();
     }
   }
 
   @Override
   public void onSyncCanceled() {
     super.onSyncCanceled();
     // TODO: cancel the sync!
     // From the docs: "This will be invoked on a separate thread than the sync
@@ -340,17 +349,16 @@ public class SyncAdapter extends Abstrac
             }
           }
 
           final String prefsPath = Utils.getPrefsPath(product, username, serverURL, profile, version);
           self.performSync(account, extras, authority, provider, syncResult,
               username, password, prefsPath, serverURL, syncKey);
         } catch (Exception e) {
           self.processException(null, e);
-          notifyMonitor();
           return;
         }
       }
     };
 
     synchronized (syncMonitor) {
       // Perform the work in a new thread from within this synchronized block,
       // which allows us to be waiting on the monitor before the callback can
@@ -474,17 +482,16 @@ public class SyncAdapter extends Abstrac
     }
   }
 
   // Implementing GlobalSession callbacks.
   @Override
   public void handleError(GlobalSession globalSession, Exception ex) {
     Logger.info(LOG_TAG, "GlobalSession indicated error.");
     this.processException(globalSession, ex);
-    notifyMonitor();
   }
 
   @Override
   public void handleAborted(GlobalSession globalSession, String reason) {
     Logger.warn(LOG_TAG, "Sync aborted: " + reason);
     notifyMonitor();
   }
 
--- a/netwerk/protocol/http/nsHttpTransaction.cpp
+++ b/netwerk/protocol/http/nsHttpTransaction.cpp
@@ -84,16 +84,17 @@ nsHttpTransaction::nsHttpTransaction()
     , mInvalidResponseBytesRead(0)
     , mChunkedDecoder(nullptr)
     , mStatus(NS_OK)
     , mPriority(0)
     , mRestartCount(0)
     , mCaps(0)
     , mClassification(CLASS_GENERAL)
     , mPipelinePosition(0)
+    , mHttpVersion(NS_HTTP_VERSION_UNKNOWN)
     , mClosed(false)
     , mConnected(false)
     , mHaveStatusLine(false)
     , mHaveAllHeaders(false)
     , mTransactionDone(false)
     , mResponseIsComplete(false)
     , mDidContentStart(false)
     , mNoContent(false)
@@ -1173,16 +1174,20 @@ nsHttpTransaction::HandleContentStart()
         if (LOG3_ENABLED()) {
             LOG3(("http response [\n"));
             nsCAutoString headers;
             mResponseHead->Flatten(headers, false);
             LogHeaders(headers.get());
             LOG3(("]\n"));
         }
 #endif
+        // Save http version, mResponseHead isn't available anymore after
+        // TakeResponseHead() is called
+        mHttpVersion = mResponseHead->Version();
+
         // notify the connection, give it a chance to cause a reset.
         bool reset = false;
         if (!mRestartInProgressVerifier.IsSetup())
             mConnection->OnHeadersAvailable(this, mRequestHead, mResponseHead, &reset);
 
         // looks like we should ignore this response, resetting...
         if (reset) {
             LOG(("resetting transaction's response head\n"));
@@ -1296,17 +1301,18 @@ nsHttpTransaction::HandleContent(char *b
         rv = mChunkedDecoder->HandleChunkedContent(buf, count, contentRead, contentRemaining);
         if (NS_FAILED(rv)) return rv;
     }
     else if (mContentLength >= PRInt64(0)) {
         // HTTP/1.0 servers have been known to send erroneous Content-Length
         // headers. So, unless the connection is persistent, we must make
         // allowances for a possibly invalid Content-Length header. Thus, if
         // NOT persistent, we simply accept everything in |buf|.
-        if (mConnection->IsPersistent() || mPreserveStream) {
+        if (mConnection->IsPersistent() || mPreserveStream ||
+            mHttpVersion >= NS_HTTP_VERSION_1_1) {
             PRInt64 remaining = mContentLength - mContentRead;
             *contentRead = PRUint32(NS_MIN<PRInt64>(count, remaining));
             *contentRemaining = count - *contentRead;
         }
         else {
             *contentRead = count;
             // mContentLength might need to be increased...
             PRInt64 position = mContentRead + PRInt64(count);
--- a/netwerk/protocol/http/nsHttpTransaction.h
+++ b/netwerk/protocol/http/nsHttpTransaction.h
@@ -172,16 +172,18 @@ private:
     PRInt16                         mPriority;
 
     PRUint16                        mRestartCount;        // the number of times this transaction has been restarted
     PRUint8                         mCaps;
     enum Classifier                 mClassification;
     PRInt32                         mPipelinePosition;
     PRInt64                         mMaxPipelineObjectSize;
 
+    nsHttpVersion                   mHttpVersion;
+
     // state flags, all logically boolean, but not packed together into a
     // bitfield so as to avoid bitfield-induced races.  See bug 560579.
     bool                            mClosed;
     bool                            mConnected;
     bool                            mHaveStatusLine;
     bool                            mHaveAllHeaders;
     bool                            mTransactionDone;
     bool                            mResponseIsComplete;
--- a/parser/html/nsHtml5Parser.cpp
+++ b/parser/html/nsHtml5Parser.cpp
@@ -582,17 +582,17 @@ nsHtml5Parser::IsScriptCreated()
 }
 
 /* End nsIParser  */
 
 // not from interface
 void
 nsHtml5Parser::ParseUntilBlocked()
 {
-  if (mBlocked || mExecutor->IsComplete() || mExecutor->IsBroken()) {
+  if (mBlocked || mExecutor->IsComplete() || NS_FAILED(mExecutor->IsBroken())) {
     return;
   }
   NS_ASSERTION(mExecutor->HasStarted(), "Bad life cycle.");
   NS_ASSERTION(!mInDocumentWrite,
     "ParseUntilBlocked entered while in doc.write!");
 
   mDocWriteSpeculatorActive = false;
 
--- a/parser/html/nsHtml5StreamParser.cpp
+++ b/parser/html/nsHtml5StreamParser.cpp
@@ -1407,17 +1407,17 @@ public:
 void
 nsHtml5StreamParser::ContinueAfterScripts(nsHtml5Tokenizer* aTokenizer, 
                                           nsHtml5TreeBuilder* aTreeBuilder,
                                           bool aLastWasCR)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!(mMode == VIEW_SOURCE_HTML || mMode == VIEW_SOURCE_XML),
       "ContinueAfterScripts called in view source mode!");
-  if (mExecutor->IsBroken()) {
+  if (NS_FAILED(mExecutor->IsBroken())) {
     return;
   }
   #ifdef DEBUG
     mExecutor->AssertStageEmpty();
   #endif
   bool speculationFailed = false;
   {
     mozilla::MutexAutoLock speculationAutoLock(mSpeculationMutex);
--- a/parser/html/nsHtml5TreeOpExecutor.cpp
+++ b/parser/html/nsHtml5TreeOpExecutor.cpp
@@ -141,17 +141,17 @@ nsHtml5TreeOpExecutor::DidBuildModel(boo
     return NS_OK;
   }
 
   GetParser()->DropStreamParser();
 
   // This comes from nsXMLContentSink and nsHTMLContentSink
   // If this parser has been marked as broken, treat the end of parse as
   // forced termination.
-  DidBuildModelImpl(aTerminated || IsBroken());
+  DidBuildModelImpl(aTerminated || NS_FAILED(IsBroken()));
 
   if (!mLayoutStarted) {
     // We never saw the body, and layout never got started. Force
     // layout *now*, to get an initial reflow.
 
     // NOTE: only force the layout if we are NOT destroying the
     // docshell. If we are destroying it, then starting layout will
     // likely cause us to crash, or at best waste a lot of time as we
@@ -475,17 +475,17 @@ nsHtml5TreeOpExecutor::RunFlushLoop()
 
   for (;;) {
     if (!mParser) {
       // Parse has terminated.
       mOpQueue.Clear(); // clear in order to be able to assert in destructor
       return;
     }
 
-    if (IsBroken()) {
+    if (NS_FAILED(IsBroken())) {
       return;
     }
 
     if (!mParser->IsParserEnabled()) {
       // The parser is blocked.
       return;
     }
   
@@ -931,17 +931,17 @@ nsHtml5TreeOpExecutor::Reset()
 {
   MOZ_ASSERT(mRunsToCompletion);
   DropHeldElements();
   mOpQueue.Clear();
   mStarted = false;
   mFlushState = eNotFlushing;
   mRunFlushLoopOnStack = false;
   MOZ_ASSERT(!mReadingFromStage);
-  MOZ_ASSERT(!mBroken);
+  MOZ_ASSERT(NS_SUCCEEDED(mBroken));
 }
 
 void
 nsHtml5TreeOpExecutor::DropHeldElements()
 {
   mScriptLoader = nullptr;
   mDocument = nullptr;
   mNodeInfoManager = nullptr;
--- a/testing/marionette/client/marionette/emulator.py
+++ b/testing/marionette/client/marionette/emulator.py
@@ -281,16 +281,17 @@ class Emulator(object):
 
         # setup DNS fix for networking
         self._run_adb(['-s', 'emulator-%d' % self.port,
                        'shell', 'setprop', 'net.dns1', '10.0.2.3'])
 
     def _save_logcat_proc(self, filename, cmd):
         self.logcat_proc = LogcatProc(filename, cmd)
         self.logcat_proc.run()
+        self.logcat_proc.processOutput()
         self.logcat_proc.waitForFinish()
         self.logcat_proc = None
 
     def rotate_log(self, srclog, index=1):
         """ Rotate a logfile, by recursively rotating logs further in the sequence,
             deleting the last file if necessary.
         """
         destlog = os.path.join(self.logcat_dir, 'emulator-%d.%d.log' % (self.port, index))
--- a/testing/marionette/client/marionette/runtests.py
+++ b/testing/marionette/client/marionette/runtests.py
@@ -9,17 +9,16 @@ import logging
 from optparse import OptionParser
 import os
 import types
 import unittest
 import socket
 import sys
 import time
 import platform
-import datazilla
 import xml.dom.minidom as dom
 
 try:
     from manifestparser import TestManifest
     from mozhttpd import iface, MozHttpd
 except ImportError:
     print "manifestparser or mozhttpd not found!  Please install mozbase:\n"
     print "\tgit clone git://github.com/mozilla/mozbase.git"
@@ -102,17 +101,18 @@ class MarionetteTextTestRunner(unittest.
         finally:
             stopTestRun = getattr(result, 'stopTestRun', None)
             if stopTestRun is not None:
                 stopTestRun()
         stopTime = time.time()
         timeTaken = stopTime - startTime
         result.printErrors()
         result.printLogs(test)
-        result.getPerfData(test)
+        if options.perf:
+            result.getPerfData(test)
         if hasattr(result, 'separator2'):
             self.stream.writeln(result.separator2)
         run = result.testsRun
         self.stream.writeln("Ran %d test%s in %.3fs" %
                             (run, run != 1 and "s" or "", timeTaken))
         self.stream.writeln()
 
         expectedFails = unexpectedSuccesses = skipped = 0
@@ -354,16 +354,17 @@ class MarionetteTestRunner(object):
                         testargs.update({ atype[1:]: 'true' })
                     elif atype.startswith('-'):
                         testargs.update({ atype[1:]: 'false' })
                     else:
                         testargs.update({ atype: 'true' })
 
             manifest = TestManifest()
             manifest.read(filepath)
+
             if options.perf:
                 if options.perfserv is None:
                     options.perfserv = manifest.get("perfserv")[0]
                 machine_name = socket.gethostname()
                 try:
                     manifest.has_key("machine_name")
                     machine_name = manifest.get("machine_name")[0]
                 except:
@@ -599,16 +600,19 @@ if __name__ == "__main__":
         parser.print_usage()
         print "must specify --binary, --emulator or --address"
         parser.exit()
 
     # default to storing logcat output for emulator runs
     if options.emulator and not options.logcat_dir:
         options.logcat_dir = 'logcat'
 
+    if options.perf:
+        import datazilla
+
     # check for valid resolution string, strip whitespaces
     try:
         dims = options.emulator_res.split('x')
         assert len(dims) == 2
         width = str(int(dims[0]))
         height = str(int(dims[1]))
         res = 'x'.join([width, height])
     except:
--- a/testing/marionette/client/setup.py
+++ b/testing/marionette/client/setup.py
@@ -6,17 +6,18 @@ version = '0.3'
 # get documentation from the README
 try:
     here = os.path.dirname(os.path.abspath(__file__))
     description = file(os.path.join(here, 'README.md')).read()
 except (OSError, IOError):
     description = ''
 
 # dependencies
-deps = ['manifestdestiny', 'mozhttpd >= 0.3', 'mozrunner', 'datazilla == 0.2.1']
+deps = ['manifestdestiny', 'mozhttpd >= 0.3',
+        'mozprocess == 0.5', 'mozrunner == 5.10', 'datazilla == 0.2.1']
 
 setup(name='marionette',
       version=version,
       description="Marionette test automation client",
       long_description=description,
       classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
       keywords='mozilla',
       author='Jonathan Griffin',
--- a/toolkit/components/telemetry/TelemetryPing.js
+++ b/toolkit/components/telemetry/TelemetryPing.js
@@ -22,16 +22,17 @@ const PREF_ENABLED = "toolkit.telemetry.
 // Do not gather data more than once a minute
 const TELEMETRY_INTERVAL = 60000;
 // Delay before intializing telemetry (ms)
 const TELEMETRY_DELAY = 60000;
 // Constants from prio.h for nsIFileOutputStream.init
 const PR_WRONLY = 0x2;
 const PR_CREATE_FILE = 0x8;
 const PR_TRUNCATE = 0x20;
+const PR_EXCL = 0x80;
 const RW_OWNER = 0600;
 const RWX_OWNER = 0700;
 
 // MEM_HISTOGRAMS lists the memory reporters we turn into histograms.
 //
 // Note that we currently handle only vanilla memory reporters, not memory
 // multi-reporters.
 //
@@ -806,34 +807,41 @@ TelemetryPing.prototype = {
       }
     }
     finally {
       entries.close();
     }
   },
 
   finishTelemetrySave: function finishTelemetrySave(ok, stream) {
-    stream.QueryInterface(Ci.nsISafeOutputStream).finish();
     stream.close();
     if (this._doLoadSaveNotifications && ok) {
       Services.obs.notifyObservers(null, "telemetry-test-save-complete", null);
     }
   },
 
-  savePingToFile: function savePingToFile(ping, file, sync) {
+  savePingToFile: function savePingToFile(ping, file, sync, overwrite) {
     let pingString = JSON.stringify(ping);
 
     let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
                     .createInstance(Ci.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
 
-    let ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"]
+    let ostream = Cc["@mozilla.org/network/file-output-stream;1"]
                   .createInstance(Ci.nsIFileOutputStream);
-    ostream.init(file, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
-                 RW_OWNER, ostream.DEFER_OPEN);
+    let initFlags = PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE;
+    if (!overwrite) {
+      initFlags |= PR_EXCL;
+    }
+    try {
+      ostream.init(file, initFlags, RW_OWNER, ostream.DEFER_OPEN);
+    } catch (e) {
+      // Probably due to PR_EXCL.
+      return;
+    }
 
     if (sync) {
       let utf8String = converter.ConvertFromUnicode(pingString);
       utf8String += converter.Finish();
       let amount = ostream.write(utf8String, utf8String.length);
       this.finishTelemetrySave(amount == utf8String.length, ostream);
     } else {
       let istream = converter.convertToInputStream(pingString)
@@ -881,29 +889,32 @@ TelemetryPing.prototype = {
     if (!('checksum' in ping)) {
       ping.checksum = this.hashString(ping.payload);
     }
     let file = this.ensurePingDirectory();
     file.append(ping.slug);
     return file;
   },
 
-  savePing: function savePing(ping) {
-    this.savePingToFile(ping, this.saveFileForPing(ping), true);
+  savePing: function savePing(ping, overwrite) {
+    this.savePingToFile(ping, this.saveFileForPing(ping), true, overwrite);
   },
 
   savePendingPings: function savePendingPings() {
-    this._pendingPings.push(this.getCurrentSessionPayloadAndSlug("saved-session"));
-    this._pendingPings.forEach(function sppcb(e, i, a) { this.savePing(e); }, this);
+    let sessionPing = this.getCurrentSessionPayloadAndSlug("saved-session");
+    this.savePing(sessionPing, true);
+    this._pendingPings.forEach(function sppcb(e, i, a) {
+                                 this.savePing(e, false);
+                               }, this);
     this._pendingPings = [];
   },
 
   saveHistograms: function saveHistograms(file, sync) {
     this.savePingToFile(this.getCurrentSessionPayloadAndSlug("saved-session"),
-                        file, sync);
+                        file, sync, true);
   },
 
   /** 
    * Remove observers to avoid leaks
    */
   uninstall: function uninstall() {
     this.detachObservers()
     if (this._hasWindowRestoredObserver) {
--- a/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_globalwarnings.js
@@ -11,43 +11,28 @@ function test() {
 
 function end_test() {
   finish();
 }
 
 add_test(function() {
   info("Testing compatibility checking warning");
 
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  }
-  catch (e) { }
-  if (channel != "aurora" &&
-      channel != "beta" &&
-      channel != "release") {
-    var version = "nightly";
-  }
-  else {
-    version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
-  }
-
-  var pref = "extensions.checkCompatibility." + version;
-  info("Setting " + pref + " pref to false")
-  Services.prefs.setBoolPref(pref, false);
+  info("Setting checkCompatibility to false");
+  AddonManager.checkCompatibility = false;
 
   open_manager("addons://list/extension", function(aWindow) {
     var hbox = aWindow.document.querySelector("#list-view hbox.global-warning-checkcompatibility");
     is_element_visible(hbox, "Check Compatibility warning hbox should be visible");
     var button = aWindow.document.querySelector("#list-view button.global-warning-checkcompatibility");
     is_element_visible(button, "Check Compatibility warning button should be visible");
 
     info("Clicking 'Enable' button");
     EventUtils.synthesizeMouse(button, 2, 2, { }, aWindow);
-    is(Services.prefs.prefHasUserValue(pref), false, "Check Compatibility pref should be cleared");
+    is(AddonManager.checkCompatibility, true, "Check Compatibility pref should be cleared");
     is_element_hidden(hbox, "Check Compatibility warning hbox should be hidden");
     is_element_hidden(button, "Check Compatibility warning button should be hidden");
 
     close_manager(aWindow, function() {
       run_next_test();
     });
   });
 });
--- a/toolkit/mozapps/extensions/test/browser/browser_searching.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_searching.js
@@ -14,32 +14,16 @@ const REMOTE_TO_INSTALL = "remote1";
 const REMOTE_INSTALL_URL = TESTROOT + "addons/browser_searching.xpi";
 
 var gManagerWindow;
 var gCategoryUtilities;
 var gProvider;
 var gServer;
 var gAddonInstalled = false;
 
-var channel = "default";
-try {
-  channel = Services.prefs.getCharPref("app.update.channel");
-}
-catch (e) { }
-if (channel != "aurora" &&
-    channel != "beta" &&
-    channel != "release") {
-  var version = "nightly";
-}
-else {
-  version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
-}
-
-const COMPATIBILITY_PREF = "extensions.checkCompatibility." + version;
-
 function test() {
   requestLongerTimeout(2);
   // Turn on searching for this test
   Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 15);
   Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true);
 
   waitForExplicitFinish();
 
@@ -598,26 +582,26 @@ add_test(function() {
       check_filtered_results(QUERY, "relevancescore", false);
       run_next_test();
     });
   });
 });
 
 // Tests that incompatible add-ons are shown with a warning if compatibility checking is disabled
 add_test(function() {
-  Services.prefs.setBoolPref(COMPATIBILITY_PREF, false);
+  AddonManager.checkCompatibility = false;
   search("incompatible", false, function() {
     var item = get_addon_item("remote5");
     is_element_visible(item, "Incompatible addon should be visible");
     is(item.getAttribute("notification"), "warning", "Compatibility warning should be shown");
 
-    var item = get_addon_item("remote6");
+    item = get_addon_item("remote6");
     is(item, null, "Addon incompatible with the product should not be visible");
 
-    Services.prefs.clearUserPref(COMPATIBILITY_PREF);
+    AddonManager.checkCompatibility = true;
     run_next_test();
   });
 });
 
 // Tests that compatible-by-default addons are shown if strict compatibility checking is disabled
 add_test(function() {
   restart_manager(gManagerWindow, null, function(aWindow) {
     gManagerWindow = aWindow;
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -21,16 +21,26 @@ Components.utils.import("resource://gre/
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
 
 var gInternalManager = null;
 var gAppInfo = null;
 var gAddonsList;
 
 var TEST_UNPACKED = false;
 
+function isNightlyChannel() {
+  var channel = "default";
+  try {
+    channel = Services.prefs.getCharPref("app.update.channel");
+  }
+  catch (e) { }
+
+  return channel != "aurora" && channel != "beta" && channel != "release" && channel != "esr";
+}
+
 function createAppInfo(id, name, version, platformVersion) {
   gAppInfo = {
     // nsIXULAppInfo
     vendor: "Mozilla",
     name: name,
     ID: id,
     version: version,
     appBuildID: "2007010101",
--- a/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_AddonRepository_compatmode.js
@@ -10,29 +10,16 @@ const PREF_GETADDONS_GETSEARCHRESULTS   
 Components.utils.import("resource://testing-common/httpd.js");
 var gServer;
 var COMPATIBILITY_PREF;
 
 function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  } catch (e) { }
-  if (channel != "aurora" &&
-      channel != "beta" &&
-      channel != "release") {
-    var version = "nightly";
-  } else {
-    version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
-  }
-  COMPATIBILITY_PREF = "extensions.checkCompatibility." + version;
-
   // Create and configure the HTTP server.
   gServer = new HttpServer();
   gServer.registerDirectory("/data/", do_get_file("data"));
   gServer.start(4444);
 
   Services.prefs.setCharPref(PREF_GETADDONS_GETSEARCHRESULTS,
                              "http://localhost:4444/data/test_AddonRepository_compatmode_%COMPATIBILITY_MODE%.xml");
   startupManager();
@@ -79,17 +66,17 @@ function run_test_2() {
       do_throw("Search should not have failed");
     }
   });
 }
 
 // Compatibility checking disabled.
 function run_test_3() {
   do_print("Testing with all compatibility checking disabled");
-  Services.prefs.setBoolPref(COMPATIBILITY_PREF, false);
+  AddonManager.checkCompatibility = false;
 
   AddonRepository.searchAddons("test", 6, {
     searchSucceeded: function(aAddons) {
       do_check_neq(aAddons, null);
       do_check_eq(aAddons.length, 1);
       do_check_eq(aAddons[0].id, "compatmode-ignore@tests.mozilla.org");
 
       end_test();
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_2.js
@@ -1,30 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 // Disables security checking our updates which haven't been signed
 Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
-// Disables compatibility checking
-var channel = "default";
-try {
-  channel = Services.prefs.getCharPref("app.update.channel");
-}
-catch (e) { }
 
-if (channel != "aurora" &&
-    channel != "beta" &&
-    channel != "release") {
-  Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false);
-}
-else {
-  Services.prefs.setBoolPref("extensions.checkCompatibility.2", false);
-}
+AddonManager.checkCompatibility = false;
 
 var ADDONS = [
   "test_bug470377_1",
   "test_bug470377_2",
   "test_bug470377_3",
   "test_bug470377_4",
   "test_bug470377_5",
 ];
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js
@@ -64,31 +64,18 @@ function run_test_1() {
     do_check_neq(a5, null);
     do_check_true(a5.isActive);
 
     run_test_2();
   });
 }
 
 function run_test_2() {
-  // Disable compatibility checks
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  }
-  catch (e) { }
+  AddonManager.checkCompatibility = false;
 
-  if (channel != "aurora" &&
-      channel != "beta" &&
-      channel != "release") {
-    Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false);
-  }
-  else {
-    Services.prefs.setBoolPref("extensions.checkCompatibility.2.2", false);
-  }
   restartManager();
 
   AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org",
                                "bug470377_2@tests.mozilla.org",
                                "bug470377_3@tests.mozilla.org",
                                "bug470377_4@tests.mozilla.org",
                                "bug470377_5@tests.mozilla.org"],
                                function([a1, a2, a3, a4, a5]) {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js
@@ -63,31 +63,18 @@ function run_test_1() {
     do_check_neq(a5, null);
     do_check_true(a5.isActive);
 
     run_test_2();
   });
 }
 
 function run_test_2() {
-  // Disable compatibility checks
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  }
-  catch (e) { }
+  AddonManager.checkCompatibility = false;
 
-  if (channel != "aurora" &&
-      channel != "beta" &&
-      channel != "release") {
-    Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false);
-  }
-  else {
-    Services.prefs.setBoolPref("extensions.checkCompatibility.2.2", false);
-  }
   restartManager();
 
   AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org",
                                "bug470377_2@tests.mozilla.org",
                                "bug470377_3@tests.mozilla.org",
                                "bug470377_4@tests.mozilla.org",
                                "bug470377_5@tests.mozilla.org"],
                                function([a1, a2, a3, a4, a5]) {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js
@@ -1,28 +1,13 @@
 /* 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/.
  */
 
-var channel = "default";
-try {
-  channel = Services.prefs.getCharPref("app.update.channel");
-}
-catch (e) { }
-
-if (channel != "aurora" &&
-    channel != "beta" &&
-    channel != "release") {
-  var checkCompatPref = "extensions.checkCompatibility.nightly";
-}
-else {
-  checkCompatPref = "extensions.checkCompatibility.2.1a";
-}
-
 function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.1a4", "2");
 
   // inject the add-ons into the profile
   var profileDir = gProfD.clone();
   profileDir.append("extensions");
   var dest = profileDir.clone();
@@ -50,18 +35,18 @@ function run_test() {
   dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
   source = do_get_file("data/test_bug470377/install_5.rdf");
   source.copyTo(dest, "install.rdf");
 
   run_test_1();
 }
 
 function run_test_1() {
-  // Disable compatibility checks
-  Services.prefs.setBoolPref(checkCompatPref, false);
+  AddonManager.checkCompatibility = false;
+
   startupManager();
 
   AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org",
                                "bug470377_2@tests.mozilla.org",
                                "bug470377_3@tests.mozilla.org",
                                "bug470377_4@tests.mozilla.org",
                                "bug470377_5@tests.mozilla.org"],
                                function([a1, a2, a3, a4, a5]) {
@@ -76,18 +61,18 @@ function run_test_1() {
     do_check_neq(a5, null);
     do_check_true(a5.isActive);
 
     run_test_2();
   });
 }
 
 function run_test_2() {
-  // Enable compatibility checks
-  Services.prefs.setBoolPref(checkCompatPref, true);
+  AddonManager.checkCompatibility = true;
+
   restartManager();
 
   AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org",
                                "bug470377_2@tests.mozilla.org",
                                "bug470377_3@tests.mozilla.org",
                                "bug470377_4@tests.mozilla.org",
                                "bug470377_5@tests.mozilla.org"],
                                function([a1, a2, a3, a4, a5]) {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug521905.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug521905.js
@@ -3,31 +3,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
 const ADDON = "test_bug521905";
 const ID = "bug521905@tests.mozilla.org";
 
 // Disables security checking our updates which haven't been signed
 Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
-// Disables compatibility checking
-Services.prefs.setBoolPref("extensions.checkCompatibility.2.0pre", false);
+AddonManager.checkCompatibility = false;
 
 function run_test() {
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  }
-  catch (e) { }
-
   // This test is only relevant on builds where the version is included in the
   // checkCompatibility preference name
-  if (channel != "aurora" &&
-      channel != "beta" &&
-      channel != "release") {
+  if (isNightlyChannel()) {
     return;
   }
 
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.0pre", "2");
 
   startupManager();
   installAllFiles([do_get_addon(ADDON)], function() {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_checkcompatibility.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_checkcompatibility.js
@@ -64,25 +64,17 @@ var gIsNightly = false;
 function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.2.3", "2");
 
   ADDONS.forEach(function(a) {
     writeInstallRDFForExtension(a, profileDir);
   });
 
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  }
-  catch (e) { }
-
-  gIsNightly = channel != "aurora" &&
-               channel != "beta" &&
-               channel != "release";
+  gIsNightly = isNightlyChannel();
 
   startupManager();
 
   run_test_1();
 }
 
 /**
  * Checks that the add-ons are enabled as expected.
--- a/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_pref_properties.js
@@ -123,23 +123,17 @@ function run_test() {
   gManagerEventsListener.expect([]);
   AddonManager.strictCompatibility = true;
   gManagerEventsListener.checkExpected();
   do_check_true(AddonManager.strictCompatibility);
   do_check_true(Services.prefs.getBoolPref("extensions.strictCompatibility"));
 
 
   // AddonManager.checkCompatibility
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  } catch (e) { }
-  if (channel != "aurora" &&
-      channel != "beta" &&
-      channel != "release") {
+  if (isNightlyChannel()) {
     var version = "nightly";
   } else {
     version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
   }
   const COMPATIBILITY_PREF = "extensions.checkCompatibility." + version;
 
   gManagerEventsListener.expect(["onCompatibilityModeChanged"]);
   AddonManager.checkCompatibility = false;
--- a/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js
@@ -9,35 +9,20 @@
 // The test extension uses an insecure update url.
 Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
 
 Components.utils.import("resource://testing-common/httpd.js");
 var testserver;
 const profileDir = gProfD.clone();
 profileDir.append("extensions");
 
-var COMPATIBILITY_PREF;
-
 function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
   
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  } catch (e) { }
-  if (channel != "aurora" &&
-      channel != "beta" &&
-      channel != "release") {
-    var version = "nightly";
-  } else {
-    version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
-  }
-  COMPATIBILITY_PREF = "extensions.checkCompatibility." + version;
-
   // Create and configure the HTTP server.
   testserver = new HttpServer();
   testserver.registerDirectory("/data/", do_get_file("data"));
   testserver.registerDirectory("/addons/", do_get_file("addons"));
   testserver.start(4444);
 
   writeInstallRDFForExtension({
     id: "compatmode-normal@tests.mozilla.org",
@@ -169,17 +154,17 @@ function run_test_3() {
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
 
 // Compatibility checking disabled.
 function run_test_4() {
   do_print("Testing with all compatibility checking disabled");
-  Services.prefs.setBoolPref(COMPATIBILITY_PREF, false);
+  AddonManager.checkCompatibility = false;
   AddonManager.getAddonByID("compatmode-ignore@tests.mozilla.org", function(addon) {
     do_check_neq(addon, null);
     addon.findUpdates({
       onCompatibilityUpdateAvailable: function() {
         do_throw("Should have not have seen compatibility information");
       },
 
       onNoUpdateAvailable: function() {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js
@@ -1,34 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // This verifies that AddonUpdateChecker works correctly
 
 Components.utils.import("resource://gre/modules/AddonUpdateChecker.jsm");
 
-var COMPATIBILITY_PREF;
-
 Components.utils.import("resource://testing-common/httpd.js");
 var testserver;
 
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
-  var channel = "default";
-  try {
-    channel = Services.prefs.getCharPref("app.update.channel");
-  } catch (e) { }
-  if (channel != "aurora" && channel != "beta" && channel != "release")
-    var version = "nightly";
-  else
-    version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
-  COMPATIBILITY_PREF = "extensions.checkCompatibility." + version;
-
   // Create and configure the HTTP server.
   testserver = new HttpServer();
   testserver.registerDirectory("/data/", do_get_file("data"));
   testserver.start(4444);
 
   do_test_pending();
   run_test_1();
 }
--- a/widget/qt/Makefile.in
+++ b/widget/qt/Makefile.in
@@ -49,16 +49,17 @@ CPPSRCS	+= \
 		mozqwidget.cpp \
 		mozSwipeGesture.cpp \
 		nsSound.cpp \
 		nsFilePicker.cpp \
 		nsPrintOptionsQt.cpp \
 		nsPrintSettingsQt.cpp \
 		nsPrintDialogQt.cpp \
 		nsDeviceContextSpecQt.cpp \
+		mozqglwidgetwrapper.cpp \
 		$(NULL)
 
 EXPORTS		= \
 		nsQtKeyUtils.h \
 		$(NULL)
 
 ifdef MOZ_ENABLE_QTMOBILITY
 MOCSRCS += moc_mozqorientationsensorfilter.cpp
--- a/widget/qt/faststartupqt/Makefile.in
+++ b/widget/qt/faststartupqt/Makefile.in
@@ -16,20 +16,30 @@ FORCE_STATIC_LIB = 1
 STL_FLAGS=
 
 EXTRA_DSO_LDOPTS = \
 	$(XPCOM_GLUE_LDOPTS) \
 	$(XPCOM_FROZEN_LDOPTS) \
 	$(MOZ_QT_LIBS) \
 	$(NULL)
 
-LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build
+LOCAL_INCLUDES += \
+	-I$(topsrcdir)/xpcom/build \
+	-I$(topsrcdir)/widget/qt \
+	$(NULL)
 
-GARBAGE += moziqwidget.h nsQAppInstance.h nsQAppInstance.cpp
-export:: $(topsrcdir)/widget/qt/moziqwidget.h $(topsrcdir)/toolkit/xre/nsQAppInstance.h $(topsrcdir)/toolkit/xre/nsQAppInstance.cpp
+EXPORT_SOURCES = \
+	$(topsrcdir)/widget/qt/moziqwidget.h \
+	$(topsrcdir)/toolkit/xre/nsQAppInstance.h \
+	$(topsrcdir)/toolkit/xre/nsQAppInstance.cpp \
+	$(topsrcdir)/widget/qt/mozqglwidgetwrapper.h \
+	$(topsrcdir)/widget/qt/mozqglwidgetwrapper.cpp
+
+GARBAGE += $(EXPORT_SOURCES)
+export:: $(EXPORT_SOURCES)
 	$(INSTALL) $^ .
 
 MOCSRCS = \
 	moc_moziqwidget.cpp \
 	moc_nsFastStartupQt.cpp \
 	$(NULL)
 
 LOCAL_INCLUDES += \
--- a/widget/qt/moziqwidget.h
+++ b/widget/qt/moziqwidget.h
@@ -5,17 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZIQWIDGET_H
 #define MOZIQWIDGET_H
 
 #include <QApplication>
 #include <QGraphicsWidget>
 #include <QGraphicsView>
-#include <QtOpenGL/QGLWidget>
+#include "mozqglwidgetwrapper.h"
 
 #include "nsCOMPtr.h"
 
 #ifdef MOZ_ENABLE_MEEGOTOUCH
 #include <MSceneWindow>
 #include <MInputMethodState>
 #include <QtGui/QGraphicsSceneResizeEvent>
 #include <QTimer>
@@ -129,18 +129,18 @@ public:
     {
         scene()->addItem(aTopLevel);
         mTopLevelWidget = aTopLevel;
     }
 
     void setGLWidgetEnabled(bool aEnabled)
     {
         if (aEnabled) {
-            mGLWidget = new QGLWidget();
-            setViewport(mGLWidget);
+            mGLWidget = new MozQGLWidgetWrapper();
+            mGLWidget->setViewport(this);
         } else {
             delete mGLWidget;
             mGLWidget = 0;
             setViewport(new QWidget());
         }
     }
 
 protected:
@@ -169,17 +169,17 @@ protected:
             mGLWidget->makeCurrent();
         }
         QGraphicsView::paintEvent(aEvent);
     }
 
 private:
     MozQGraphicsViewEvents mEventHandler;
     IMozQWidget* mTopLevelWidget;
-    QGLWidget* mGLWidget;
+    MozQGLWidgetWrapper* mGLWidget;
 };
 
 #ifdef MOZ_ENABLE_MEEGOTOUCH
 class MozMSceneWindow : public MSceneWindow
 {
     Q_OBJECT
 public:
     MozMSceneWindow(IMozQWidget* aTopLevel)
new file mode 100644
--- /dev/null
+++ b/widget/qt/mozqglwidgetwrapper.cpp
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 et sw=4 tw=80: */
+/* 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 "mozqglwidgetwrapper.h"
+#include <QGraphicsView>
+#include <QtOpenGL/QGLWidget>
+#include <QtOpenGL/QGLContext>
+
+MozQGLWidgetWrapper::MozQGLWidgetWrapper()
+  : mWidget(new QGLWidget())
+{
+}
+
+MozQGLWidgetWrapper::~MozQGLWidgetWrapper()
+{
+    delete mWidget;
+}
+
+void MozQGLWidgetWrapper::makeCurrent()
+{
+    mWidget->makeCurrent();
+}
+
+void MozQGLWidgetWrapper::setViewport(QGraphicsView* aView)
+{
+    aView->setViewport(mWidget);
+}
+
+bool MozQGLWidgetWrapper::hasGLContext(QGraphicsView* aView)
+{
+    return aView && qobject_cast<QGLWidget*>(aView->viewport());
+}
+
+bool MozQGLWidgetWrapper::isRGBAContext()
+{
+    QGLContext* context = const_cast<QGLContext*>(QGLContext::currentContext());
+    return context && context->format().alpha();
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/widget/qt/mozqglwidgetwrapper.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* vim: set ts=4 et sw=4 tw=80: */
+/* 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 MOZQGLWIDGETWRAPPER_H
+#define MOZQGLWIDGETWRAPPER_H
+
+/*
+ * qgl.h and GLDefs.h has conflicts in type defines
+ * QGLWidget wrapper class helps to avoid including qgl.h with mozilla gl includes
+ */
+
+class QGLWidget;
+class QGraphicsView;
+class MozQGLWidgetWrapper
+{
+public:
+    MozQGLWidgetWrapper();
+    ~MozQGLWidgetWrapper();
+    void makeCurrent();
+    void setViewport(QGraphicsView*);
+    static bool hasGLContext(QGraphicsView*);
+    static bool isRGBAContext();
+private:
+    QGLWidget* mWidget;
+};
+
+#endif
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -1,37 +1,33 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* vim:expandtab:shiftwidth=4:tabstop=4:
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Util.h"
-#include "BasicLayers.h"
-
-#include <QtOpenGL/QGLWidget>
-#include <QtOpenGL/QGLContext>
-// Solve conflict of qgl.h and GLDefs.h
-#define GLdouble_defined 1
+
 #include <QApplication>
 #include <QDesktopWidget>
 #include <QtGui/QCursor>
 #include <QIcon>
 #include <QGraphicsScene>
 #include <QGraphicsView>
 #include <QGraphicsSceneContextMenuEvent>
 #include <QGraphicsSceneDragDropEvent>
 #include <QGraphicsSceneMouseEvent>
 #include <QGraphicsSceneHoverEvent>
 #include <QGraphicsSceneWheelEvent>
 #include <QGraphicsSceneResizeEvent>
 #include <QStyleOptionGraphicsItem>
 #include <QPaintEngine>
 #include <QMimeData>
+#include "mozqglwidgetwrapper.h"
 
 #include <QtCore/QDebug>
 #include <QtCore/QEvent>
 #include <QtCore/QVariant>
 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
 #include <QPinchGesture>
 #include <QGestureRecognizer>
 #include "mozSwipeGesture.h"
@@ -101,16 +97,17 @@ using namespace QtMobility;
 #include <X11/Xatom.h>
 static Atom sPluginIMEAtom = nullptr;
 #define PLUGIN_VKB_REQUEST_PROP "_NPAPI_PLUGIN_REQUEST_VKB"
 #include <QThread>
 #endif
 #endif //MOZ_X11
 
 #include "Layers.h"
+#include "BasicLayers.h"
 #include "LayerManagerOGL.h"
 #include "nsFastStartupQt.h"
 
 // If embedding clients want to create widget without real parent window
 // then nsIBaseWindow->Init() should have parent argument equal to PARENTLESS_WIDGET
 #define PARENTLESS_WIDGET (void*)0x13579
 
 #include "nsShmImage.h"
@@ -2576,18 +2573,17 @@ nsPopupWindow::nsPopupWindow()
 
 nsPopupWindow::~nsPopupWindow()
 {
 }
 
 NS_IMETHODIMP_(bool)
 nsWindow::HasGLContext()
 {
-    QGraphicsView *view = qobject_cast<QGraphicsView*>(GetViewWidget());
-    return view && qobject_cast<QGLWidget*>(view->viewport());
+    return MozQGLWidgetWrapper::hasGLContext(qobject_cast<QGraphicsView*>(GetViewWidget()));
 }
 
 MozQWidget*
 nsWindow::createQWidget(MozQWidget *parent,
                         nsNativeWidget nativeParent,
                         nsWidgetInitData *aInitData)
 {
     const char *windowName = NULL;
@@ -3267,18 +3263,13 @@ nsWindow::UserActivity()
   }
 }
 
 PRUint32
 nsWindow::GetGLFrameBufferFormat()
 {
     if (mLayerManager &&
         mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
-        // On maemo the hardware fb has RGB format.
-#ifdef MOZ_PLATFORM_MAEMO
-        return LOCAL_GL_RGB;
-#else
-        return LOCAL_GL_RGBA;
-#endif
+        return MozQGLWidgetWrapper::isRGBAContext() ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
     }
     return LOCAL_GL_NONE;
 }
 
--- a/widget/reftests/reftest.list
+++ b/widget/reftests/reftest.list
@@ -1,6 +1,6 @@
 skip-if(!cocoaWidget) != 507947.html about:blank
 == progressbar-fallback-default-style.html progressbar-fallback-default-style-ref.html
-== meter-native-style.html meter-native-style-ref.html
-skip-if(!cocoaWidget) == meter-vertical-native-style.html meter-vertical-native-style-ref.html
+fuzzy-if(Android,17,1120) == meter-native-style.html meter-native-style-ref.html
+skip-if(!cocoaWidget) == meter-vertical-native-style.html meter-vertical-native-style-ref.html # dithering
 == meter-fallback-default-style.html meter-fallback-default-style-ref.html
 load 664925.xhtml